Cómo agregar un Fragmento dentro de una ViewPager usando el Fragmento nested (Android 4.2)

Tengo un ViewPager con tres Fragments , cada uno muestra una List (o Grid ).

En el nuevo Android API level 17 (Jelly Bean 4.2), una de las características es Fragmentos nesteds . La nueva descripción de la funcionalidad dice:

si usa ViewPager para crear fragmentos que se deslizan hacia la izquierda y derecha y consumen la mayor parte del espacio de la pantalla, ahora puede insertar fragmentos en cada página de fragmento.

Entonces, si entiendo bien, ahora puedo crear una ViewPager con Fragments (con un botón dentro, por ejemplo) adentro, y cuando el usuario presiona el botón, muestra otro Fragment sin perder la ViewPager usando esta nueva característica.

He gastado mi mañana intentando implementar esto de diferentes maneras, pero no puedo hacerlo funcionar … ¿Alguien puede agregar un ejemplo simple de cómo implementar esto?

PD: solo estoy interesado en hacerlo de esta manera, con getChildFragmentManager para aprender cómo funciona.

Suponiendo que ha creado los diseños correctos de xml. Ahora es muy simple visualizar fragmentos en una ViewPager hospedada por otro Fragment.

El código se ve así en un Fragmento principal:

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

Es importante usar Fragment.getChildFragmentManager () al crear instancias de FragmentPagerAdapter. También tenga en cuenta que no puede usar Fragment.setRetainInstance () en los fragmentos secundarios o obtendrá una excepción.

El código fuente se puede encontrar en: https://github.com/marcoRS/nested-fragments

Editar: si desea reemplazar todo el contenido de una página en una ViewPager , aún puede usar fragmentos nesteds, pero se necesitan algunos cambios. Verifique el ejemplo a continuación ( FragmentActivity , configurar ViewPager y PagerAdapter son los mismos que el fragmento de código anterior):

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

En un vistazo rápido funciona, pero pueden aparecer problemas ya que no lo he probado demasiado.

¿Alguien puede mostrar un ejemplo simple de cómo hacer esto?

Usar fragmentos nesteds parece bastante fácil, hasta que Commonsware venga con una muestra más elaborada, puedes probar el siguiente código:

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

Era flojo e hice todo en código, pero estoy seguro de que puede funcionar con diseños xml inflados.

He creado un ViewPager con 3 elementos y 2 elementos secundarios para el índice 2 y 3 y aquí lo que quería hacer …

enter image description here

Lo he implementado con la ayuda de preguntas y respuestas anteriores de StackOverFlow y aquí está el enlace.

ViewPagerChildFragments