android - studio - startactivityforresult activity to fragment




onActivityResult()가 새 중첩 프래그먼트 API에서 호출되지 않았습니다. (5)

FragmentActivity 소스를 검색했습니다.이 사실을 발견했습니다.

  1. 조각 호출 startActivityForResult ()가 실제로 부모 FragmentActivity의 startAcitivityFromFragment ()를 호출합니다.
  2. 결과에 대한 조각 시작 활동이있는 경우 requestCode는 65536 (16 비트) 미만이어야합니다.
  3. FragmentActivity의 startActivityFromFragment ()에서 Activity.startActivityForResult ()를 호출하면이 함수도 requestCode가 필요하지만이 requestCode는 origin requestCode와 같지 않습니다.
  4. 실제로 FragmentActivity의 requestCode에는 두 부분이 있습니다. 더 높은 16 비트 값은 (FragmentManager의 프래그먼트 색인) +1입니다. 하위 16 비트는 원점 requestCode와 같습니다. 이것이 바로 requestCode가 65536 미만이어야하는 이유입니다.

FragmentActivity에서 코드를 봅니다.

public void startActivityFromFragment(Fragment fragment, Intent intent,
        int requestCode) {
    if (requestCode == -1) {
        super.startActivityForResult(intent, -1);
        return;
    }
    if ((requestCode&0xffff0000) != 0) {
        throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
    }
    super.startActivityForResult(intent, ((fragment.mIndex+1)<<16) + (requestCode&0xffff));
}

결과 back.FragmentActivity가 onActivityResult 함수를 재정의하고 onActivityResult를 그의 자식 조각에 전달하는 것보다 requestCode의 상위 16 비트가 0이 아닌지 확인합니다.

    @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    mFragments.noteStateNotSaved();
    int index = requestCode>>16;
    if (index != 0) {
        index--;
        final int activeFragmentsCount = mFragments.getActiveFragmentsCount();
        if (activeFragmentsCount == 0 || index < 0 || index >= activeFragmentsCount) {
            Log.w(TAG, "Activity result fragment index out of range: 0x"
                    + Integer.toHexString(requestCode));
            return;
        }
        final List<Fragment> activeFragments =
                mFragments.getActiveFragments(new ArrayList<Fragment>(activeFragmentsCount));
        Fragment frag = activeFragments.get(index);
        if (frag == null) {
            Log.w(TAG, "Activity result no fragment exists for index: 0x"
                    + Integer.toHexString(requestCode));
        } else {
            frag.onActivityResult(requestCode&0xffff, resultCode, data);
        }
        return;
    }

    super.onActivityResult(requestCode, resultCode, data);
}

그래서 이것이 FragmentActivity가 onActivityResult 이벤트를 전달하는 방법입니다.

fragmentActivity가 있으면 fragment1이 포함되고 fragment1에는 fragment2가 포함됩니다. 따라서 onActivityResult는 단편 1에만 전달할 수 있습니다.

그리고 나는이 문제를 해결할 방법을 찾는다. 먼저 NestedFragment extends Fragment를 작성하여 startActivityForResult 함수를 대체하십시오.

public abstract class NestedFragment extends Fragment {

@Override
public void startActivityForResult(Intent intent, int requestCode) {

    List<Fragment> fragments = getFragmentManager().getFragments();
    int index = fragments.indexOf(this);
    if (index >= 0) {
        if (getParentFragment() != null) {
            requestCode = ((index + 1) << 8) + requestCode;
            getParentFragment().startActivityForResult(intent, requestCode);
        } else {
            super.startActivityForResult(intent, requestCode);
        }

    }
}

}

Create MyFragment extends onActivityResult 함수를 오버라이드 (override)합니다.

public abstract class MyFragment extends Fragment {

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    int index = requestCode >> 8;
    if (index > 0) {
        //from nested fragment
        index--;

        List<Fragment> fragments = getChildFragmentManager().getFragments();
        if (fragments != null && fragments.size() > index) {
            fragments.get(index).onActivityResult(requestCode & 0x00ff, resultCode, data);
        }
    }
}

}

그게 다야! 용법:

  1. fragment1은 MyFragment를 확장합니다.
  2. fragment2는 NestedFragment를 확장합니다.
  3. 더 이상 다르지 않습니다. fragment2에서 startActivityForResult ()를 호출하고 onActivityResult () 함수를 재정의하십시오.

와 링 !!!!!!!! 우리가 3 부분에 requestCode를 쏟았 기 때문에 requestCode는 512 (8 비트) 이하 여야합니다.

16 비트 | 8 비트 | 8 비트

더 높은 16 비트 안드로이드가 이미 사용 된 가운데 8 비트는 fragment1이 fragmentManager 배열에서 fragment2를 찾도록 돕는 것입니다. 가장 낮은 8 비트가 origin requestCode입니다.

필자는 Android가 지원 라이브러리에 포함하는 새로운 중첩 조각 API를 사용하고 있습니다.

중첩 된 단편에서 직면하는 문제는 중첩 된 단편 (즉, getChildFragmentManager() 의해 반환 된 FragmentManager 를 통해 다른 단편에 추가 된 단편)이 startActivityForResult() 호출하면 중첩 된 단편의 onActivityResult() 메소드 호출되지 않습니다. 그러나 부모 프래그먼트의 onActivityResult() 및 activity의 onActivityResult() 가 호출됩니다.

중첩 된 조각에 대해 뭔가 빠졌는지 모르겠지만 설명 된 동작은 기대하지 않았습니다. 이 문제를 재현하는 코드는 다음과 같습니다. 나는 누군가가 올바른 방향으로 나를 가리키고 내가 잘못하고있는 것을 나에게 설명 할 수 있다면 매우 감사 할 것이다.

package com.example.nestedfragmentactivityresult;

import android.media.RingtoneManager;
import android.os.Bundle;
import android.content.Intent;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends FragmentActivity
{
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        this.getSupportFragmentManager()
            .beginTransaction()
            .add(android.R.id.content, new ContainerFragment())
            .commit();
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);

        // This is called
        Toast.makeText(getApplication(),
            "Consumed by activity",
            Toast.LENGTH_SHORT).show();
    }

    public static class ContainerFragment extends Fragment
    {
        public final View onCreateView(LayoutInflater inflater,
                                       ViewGroup container,
                                       Bundle savedInstanceState)
        {
            View result = inflater.inflate(R.layout.test_nested_fragment_container,
                container,
                false);

            return result;
        }

        public void onActivityCreated(Bundle savedInstanceState)
        {
            super.onActivityCreated(savedInstanceState);
            getChildFragmentManager().beginTransaction()
                .add(R.id.content, new NestedFragment())
                .commit();
        }

        public void onActivityResult(int requestCode,
                                     int resultCode,
                                     Intent data)
        {
            super.onActivityResult(requestCode, resultCode, data);

            // This is called
            Toast.makeText(getActivity(),
                "Consumed by parent fragment",
                Toast.LENGTH_SHORT).show();
        }
    }

    public static class NestedFragment extends Fragment
    {
        public final View onCreateView(LayoutInflater inflater,
                                       ViewGroup container,
                                       Bundle savedInstanceState)
        {
            Button button = new Button(getActivity());
            button.setText("Click me!");
            button.setOnClickListener(new View.OnClickListener()
            {
                public void onClick(View v)
                {
                    Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
                    startActivityForResult(intent, 0);
                }
            });

            return button;
        }

        public void onActivityResult(int requestCode,
                                     int resultCode,
                                     Intent data)
        {
            super.onActivityResult(requestCode, resultCode, data);

            // This is NOT called
            Toast.makeText(getActivity(),
                "Consumed by nested fragment",
                Toast.LENGTH_SHORT).show();
        }
    }
}

test_nested_fragment_container.xml은 다음과 같습니다.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/content"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

</FrameLayout>

나는 똑같은 문제에 직면했다! ParentFragment 에서 정적 ChildFragment 를 사용하여 ParentFragment 과 같이 해결했습니다.

private static ChildFragment mChildFragment;

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    mChildFragment.onActivityResult(int requestCode, int resultCode, Intent data);

}

여기 내가 어떻게 해결 했는가.

활동 내 :

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    List<Fragment> frags = getSupportFragmentManager().getFragments();
    if (frags != null) {
        for (Fragment f : frags) {
            if (f != null)
                handleResult(f, requestCode, resultCode, data);
        }
    }
}

private void handleResult(Fragment frag, int requestCode, int resultCode, Intent data) {
    if (frag instanceof IHandleActivityResult) { // custom interface with no signitures
        frag.onActivityResult(requestCode, resultCode, data);
    }
    List<Fragment> frags = frag.getChildFragmentManager().getFragments();
    if (frags != null) {
        for (Fragment f : frags) {
            if (f != null)
                handleResult(f, requestCode, resultCode, data);
        }
    }
}

예, 중첩 된 단편에서 onActivityResult() 는이 방식으로 호출되지 않습니다.

onActivityResult (Android 지원 라이브러리)의 호출 순서는 다음과 같습니다.

  1. Activity.dispatchActivityResult() .
  2. FragmentActivity.onActivityResult() .
  3. Fragment.onActivityResult() .

세 번째 단계에서 프래그먼트는 부모 ActivityFragmentMananger 에 있습니다. 따라서 귀하의 예에서는 onActivityResult() 를 전달하기 위해 발견 된 컨테이너 단편입니다. 중첩 된 단편은 결코 이벤트를 수신 할 수 없습니다.

난 당신이 ContainerFragment.onActivityResult() 에서 자신의 파견을 구현해야한다고 생각, 중첩 조각을 찾아 호출 결과와 데이터를 전달합니다.


주 활동의 경우 OnActivityForResult와 같이 Super 클래스로 작성합니다.

  @Override
public void onActivityResult(int requestCode, int resultCode, Intent result) {
    super.onActivityResult(requestCode, resultCode, result);
    if (requestCode == Crop.REQUEST_PICK && resultCode == RESULT_OK) {
        beginCrop(result.getData());
    } }

액티비티의 경우 getActivity ()없이 int로 작성

 Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts"));
        pickContactIntent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers
       startActivityForResult(pickContactIntent, 103);

조각에 대한 OnActivityResult

   @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == 101 && resultCode == getActivity().RESULT_OK && null != data) {

}}







android-nested-fragment