Mostrar fragmento viewpager dentro de un fragmento
Tengo un fragmento que contiene un ViewPager. ViewPager está asociado con un adaptador que contiene un conjunto de fragmentos.
Al cargar el fragmento padre, me encuentro con una IllegalStateException
con el mensaje: java.lang.IllegalStateException: Recursive entry to executePendingTransactions
.
- El método getChildFragmentManager () no está definido
- Cómo obtener la posición actual de un ViewPager
- ¿Existe un DotsPageIndicator predeterminado para Android móvil (no usar)?
- ViewPager dentro de Fragmento desaparece después de transaction.remove () (Mantener instancia?)
- Desplazamiento no funciona en android ViewPager con FragmentPagerAdapter
Algunas investigaciones me han llevado a la conclusión de que el sistema es incapaz de mostrar fragmentos dentro de otro fragmento, sin embargo, parece haber alguna indicación de que es posible hacer exactamente esto con el uso de un ViewPager ( un error en ViewPager con otro fragmento ).
De hecho, si agrego un botón a mi fragmento padre que llama a mPager.setAdapter(mAdapter)
en mi ViewPager cuando se presiona, ViewPager se carga correctamente. Esto no es ideal.
El problema entonces debe estar relacionado con el ciclo de vida de los fragmentos. Mi pregunta, por lo tanto, es esta: ¿Alguien más ha encontrado una manera de evitar este problema, y si es así, ¿cómo?
¿Hay alguna manera de retrasar la configuración del adaptador en el ViewPager hasta después de la transacción de fragmento?
Aquí está mi código de fragmento padre:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mView = inflater.inflate(R.layout.team_card_master, container, false); mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager); final Button button = (Button)mView.findViewById(R.id.load_viewpager_button); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mViewPager.setAdapter(mAdapter); button.setVisibility(View.GONE); } }); mAdapter = new ViewPagerAdapter(getFragmentManager()); // mViewPager.setAdapter(mAdapter); return mView; }
Y el adaptador:
public class ViewPagerAdapter extends FragmentPagerAdapter { public ViewPagerAdapter(FragmentManager fm) { super(fm); } @Override public int getCount() { if (mCursor == null) return 0; else return mCursor.getCount(); } @Override public Fragment getItem(int position) { Bundle b = createBundle(position, mCursor); return TeamCardFragment.newInstance(b); } }
- No se puede establecer la propiedad en un fragmento con varias instancias
- Eclipse no reconocerá el proyecto como biblioteca (ActionBarSherlock / ViewPagerIndicator)
- Aplicar fuerza cerrar en viewPager.setAdapter (adaptador)
- FragmentTabHost - No se conoce ninguna pestaña null
- ¿Las pestañas anidadas con el visor de desplazamiento en android?
- Android usando viewPager vs usando tabhost
- ¿Hay una manera de desactivar el desvanecimiento que un viewPager tiene desplazamiento a los bordes?
- Cómo colocar el botón de acción flotante exclusivamente en un fragmento sólo en el diseño de la pestaña
Utilice AsyncTask para establecer el adaptador para viewPager. Esto funciona para mi. El asyncTask es hacer que el fragmento original complete su transición. Y luego procedemos con fragmentos viewPager, básicamente para evitar la recursión.
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mView = inflater.inflate(R.layout.team_card_master, container, false); mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager); final Button button = (Button)mView.findViewById(R.id.load_viewpager_button); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mViewPager.setAdapter(mAdapter); button.setVisibility(View.GONE); } }); mAdapter = new ViewPagerAdapter(getFragmentManager()); new setAdapterTask().execute(); return mView; } private class setAdapterTask extends AsyncTask<Void,Void,Void>{ protected Void doInBackground(Void... params) { return null; } @Override protected void onPostExecute(Void result) { mViewPager.setAdapter(mAdapter); } }
Jords, creo que puedes usar FragmentStatePagerAdapter
lugar de FragmentPageAdapter
. Se eliminará fragmentos para usted.
PD. Lo siento por usar respuesta en lugar de comentario, pero mi reputación es demasiado baja.
Me encontré con el mismo problema. Tuve un Fragment
que necesitaba para alojar un ViewPager
de Fragments
. Cuando apilado otro Fragment
en la parte superior de mi ViewPagerFragment
, y luego golpeó de nuevo, me gustaría obtener una IllegalStateException
. Después de comprobar los registros (al apilar un nuevo Fragment
), encontré que mi ViewPagerFragment
iría a través de sus métodos de ciclo de vida para detener y destruir, sin embargo sus Fragments
en el ViewPager
se quedaría en onResume
. Me di cuenta de que los Fragments
los niños deben ser administrados por el FragmentManager
para el ViewPagerFragment
, no el FragmentManager
de la Activity
.
Entiendo en el momento, las respuestas anteriores fueron para evitar las limitaciones de Fragments
no ser capaz de tener Fragments
hijos. Sin embargo, ahora que la última biblioteca de soporte tiene soporte para la anidación de Fragment
, ya no necesitará hackear la configuración del adaptador para ViewPager
y pasar getChildFragmentManager()
es todo lo que necesita. Esto ha funcionado perfectamente para mí hasta ahora.
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mView = inflater.inflate(R.layout.team_card_master, container, false); mViewPager = (ViewPager) mView.findViewById(R.id.team_card_master_view_pager); mAdapter = new ViewPagerAdapter(getChildFragmentManager()); mViewPager.setAdapter(mAdapter); return mView; }
He utilizado Handler.post()
para configurar el adaptador fuera de la transacción de fragmento original:
@Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mHandler.post(new Runnable() { @Override public void run() { mViewPager.setAdapter(mAdapter); } }); }
He hecho frente a este problema al intentar inicializar el adaptador del viewPager en el TabIndicator en encendido ViewCreated. Después de leer sobre él en línea me di cuenta de que esto podría ser sólo porque el fragmento no se agregó aún a la actividad. Así que moví el código de inicialización a onStart () del fragmento, esto debería resolver su problema. Pero no para mí todavía estaba recibiendo el mismo problema de nuevo.
Pero eso era porque en mi código estaba intentando el bypass la ejecución asíncrona normal de la tarea pendiente por llamada explícita a executePendingTransactions (), después de bloquear que todo funcionó bien
Al cargar el fragmento padre, me encuentro con una IllegalStateException con el mensaje: java.lang.IllegalStateException: Entrada recursiva para ejecutarPendingTransactions.
Algunas investigaciones me han llevado a la conclusión de que el sistema no puede mostrar fragmentos dentro de otro fragmento, sin embargo, parece que hay alguna indicación de que es posible hacer exactamente esto con el uso de un ViewPager (Un error en ViewPager con otro fragmento ).
Establece Id para ViewPager explícitamente.
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mView = inflater.inflate(R.layout.team_card_master, container, false); mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager); mViewPager.setId(100); final Button button = (Button)mView.findViewById(R.id.load_viewpager_button); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mViewPager.setAdapter(mAdapter); button.setVisibility(View.GONE); } }); mAdapter = new ViewPagerAdapter(getFragmentManager()); mViewPager.setAdapter(mAdapter); return mView; }
Puede utilizar id en sus recursos xml en lugar de un número mágico 100.
<resources> <item name="Id_For_ViewPager" type="id"/> </resources>
Y setId (R.Id_For_ViewPager).
Vea la fuente FragmentManager.java para más detalles.
O vea esta página (en japonés). La idea original es de ella, en realidad, no yo. http://y-anz-m.blogspot.jp/2012/04/androidfragment-viewpager-id.html
Usando este brillante post de Thomas Amssler: http://tamsler.blogspot.nl/2011/11/android-viewpager-and-fragments-part-ii.html
Iv'e creó un adaptador que se puede utilizar para crear todo tipo de fragmentos. El propio adaptador se ve así:
public abstract class EmbeddedAdapter extends FragmentStatePagerAdapter { private SparseArray<WeakReference<Fragment>> mPageReferenceMap = new SparseArray<WeakReference<Fragment>>(); private ArrayList<String> mTabTitles; public abstract Fragment initFragment(int position); public EmbeddedAdapter(FragmentManager fm, ArrayList<String> tabTitles) { super(fm); mTabTitles = tabTitles; } @Override public Object instantiateItem(ViewGroup viewGroup, int position) { mPageReferenceMap.put(Integer.valueOf(position), new WeakReference<Fragment>(initFragment(position))); return super.instantiateItem(viewGroup, position); } @Override public int getCount() { return mTabTitles.size(); } @Override public CharSequence getPageTitle(int position) { return mTabTitles.get(position); } @Override public Fragment getItem(int pos) { return getFragment(pos); } @Override public void destroyItem(ViewGroup container, int position, Object object) { super.destroyItem(container, position, object); mPageReferenceMap.remove(Integer.valueOf(position)); } public Fragment getFragment(int key) { WeakReference<Fragment> weakReference = mPageReferenceMap.get(key); if (null != weakReference) { return (Fragment) weakReference.get(); } else { return null; } } @Override public int getItemPosition(Object object) { return POSITION_NONE; }
}
Para utilizar el adaptador tendrá que hacer lo siguiente:
private void setAdapter() { if(mAdapter == null) mAdapter = new EmbeddedAdapter(getActivity().getSupportFragmentManager(), mTabTitles) { @Override public Fragment initFragment(int position) { Fragment fragment; if(position == 0){ // A start fragment perhaps? fragment = StartFragment.newInstance(mBlocks); }else{ // Some other fragment fragment = PageFragment.newInstance(mCategories.get((position))); } return fragment; } }; // Have to set the adapter in a handler Handler handler = new Handler(); handler.post(new Runnable() { @Override public void run() { mViewPager.setVisibility(View.VISIBLE); mPagerTabStrip.setVisibility(View.VISIBLE); mAdapter.notifyDataSetChanged(); } }); }
Tenga en cuenta que todos los fragmentos utilizan:
setRetainInstance(true);
De acuerdo con la documentación: https://developer.android.com/reference/android/app/Fragment.html#getChildFragmentManager ()
Si desea administrar el fragmento de anidamiento, debe utilizar getChildFragmentManager
lugar de getFragmentManager
.
- OnClickListener – x, y ubicación del evento?
- Arquitectura de la aplicación de Android: ¿cuál es el modelo sugerido?