Android, Cómo mezclar ActionBar.Tab + Ver Pager + ListFragment
¡He estado intentando probar cómo mezclar todas estas cosas juntas y tengo problemas !! Sólo quiero una aplicación con tres pestañas utilizando el ActionBar.Tab. Por ejemplo, estas pestañas pueden ser películas de género Acción, Aventura y Animación, el usuario puede pasar por las pestañas, por lo que utilizará el ViewPager y cada pestaña mostrará una lista de películas de ese género. No es necesario tener tres clases de fragmentos diferentes porque todas las fichas tendrán el mismo formato una lista simple. Y estoy teniendo problemas porque cuando selecciono la segunda pestaña, la posición de onPageSelected es 1,
mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setAdapter(mCollectionPagerAdapter); mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { mActionBar.setSelectedNavigationItem(position); } });
Esto hace que la llamada al método public Fragment getItem (int i) dentro de la clase CollectionPagerAdapter, pero entonces el valor de i es 2 NOT 1, por lo que llama a createView para la clase TabFragment con un valor de 2 NOT 1, así que las pestañas No se están actualizando correctamente.
- ViewPager + PagerAdapter muestra páginas en blanco después de los dos primeros elementos
- Utilizar Pull to Refresh gridview en viewpager en Activity within ActivityGroup provoca ClassCastException
- Infinite Scrolling Image ViewPager
- Viewpager + webview, cómo detener la carga de la webview
- Botón de acción flotante en una actividad - ¿cómo anclar a una vista de reciclaje en un fragmento?
¡¡Cualquier ayuda será muy apreciada!!
Código para crear las pestañas,
// For each of the sections in the app, add a tab to the action bar. for (int i = 0; i < mCollectionPagerAdapter.getCount(); i++) { mActionBar.addTab(mActionBar.newTab() .setText(mGenres.get(i).getName()) .setTabListener(this)); //Let's request the movies for the first three genres new GetMoviesByGenre().execute(mGenres.get(i).getId()); }
Cuando se selecciona una pestaña,
@Override public void onTabSelected(ActionBar.Tab tab, android.app.FragmentTransaction arg1) { //Let's update the dataset for the selected genre TabFragment fragment = (TabFragment) getSupportFragmentManager().findFragmentByTag( "android:switcher:"+R.id.pager+":"+tab.getPosition()); if(fragment != null) // could be null if not instantiated yet { if(fragment.getView() != null) { fragment.updateDisplay(tab.getPosition()); // do what updates are required } } mViewPager.setCurrentItem(tab.getPosition()); }
Clase CollectionPageAdapter
public class CollectionPagerAdapter extends FragmentPagerAdapter { final int NUM_ITEMS = 3; // number of tabs List<Fragment> fragments = new ArrayList<Fragment>(); public Fragment getItem(int pos) { return fragments.get(pos); } public void addFragment(Fragment f) { fragments.add(f); } public CollectionPagerAdapter(FragmentManager fm) { super(fm); //Let's add the fragments for (int i=0;i<NUM_ITEMS;i++) { Fragment fragment = new TabFragment(); Bundle args = new Bundle(); args.putInt(TabFragment.ARG_OBJECT, 0); fragment.setArguments(args); addFragment (fragment); } } @Override public int getCount() { return NUM_ITEMS; }
}
Clase TabFragment
public class TabFragment extends ListFragment { public static final String ARG_OBJECT = "object"; private MoviesAdapter m_Adapter; private ArrayList <Movie> mMovies = new ArrayList<Movie>(); @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // you only need to instantiate these the first time your fragment is // created; then, the method above will do the rest if (m_Adapter == null) { m_Adapter = new MoviesAdapter(getActivity(), mMovies); } setListAdapter(m_Adapter); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { int position = getArguments().getInt(ARG_OBJECT); // to check is the right fragment View rootView = inflater.inflate(R.layout.tabs, container, false); return rootView; } public void updateDisplay (int type) { GlobalVars gv = (GlobalVars)getActivity().getApplicationContext(); switch (type) { case 0: mMovies = gv.getActionMovies(); break; case 1: mMovies = gv.getAdventureMovies(); break; case 2: mMovies = gv.getAnimationMovies(); break; } m_Adapter.notifyDataSetChanged(); }
}
No hago lo que estoy haciendo mal, supongo que los fragmentos están desordenados, porque cuando presiono la segunda pestaña, los datos de la primera pestaña se actualiza, y así sucesivamente …
¡Gracias!
- Segundo conjunto de pestañas en un fragmento de Android
- Ver Pager Crash Null Pointer Excepción debido a navegar de nuevo al fragmento antiguo - Android
- Deshabilitar y habilitar la paginación en ViewPager en Android
- Contenido de Viewpager perdido en rotación
- No se puede cambiar ID de contenedor de fragmento
- ViewPager no muestra nada
- Actualizar / Recargar / Re instanciar un fragmento en un sistema de pestañas android
- Fragment onResume () no se llama cuando se utiliza FragmentPagerAdapter
En lugar de usar CollectionPageAdapter, cambié para usar la clase TabsAdapter mostrada en la documentación de ViewPager de Android y funciona!
public class TabsAdapter extends FragmentPagerAdapter implements ActionBar.TabListener, ViewPager.OnPageChangeListener { private final Context mContext; private final ActionBar mActionBar; private final ViewPager mViewPager; private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>(); private final List<Fragment> fragments = new ArrayList<Fragment>(); static final class TabInfo { private final Class<?> clss; private final Bundle args; TabInfo(Class<?> _class, Bundle _args) { clss = _class; args = _args; } } public TabsAdapter(FragmentActivity activity, ViewPager pager) { super(activity.getSupportFragmentManager()); mContext = activity; mActionBar = activity.getActionBar(); mViewPager = pager; mViewPager.setAdapter(this); mViewPager.setOnPageChangeListener(this); } public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) { TabInfo info = new TabInfo(clss, args); tab.setTag(info); tab.setTabListener(this); mTabs.add(info); mActionBar.addTab(tab); notifyDataSetChanged(); } @Override public int getCount() { return mTabs.size(); } @Override public int getItemPosition(Object object) { return POSITION_NONE; } @Override public Fragment getItem(int position) { TabInfo info = mTabs.get(position); Fragment fr = Fragment.instantiate(mContext, info.clss.getName(), info.args); //addFragment (fr, position); return fr; } public void addFragment(Fragment f, int location) { if (fragments.size() == 0) fragments.add(f); else fragments.add(location, f); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { mActionBar.setSelectedNavigationItem(position); } @Override public void onPageScrollStateChanged(int state) { } @Override public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) { Object tag = tab.getTag(); for (int i=0; i<mTabs.size(); i++) { if (mTabs.get(i) == tag) { updateDatasetMovies (i); mViewPager.setCurrentItem(i); } } } @Override public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) { // TODO Auto-generated method stub } @Override public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) { // TODO Auto-generated method stub } public void updateDatasetMovies (int pos) { //Let's update the dataset for the selected genre TabFragment fragment = (TabFragment) ((FragmentActivity)mContext).getSupportFragmentManager().findFragmentByTag( "android:switcher:"+R.id.pager+":"+pos); //TabFragment fragment = (TabFragment) getItem(pos); if(fragment != null) // could be null if not instantiated yet { if(fragment.getView() != null) { // no need to call if fragment's onDestroyView() //has since been called. fragment.updateDisplay(pos); // do what updates are required } } }
Todos los derechos reservados
Estoy de acuerdo con nirvik en esto, sin embargo hay una mejora cruciual que debe hacerse. Esta implementación tiene una falla: al pasar a un fragmento siguiente se invoca el método onPageSelected, que a su vez invoca el método onTabSelected llamando a mActionBar.setSelectedNavigationItem (position) ;. Esto provoca un parpadeo en la animación. Esta:
viewPager.setCurrentItem(i);
Debe sustituirse por el siguiente:
if(i != viewPager.getCurrentItem()) { viewPager.setCurrentItem(i); }
Resultando en una transición suave.
Puede intentar incluir el código siguiente en su FragmentPagerAdapter
y ver si esto soluciona el problema.
public int getItemPosition(Object object) { return POSITION_NONE; }
También puede intentar usar un FragmentStatePagerAdapter
.
- NVidia PerfHUD ES Tegra en Google Nexus 7
- Crear forzosamente nuevo contacto cuando inserte nuevo contacto en bruto