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.
Je l’ai mis en œuvre avec l’aide de questions et réponses précédentes de StackOverFlow et voici le lien.
ViewPagerChildFragments