Comment append un fragment dans un ViewPager en utilisant un fragment nested (Android 4.2)

J’ai un ViewPager avec trois Fragments , chacun ViewPager une List (ou Grid ).

Dans le nouvel Android API level 17 (Jelly Bean 4.2), l’une des fonctionnalités est Nested Fragments . La nouvelle description de la fonctionnalité indique:

Si vous utilisez ViewPager pour créer des fragments qui glissent de gauche à droite et consumnt la majorité de l’espace écran, vous pouvez désormais insérer des fragments dans chaque page de fragment.

Donc, si je comprends bien, maintenant je peux créer un ViewPager avec Fragments (avec un bouton à l’intérieur par exemple) à l’intérieur, et lorsque l’utilisateur appuie sur le bouton, affiche un autre Fragment sans perdre le ViewPager utilisant cette nouvelle fonctionnalité.

J’ai passé ma matinée à essayer de mettre en œuvre plusieurs façons différentes, mais je ne peux pas le faire fonctionner … Quelqu’un peut-il append un exemple simple de la façon de mettre en œuvre cela?

PS: Je ne suis intéressé que par ce moyen, avec getChildFragmentManager pour apprendre comment fonctionne.

En supposant que vous avez créé les dispositions XML correctes. Il est désormais très simple d’afficher des fragments dans un ViewPager hébergé par un autre fragment.

Le code ressemble à ceci dans un fragment parent:

  @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_parent, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ViewPager mViewPager = (ViewPager) view.findViewById(R.id.viewPager); mViewPager.setAdapter(new MyAdapter(getChildFragmentManager())); } public static class MyAdapter extends FragmentPagerAdapter { public MyAdapter(FragmentManager fm) { super(fm); } @Override public int getCount() { return 4; } @Override public Fragment getItem(int position) { Bundle args = new Bundle(); args.putInt(TextViewFragment.POSITION_KEY, position); return TextViewFragment.newInstance(args); } } 

Il est important d’utiliser Fragment.getChildFragmentManager () lors de l’instanciation de FragmentPagerAdapter. Notez également que vous ne pouvez pas utiliser Fragment.setRetainInstance () sur les fragments enfants ou que vous obtenez une exception.

Le code source peut être trouvé à: https://github.com/marcoRS/nested-fragments

Modifier: si vous souhaitez remplacer tout le contenu d’une page dans un ViewPager vous pouvez toujours utiliser des fragments nesteds, mais certaines modifications sont nécessaires. Vérifiez l’exemple ci-dessous ( FragmentActivity , la définition du ViewPager et du PagerAdapter sont identiques à ceux du code précédent):

 // this will act as a fragment container, representing one page in the ViewPager public static class WrapperFragment extends Fragment implements ReplaceListener { public static WrapperFragment newInstance(int position) { WrapperFragment wp = new WrapperFragment(); Bundle args = new Bundle(); args.putInt("position", position); wp.setArguments(args); return wp; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { FrameLayout fl = new FrameLayout(getActivity()); fl.setId(10000); if (getChildFragmentManager().findFragmentByTag("initialTag") == null) { InitialInnerFragment iif = new InitialInnerFragment(); Bundle args = new Bundle(); args.putInt("position", getArguments().getInt("position")); iif.setArguments(args); getChildFragmentManager().beginTransaction() .add(10000, iif, "initialTag").commit(); } return fl; } // required because it seems the getChildFragmentManager only "sees" // containers in the View of the parent Fragment. @Override public void onReplace(Bundle args) { if (getChildFragmentManager().findFragmentByTag("afterTag") == null) { InnerFragment iif = new InnerFragment(); iif.setArguments(args); getChildFragmentManager().beginTransaction() .replace(10000, iif, "afterTag").addToBackStack(null) .commit(); } } } // the fragment that would initially be in the wrapper fragment public static class InitialInnerFragment extends Fragment { private ReplaceListener mListener; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mListener = (ReplaceListener) this.getParentFragment(); LinearLayout ll = new LinearLayout(getActivity()); Button b = new Button(getActivity()); b.setGravity(Gravity.CENTER_HORIZONTAL); b.setText("Frame " + getArguments().getInt("position")); b.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Bundle args = new Bundle(); args.putInt("positionInner", getArguments().getInt("position")); if (mListener != null) { mListener.onReplace(args); } } }); ll.setOrientation(LinearLayout.VERTICAL); ll.addView(b, new LinearLayout.LayoutParams(250, LinearLayout.LayoutParams.WRAP_CONTENT)); return ll; } } public static class InnerFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { TextView tv = new TextView(getActivity()); tv.setText("InnerFragment in the outher Fragment with position " + getArguments().getInt("positionInner")); return tv; } } public interface ReplaceListener { void onReplace(Bundle args); } 

Au coup d’œil, cela fonctionne, mais des problèmes peuvent apparaître car je ne l’ai pas trop testé.

Quelqu’un peut-il montrer un exemple simple de comment faire cela?

Utiliser des fragments nesteds semble assez simple, jusqu’à ce que Commonsware soit livré avec un exemple plus élaboré, vous pouvez essayer le code ci-dessous:

 public class NestedFragments extends FragmentActivity { @Override protected void onCreate(Bundle arg0) { super.onCreate(arg0); ViewPager vp = new ViewPager(this); vp.setId(5000); vp.setAdapter(new MyAdapter(getSupportFragmentManager())); setContentView(vp); } private static class MyAdapter extends FragmentPagerAdapter { public MyAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return WrapperFragment.newInstance(position); } @Override public int getCount() { return 8; } } public static class WrapperFragment extends Fragment { public static WrapperFragment newInstance(int position) { WrapperFragment wp = new WrapperFragment(); Bundle args = new Bundle(); args.putInt("position", position); wp.setArguments(args); return wp; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { LinearLayout ll = new LinearLayout(getActivity()); FrameLayout innerFragContainer = new FrameLayout(getActivity()); innerFragContainer.setId(1111); Button b = new Button(getActivity()); b.setText("Frame " + getArguments().getInt("position")); b.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { InnerFragment innerFragment = new InnerFragment(); Bundle args = new Bundle(); args.putInt("positionInner", getArguments().getInt("position")); innerFragment.setArguments(args); FragmentTransaction transaction = getChildFragmentManager() .beginTransaction(); transaction.add(1111, innerFragment).commit(); } }); ll.setOrientation(LinearLayout.VERTICAL); ll.addView(b, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); ll.addView(innerFragContainer, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); return ll; } } public static class InnerFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { TextView tv = new TextView(getActivity()); tv.setText("InnerFragment in the outher Fragment with position " + getArguments().getInt("positionInner")); return tv; } } } 

J’étais paresseux et j’ai tout fait en code, mais je suis sûr que cela peut fonctionner avec des mises en page XML gonflées.

J’ai créé un ViewPager avec 3 éléments et 2 sous-éléments pour les index 2 et 3 et voici ce que je voulais faire.

entrer la description de l'image ici

Je l’ai mis en œuvre avec l’aide de questions et réponses précédentes de StackOverFlow et voici le lien.

ViewPagerChildFragments