77 votes

onActivityResult () non appelé dans la nouvelle API de fragment imbriqué

J'ai été en utilisant le nouveau imbriquée fragment API Android inclut dans la bibliothèque de prise en charge.

Le problème que je suis confronté avec imbriqué fragments, c'est que, si imbriquée fragment (qui est, un fragment qui a été ajouté à un autre fragment via l' FragmentManagerretournée par getChildFragmentManager()) des appels startActivityForResult(), imbriquée du fragment onActivityResult() méthode n'est pas appelée. Toutefois, la société mère du fragment onActivityResult() et l'activité de l' onActivityResult() n'appelée.

Je ne sais pas si je suis absent quelque chose à propos de imbriquée des fragments, mais je ne m'attendais pas le comportement décrit. Ci-dessous est le code qui reproduit ce problème. Je serais très heureux si quelqu'un peut me pointer dans la bonne direction et m'expliquer ce que je fais de mal:

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 est:

<?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>

145voto

pvshnik Points 503

J'ai résolu ce problème avec le code suivant (bibliothèque de prise en charge est utilisé):

Dans un récipient fragment de remplacer onActivityResult de cette façon:

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

        List<Fragment> fragments = getChildFragmentManager().getFragments();
        if (fragments != null) {
            for (Fragment fragment : fragments) {
                fragment.onActivityResult(requestCode, resultCode, data);
            }
        }
    }

Imbriqués fragment recevrez appel à la méthode onActivityResult.

Aussi, comme l' a noté Eric Brynsvold en question similaire, imbriqués fragment devrait commencer l'activité à l'aide de c'est parent fragment et non pas dans le simple startActivityForResult (). Ainsi, dans les fragment de démarrer l'activité avec:

getParentFragment().startActivityForResult(intent, requestCode);

58voto

faylon Points 3497

Oui, le onActivityResult() dans NestedFragment ne sera pas invoquée par ce moyen.

La séquence d'appel de onActivityResult (en android support library) est

  1. De l'activité.dispatchActivityResult().
  2. FragmentActivity.onActivityResult().
  3. Le Fragment.onActivityResult().

Dans la 3ème étape, le fragment se trouve dans le FragmentMananger d'Activité parent. Donc dans votre exemple, c'est le ContainerFragment qui se trouve à l'expédition onActivityResult(), NestedFragment ne pourrait jamais recevoir l'événement.

Je pense que vous devez mettre en place votre propre expédition en ContainerFragment.onActivityResult(), trouver la NestedFragment et invoquer transmettre le résultat et les données.

8voto

whizzle Points 356

Voici comment je l'ai résolu.

En activité:

 @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);
        }
    }
}
 

-2voto

JulianLiu Points 9

J'ai fait face au même problème! Je l'ai résolu en utilisant statique ChildFragment dans le ParentFragment , comme ceci:

 private static ChildFragment mChildFragment;

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

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

}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X