Cómo agregar un fragmento dentro de un ViewPager usando Nested Fragment (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 Nested Fragments . La nueva descripción de la funcionalidad dice:

Si utiliza ViewPager para crear fragmentos que deslizan hacia la izquierda y la derecha y consumen la mayoría del espacio de la pantalla, ahora puede insertar fragmentos en cada página de fragmentos.

Por lo tanto, si entiendo bien, ahora puedo crear un ViewPager con Fragments (con un botón dentro por ejemplo) dentro, y cuando el usuario presione el botón mostrar otro Fragment sin perder el ViewPager con esta nueva característica.

He gastado mi mañana tratando de implementar varias maneras diferentes, pero no puedo conseguir que funcione … ¿Puede alguien añadir un ejemplo sencillo de cómo implementar esto?

PS: Sólo estoy interesado en hacer de esta manera, con getChildFragmentManager para aprender cómo funciona.

Suponiendo que ha creado los diseños xml correctos. Ahora es muy sencillo mostrar fragmentos en un ViewPager que está alojado en otro Fragmento.

El código se ve algo así en un fragmento de origen:

  @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 utilizar Fragment.getChildFragmentManager () al instanciar el FragmentPagerAdapter. También tenga en cuenta que no puede utilizar Fragment.setRetainInstance () en los fragmentos de niños 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 un ViewPager , puede utilizar fragmentos anidados, pero es necesario realizar algunos cambios. Compruebe el ejemplo a continuación (la FragmentActivity , establecer el ViewPager y el 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 los problemas pueden aparecer como no lo he probado a mucho.

¿Puede alguien mostrar un ejemplo simple de cómo hacer esto?

El uso de fragmentos anidados parece bastante fácil, hasta que Commonsware viene 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; } } } 

Yo era perezoso e hizo todo en código, pero estoy seguro de que puede trabajar con diseños inflados xml.

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

Introduzca aquí la descripción de la imagen

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

ViewPagerChildFragments

  • CoordinatorLayout + AppbarLayout + Viewpager no cambia el tamaño del diseño secundario
  • FragmentPagerAdapter muestra todo el contenido del fragmento en la primera página
  • OnPrepareOptionsMenu no se llama
  • Android: ¿cuál es mejor, viewpager, galería, vista de desplazamiento horizontal ... o?
  • OnResume () no se llama al fragmento ViewPager cuando se utiliza Custom Loader
  • La aplicación de Android se bloquea después de un tiempo utilizando Fragments y ViewPager
  • SimpleCursorAdapter en un ViewPager
  • Android: ¿Cómo agregar iconos / drawables a la PagerTabStrip de la versión 4 de Android Support Lib?
  • Cómo comprometer Fragment transacciones en FragmentPagerAdapter en onLoadFinish método de devolución de llamada?
  • IllegalStateException: No se puede cambiar la etiqueta del fragmento era android: switcher ahora android: switcher
  • Escucha de zoom para PhotoView
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.