¿Es posible acceder al Fragmento actual que está siendo visualizado por un ViewPager?
Tengo una aplicación con ViewPager
y tres Fragment
. Estoy tratando de averiguar cómo obtener el Fragment
actual de ser visto para que pueda llegar a sus argumentos.
Tengo un OnPageChangeListener
agarra el índice actual de la página, pero
- ¿Por qué se llama a onCreateView, onCreate, onActivityCreated del fragmento
- Código fuente para la nueva aplicación Android Lollipop Calendar
- Viewpager vertical en la más reciente biblioteca de soporte técnico de Android da errores
- NullPointerException en ViewPager con Recyclerview
- Ocultar barra Tablayout en android
ViewPager.getChildAt(int position);
Devuelve una View
. ¿Cuál es la relación entre esta View
y el Fragment
actual?
Gracias.
- Escucha de zoom para PhotoView
- ViewPager con límites de páginas anteriores y siguientes
- Pager centrado de la visión con la previsualización siguiente y anterior y pagetransformer
- Comunicación de Android entre la actividad y el fragmento
- Los datos de ViewPager se pierden al volver de la siguiente pantalla
- AdMob AdView y ViewPager?
- ¿Cómo evito enfocar el último EditText al navegar desde un Fragment con pestañas?
- Cómo encontrar la "última página" en un paginador de vista. O el número total de puntos de vista. Desarrollo de Android
Finalmente encontré una respuesta que funcionó para mí. Básicamente, puede acceder al fragmento de una página viewPager mediante la etiqueta "android: switcher:" + R.id.viewpager + ": 0".
He solucionado este problema al revés. En lugar de buscar el fragmento de la actividad, estoy registrando el Fragmento durante su método onAttach () en su actividad de propietario y de-registrarlo en el método onStop (). Idea básica:
Fragmento:
@Override public void onAttach(Activity activity) { super.onAttach(activity); try{ mActivity = (IMyActivity)activity; }catch(ClassCastException e){ throw new ClassCastException(activity.toString() +" must be a IMyActivity"); } mActivity.addFragment(this); } @Override public void onStop() { mActivity.removeFragment(this); super.onStop(); }
IMyActivity:
public interface IFriendActivity { public void addFragment(Fragment f); public void removeFragment(Fragment f); }
Mi actividad:
public class MyActivity implements IMyActivity{ [...] @Override public void addFragment(Fragment f) { mFragments.add(f); } @Override public void removeFragment(Fragment f) { mFragments.remove(f); } }
Editar – No haga esto. Si te sientes tentado, lee los comentarios de por qué es una mala idea.
En la extraña oportunidad que todavía está tratando de resolver este problema:
Extienda FragmentPagerAdapter
. En el constructor, cree los Fragmentos que necesita y guárdelos en una Lista (array / ArrayList) de Fragmentos.
private final int numItems = 3; Fragment[] frags; public SwipeAdapter (FragmentManager fm) { super(fm); //Instantiate the Fragments frags = new Fragment[numItems]; Bundle args = new Bundle(); args.putString("arg1", "foo"); frags[0] = new MyFragment(); frags[1] = new YourFragment(); frags[2] = new OurFragment(); frags[2].setArguments(args); }
Luego, para getItem(int position)
, puedes hacer algo como
public Fragment getItem(int position) { return frags[position]; }
No estoy seguro de si esta es la forma generalmente aceptada de hacerlo, pero funcionó para mí.
Editar
Esto realmente no es un buen camino por recorrer. Si planeas manejar cambios de orientación o tu aplicación va al fondo, entonces probablemente romperás tu código. Por favor, lea los comentarios debajo de esta respuesta para más información. Usa la respuesta de @James
POR FAVOR NO UTILICE ESTE
Haga que su adaptador extienda la siguiente clase FragmentStatePagerWithCurrentAdapter
y en lugar de implementar getItem
implemente el mismo código en getItemAtIndex
Establezca ViewPager
OnPageChangeListener
, en la instancia del adaptador.
Cuando necesite acceder al fragmento actual, simplemente llame a adapter.getCurrentItem()
.
package your.package; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.SparseArray; import android.view.ViewGroup; public abstract class FragmentStatePagerWithCurrentAdapter extends FragmentStatePagerAdapter implements OnPageChangeListener { int currentPage = 0; private SparseArray<Fragment> mPageReferenceMap = new SparseArray<Fragment>(); public FragmentStatePagerWithCurrentAdapter(FragmentManager fm) { super(fm); } @Override public final Fragment getItem(int index) { Fragment myFragment = getItemAtIndex(index); mPageReferenceMap.put(index, myFragment); return myFragment; } public abstract Fragment getItemAtIndex(int index); @Override public void destroyItem(ViewGroup container, int position, Object object) { super.destroyItem(container, position, object); mPageReferenceMap.remove(Integer.valueOf(position)); } public Fragment getCurrentItem() { return mPageReferenceMap.get(currentPage); } @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int newPageIndex) { currentPage = newPageIndex; } }
Utilicé como referencia la siguiente entrada del blog: http://tamsler.blogspot.com/2011/11/android-viewpager-and-fragments-part-ii.html
Sí, es posible si está utilizando FragmentStatePagerAdapter
.
ViewPager vp; //... YourFragment fragment = (YourFragment) adapter.instantiateItem(vp, vp.getCurrentItem());
Se ha explicado aquí: http://developer.android.com/guide/topics/fundamentals/fragments.html
En OnCreateView debe devolver una vista para dibujar una interfaz de usuario para su fragmento, creo que esa es la relación.
También esta pregunta podría ser similar: Get focused View from ViewPager
Puede hacerlo: – En la extensión de la clase de un adaptador de paginador de vista (como PagerAdapter, FragmentStatePagerAdapter …) método de sustitución instantiateItem:
@Override public Object instantiateItem(ViewGroup container, int position) { final Fragment frag = (Fragment) super.instantiateItem(container, position); if(frag instanceof ListNoteOfTypeFragment){ final ListNoteOfTypeFragment listNoteOfTypeFragment = (ListNoteOfTypeFragment) frag; //do whatever you want with your fragment here listNoteOfTypeFragment.setNoteChangeListener(mListener); } return frag; }
Respuesta definitiva que funciona perfectamente (pero pequeño hack):
En algún lugar del diseño del fragmento de página:
<FrameLayout android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone" android:id="@+id/fragment_reference"> <View android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone"/> </FrameLayout>
En el fragmento onCreateView ():
... View root = inflater.inflate(R.layout.fragment_page, container, false); ViewGroup ref = (ViewGroup)root.findViewById(R.id.fragment_reference); ref.setTag(this); ref.getChildAt(0).setTag("fragment:" + pageIndex); return root;
Y el método para devolver fragmento de ViewPager, si existe:
public Fragment getFragment(int pageIndex) { View w = mViewPager.findViewWithTag("fragment:" + pageIndex); if (w == null) return null; View r = (View) w.getParent(); return (Fragment) r.getTag(); }
FragmentStatePagerWithCurrentAdapter de Jorge Garcia es una muy buena solución, pero necesita una pequeña mejora. En caso de que la actividad se destruya y vuelva a crear en respuesta a un cambio de configuración o algo así, el getItem no será llamado para los fragmentos que fueron guardados y recuperados por el gestor de fragmentos. Por lo tanto, anula getItem normalmente en mi subclase y pongo lo siguiente en FragmentStatePagerWithCurrentAdapter
@Override public Object instantiateItem(ViewGroup container, int position) { Object item = super.instantiateItem(container, position); if ( item instanceof Fragment ) { pageReferenceMap.put(position, (Fragment)item); } return item; }
El instantiateItem se llama cada vez que se accede al fragmento en esa posición.
O simplemente guarde todos los Fragmentos en un mapa:
public class MyFragment extends Fragment implements OnPageChangeListener { private ViewPager viewPager; private FragmentStatePagerAdapter viewAdapter; private View rootView; private Map<Integer, Fragment> fragments = new HashMap<Integer, Fragment>(); @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.introdution, container, false); viewPager = (ViewPager) rootView.findViewById(R.id.pager); viewAdapter = new ViewAdapter(getFragmentManager()); viewPager.setAdapter(viewAdapter); viewPager.addOnPageChangeListener(this); return rootView; } private class ViewAdapter extends FragmentStatePagerAdapter { public ViewAdapter(FragmentManager fragmentManager) { super(fragmentManager); } @Override public Fragment getItem(int position) { Fragment result = null; switch (position) { case 0: result = Fragment1.newInstance(); break; case 1: result = Fragment2.newInstance(); break; } if (result != null) fragments.put(position, result); return result; } @Override public int getCount() { return 2; } } @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int position) { Fragment currentFragment = fragments.get(position); } }
Creo que hay la mejor manera de usar este
Log.i(TAG, "getCurrentItem " + mViewPager.getCurrentItem());
Puede obtener la página actual del fragmento de visualización.
- Cuando se reemplaza un fragmento y se coloca en la pila de atrás (o se quita) ¿permanece en la memoria?
- Gradiente circular en android