Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


IllegalArgumentException: No se encontró ninguna vista para id para fragmento – ViewPager en ViewPager

He conocido el problema que me preocupa durante días.

Hay un ViewPager en la actividad principal que contiene 3 Fragment como fragmentos de tabulación. En el primer fragmento hay un ListView que contiene algunas vistas, y que es el más importante, otro ViewPager . Quiero celebrar algunas fotos en el ViewPager sub, y utilizar algunos fragmentos más aquí.

Ahora está el problema:
Cuando el primer Fragment se detiene (el tercer fragmento en el ViewPager padre se ve en la pantalla) y se reanuda (el usuario cambia al segundo fragmento), la aplicación se bloquea y el depurador dice:

 java.lang.IllegalArgumentException: No view found for id 0x7f05008b (com.example.viewpager:id/sub_viewpager) for fragment ScreenSlidePageFragment 

Ya he utilizado el getChildFragmentManager() ya que esta es una situación de fragmentos anidados .

Aquí está el código clave del adaptador de lista correspondiente al primer fragmento en el ViewPager padre:

 @Override public View getView(int position, View convertView, ViewGroup parent) { int type = getItemViewType(position); switch (type) { case TYPE_BANNER: if (convertView == null) { convertView = mBannerView.getBannerView(parent); } mBannerView.update(convertView); break; case TYPE_ITEM: break; } return convertView; } 

Aquí está el código de mBannerView :

 public class BannerView { private static final DisplayImageOptions IMAGE_OPTIONS_SCALE_STRETCHED = new DisplayImageOptions.Builder() .cacheInMemory() .cacheOnDisc() .imageScaleType(ImageScaleType.EXACTLY_STRETCHED) .build(); private FragmentActivity mActivity; private Fragment mFragment; private List<Banner> mBanners; private ScreenSlidePagerAdapter mPagerAdapter; private ViewPager mViewPager; public BannerView(FragmentActivity activity, Fragment fragment) { mActivity = activity; mFragment = fragment; } public void update(View convertView) { mViewPager = (ViewPager) convertView; if (mBanners != null && !mBanners.isEmpty()) { if (mPagerAdapter == null) { mPagerAdapter = new ScreenSlidePagerAdapter(mFragment.getChildFragmentManager()); mViewPager.setAdapter(mPagerAdapter); } } mViewPager.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mOnBannerClickListener != null) { mOnBannerClickListener.onBannerClick(); } } }); } class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { public ScreenSlidePagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return new ScreenSlidePageFragment(mBanners.get(position).getImageUrl()); } @Override public int getCount() { return mBanners == null ? 0 : mBanners.size(); } } class ScreenSlidePageFragment extends Fragment { private String mUrl; ScreenSlidePageFragment(String url) { super(); mUrl = url; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.item_banner, container, false); if (view != null) { ImageView imageView = (ImageView) view.findViewById(R.id.item_banner_image); imageView.setLayoutParams(new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); ImageLoader.getInstance().displayImage(mUrl, imageView, IMAGE_OPTIONS_SCALE_STRETCHED); } return view; } } } 

Aquí está la lista detallada de errores:

 11-10 18:12:19.217 1444-1444/? E/MessageQueue-JNI﹕ java.lang.IllegalArgumentException: No view found for id 0x7f05008b (com.example.viewpager:id/sub_viewpager) for fragment ScreenSlidePageFragment{428d8ea0 #0 id=0x7f05008b} at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:919) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1086) at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1884) at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1514) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:947) at android.support.v4.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1280) at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:672) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467) at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:472) at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141) at android.support.v4.view.ViewPager.populate(ViewPager.java:1068) at android.support.v4.view.ViewPager.populate(ViewPager.java:914) at android.support.v4.view.ViewPager$3.run(ViewPager.java:244) at android.support.v4.view.ViewPager.completeScroll(ViewPager.java:1761) at android.support.v4.view.ViewPager.onInterceptTouchEvent(ViewPager.java:1896) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1854) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1912) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1912) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1912) at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2228) at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1471) at android.app.Activity.dispatchTouchEvent(Activity.java:2424) at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2176) at android.view.View.dispatchPointerEvent(View.java:7571) at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3883) at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3778) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3379) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3429) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3398) at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3483) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3406) at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3540) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3379) at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3429) at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3398) at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3406) at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3379) at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5419) at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5399) at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5370) at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5493) at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:182) at android.os.MessageQueue.nativePollOnce(Native Method) at android.os.MessageQueue.next(MessageQueue.java:132) at android.os.Looper.loop(Looper.java:124) at android.app.ActivityThread.main(ActivityThread.java:5289) at java.lang 

  • Tener páginas de desplazamiento vertical en ViewPager
  • OnTouchEvent se ejecuta cuando se pasa la página usando ViewPager y PassByValue
  • Cómo determinar cuándo Fragmento se vuelve visible en ViewPager
  • Mediaplayer responde al segundo clic para pausar
  • ¿Cómo puedo poner títulos en ViewPager usando fragmentos?
  • ¿Por qué ViewPager y GridLayout con 30 elementos son muy lentos?
  • Implementar la función como la aplicación de iOS que cierra vertical Desplazar-para-Descartar con ViewPager
  • ViewPager y base de datos
  • 7 Solutions collect form web for “IllegalArgumentException: No se encontró ninguna vista para id para fragmento – ViewPager en ViewPager”

    Actualizar:

    He leído el código fuente del FragmentManager y finalmente conseguí la razón verdadera: Esta excepción ocurre cuando los fragmentos desean ser atados al viewpager antes de que el viewpager sea atado a su padre. En otras palabras, antes de devolver el método getView (), los fragmentos se inflan. A continuación, se llama al método findViewById () del contenedor del ViewPager pero el ViewPager se encuentra en estado desvinculado, por lo que se encuentra nulo y se lanza la excepción IllegalArgumentException.

    La solución es crear un ViewPager personalizado y perezoso configurar el adaptador:

     public class BannerViewPager extends ViewPager { PagerAdapter mPagerAdapter; @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (mPagerAdapter != null) { super.setAdapter(mPagerAdapter); mPageIndicator.setViewPager(this); } } @Override public void setAdapter(PagerAdapter adapter) { } public void storeAdapter(PagerAdapter pagerAdapter) { mPagerAdapter = pagerAdapter; } public BannerViewPager(Context context) { super(context); } public BannerViewPager(Context context, AttributeSet attrs) { super(context, attrs); } } 

    Y en el método getView (), use storeAdapter () en lugar de setAdapter.

    Las siguientes afirmaciones no son correctas. Las palabras anteriores son la razón real.


    Finalmente tengo la respuesta. Está formado por dos partes.

    1. En el ViewPager padre utilicé un FragmentPagerAdapter para mantener fragmentos, pero ahora uso un FragmentStatePagerAdapter lugar. La diferencia entre estos dos se puede encontrar aquí: Diferencia entre FragmentPagerAdapter y FragmentStatePagerAdapter .
      Simplemente hablando, FragmentPagerAdapter almacenará más información cuando se detenga un fragmento. En esta situación, el primer fragmento en el ViewPager padre se detiene pero no se destruye mientras se destruyen las vistas en este fragmento. Después de reanudar, el fragmento trata de volver a inflar todas las vistas. Pero antes de getView() método getView() y recriar el sub-ViewPager, el niño FragmentManager intenta encontrar el sub-ViewPager para contener los fragmentos previamente almacenados. Por lo tanto, se produce la "java.lang.IllegalArgumentException: no se encontró ninguna vista para id".

    2. Después de reemplazar el FragmentPagerAdapter con FragmentStatePagerAdapter, aparece otro problema. El sub-viewpager falta cuando el fragmento padre (el primer fragmento en el viewpager padre) se detuvo, se destruyó y se reanudó. Esto ocurre cuando se elige el primer fragmento, luego se selecciona el tercer fragmento y finalmente se vuelve a elegir el primer fragmento.
      Creo que esto es un error de android sdk. Inspirado aquí y aquí , uso algunos métodos difíciles para resolver el problema. El punto es, cuando un fragmento padre es destruido, el miembro de campo — mChildFragmentManager "termina con un estado interno roto" y no está totalmente limpiado. Cuando se vuelve a crear el fragmento padre, mChildFragmentManager no es nulo, pero los subfragmentos ya se han destruido después de destruir el fragmento padre, que fue administrado por mChildFragmentManager. Así, el ViewPager sub muestra una vista vacía en la pantalla, que responde a un fragmento falso que en realidad no existe. Lo curioso es que, después de pasar directamente al sub ViewPager durante varias veces, los fragmentos secundarios y las vistas vuelven a aparecer.

    Aquí están los códigos:

    Adaptador padre:

     @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = getBannerView(mParent); } mViewPager = (ViewPager) convertView; if (mBanners != null && !mBanners.isEmpty()) { if (mPagerAdapter == null) { FragmentManager childFM = mFragment.getChildFragmentManager(); removeOldFragment(childFM); mPagerAdapter = new ScreenSlidePagerAdapter(childFM, mBanners); mViewPager.setAdapter(mPagerAdapter); } } return convertView; } 

    El método clave:

      private void removeOldFragment(FragmentManager fm) { try { Field added = fm.getClass().getDeclaredField("mAdded"); added.setAccessible(true); added.set(fm, null); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } try { Field active = fm.getClass().getDeclaredField("mActive"); active.setAccessible(true); active.set(fm, null); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } 

    Cuando usted tiene una Actividad y un Fragmento que estaría contenido por la Actividad, tendrá layout-xml con un id donde debe colocarse el fragmet.

    Si el ID no se encuentra en la Actividad, obtendrá esta excepción.

    Ejemplo:

     getSupportFragmentManager().beginTransaction() .add(R.id.banner_container, bannerFragment) .commit(); 

    Si R.id.banner_container no es un id en Activity-layout-xml, obtendrá la excepción.

    Xieyi hizo un buen trabajo explicando el razonamiento detrás de la excepción.

    Aquí está la solución que encontré:

     @Override public void onPause() { super.onPause(); for ( Fragment f : getChildFragmentManager().getFragments() ) { if ( f instanceof MyFragmentType ) { getChildFragmentManager().beginTransaction().remove( f ).commit(); } } } 

    Estaba recibiendo la excepción cada vez que iba a un nuevo fragmento y regresaba. Asegúrese de quitar los fragmentos en su "cleaup" método, entonces usted puede cargar puede recargar sus puntos de vista cuando vuelva al fragmento.

    Se produjo el mismo problema al utilizar ViewPagers anidados. Fijé el problema substituyendo el FragmentPagerAdapter s con FragmentStatePagerAdapter s.

    Aunque la solución de Xieyi funciona perfectamente bien, se basa bastante en hacer una reflexión, lo cual no es realmente una buena cosa hacer.

    Como una respuesta alternativa, me las arreglé para eliminar los fragmentos de los niños mediante la transacción de fragmentos en su lugar, que creo que debería ser el enfoque preferido aquí.

    Primero, registre una devolución de llamada del ciclo de vida del fragmento al gestor de fragmentos secundarios para que podamos mantener la referencia a los fragmentos secundarios.

     private List<Fragment> mFragments = new ArrayList<>(); @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); …(DO YOUR STUFF) //register a fragment lifecycle callback getChildFragmentManager().registerFragmentLifecycleCallbacks(new FragmentManager.FragmentLifecycleCallbacks() { @Override public void onFragmentCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) { super.onFragmentCreated(fm, f, savedInstanceState); mFragments.add(f); } @Override public void onFragmentDestroyed(FragmentManager fm, Fragment f) { super.onFragmentDestroyed(fm, f); mFragments.remove(f); } }, false); 

    A continuación, solo necesitamos iterar sobre la lista de fragmentos para eliminarlos del gestor de fragmentos secundarios, dentro de onCreateView:

     @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { //remove child fragments before inflating view Iterator<Fragment> iterator = mFragments.iterator(); while (iterator.hasNext()) { Fragment fragment = iterator.next(); iterator.remove(); getChildFragmentManager().beginTransaction() .remove(fragment) .commitNow(); } return inflater.inflate(R.layout.your_fragment, container, false); } 

    Eso es.

    Tuve un problema similar. Tengo un fragmento (HomeFragment) con un ListView y un ViewPager que tiene algunos fragmentos en el interior, todo funciona muy bien cuando el fragmento comienza, cuando hago clic en una fila en el ListView, me llevará a otro fragmento, pero cuando quiero Volver al fragmento anterior (HomeFragment) Obtengo la vista No encontrada para el error de identificación (tengo addToBackStack el fragmento).

    La solución era verificar en el onCreateView de HomeFragment si ya se habían creado View y otros componentes, como:

     View view; public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (view == null) { //All the code in the onCreateView view = inflater.inflate(R.layout.item_banner, container, false); //... } } 

    Con esta verificación cuando se vuelve al fragmento anterior, todo funciona bien, ya se han creado View, pager, list, etc, por lo que no es necesario volver a crearlo. =)

    Tuve el mismo problema antes, y probé la respuesta aceptada, pero no funcionó para mí. Después de más investigación encontré mi solución.

    Esto está en mi fragmento

     CustomViewPager customViewPager = (customViewPager) View.inflate(parentActivity, R.layout.custom_viewpager, null); 

    Y este es mi diseño

     <com.test.package.ui.CustomViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/custom_viewpager" android:layout_width="match_parent" android:layout_height="match_parent"/> 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.