viewpager tablayout practice pagetransformer example best android android-fragments android-viewpager android-tabhost android-pageradapter

practice - tablayout android example



FragmentPagerAdapter: ¿cómo detectar un deslizamiento o un clic de pestaña cuando el usuario accede a una nueva pestaña? (4)

El método getItem() solo se llama cuando se crea una vista. Para comprender por qué no se llama a getItem() , ayuda a comprender el comportamiento predeterminado de un ViewPager . De forma predeterminada, cuando está en una página particular de un ViewPager , también crea las páginas que están antes y después de esta página en particular. Si tuviera 3 fragmentos nombrados y en este orden [a, b, c], y estuviera en la página b, debido al comportamiento predeterminado de los fragmentos de ViewPager a y c ya se crearía con una llamada a getItem(int) . Debido a que los fragmentos ya están creados, no recibirá otra llamada a getItem()

Aparte: este comportamiento se puede modificar con ViewPager.setOffScreenLimit()

Lo que realmente desea hacer para recibir una notificación cuando un usuario cambia de página es configurar un OnPageChangeListener para el ViewPager usando ViewPager.addOnPageChangeListener() para que se le notifique cuando se selecciona una página.

Tengo una MainActivity que tiene tres fragmentos en un FragmentPagerAdapter como se muestra a continuación. ¿Cómo puedo saber cuándo un usuario pasa del primer fragmento al segundo o del segundo al tercero, con solo deslizar o haciendo clic en la pestaña? Vi que el método getItem() no se llama siempre, ya que he declarado mViewPager.setOffscreenPageLimit(2) ;

public class MainThreeTabAdapter extends FragmentPagerAdapter { private final String[] CONTENT = new String[]{"News", "Rewards", "Me"}; public MainThreeTabAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { if (position == 0) { return NewsFragment.newInstance(); } else if (position == 1) { return RewardsFragment.newInstance(); } else if (position == 2) { return MeFragment.newInstance(true, App.getAccountData().getId()); } else { return null; } } @Override public CharSequence getPageTitle(int position) { return CONTENT[position % CONTENT.length]; } @Override public int getCount() { return CONTENT.length; } }

En el onCreate de onCreate()

mainThreeTabAdapter = new MainThreeTabAdapter(getFragmentManager()); // Set up the ViewPager with the sections adapter. // this ensures that 2 tabs on each side of current are kept in memory, which is all we need for our case. Default = 1 // this is all taken from the Quickreturn facebook sample app mViewPager.setOffscreenPageLimit(2); mViewPager.setAdapter(mainThreeTabAdapter);


En primer lugar supongo que tienes los siguientes campos declarados.

ViewPager pager; TabLayout tabs; MainThreeTabAdapter adapter;

A continuación, debe crear su instancia de adaptador y establecerla en paginador. Aquí puede agregar oyente llamando a addOnPageChangeListener

adapter = new MainThreeTabAdapter(getSupportFragmentManager()); pager.setAdapter(adapter); pager.addOnPageChangeListener(/*here is your listener instance*/); tabs.setupWithViewPager(pager);

Siempre que la página cambie a una nueva al deslizar o hacer clic en la pestaña, se onPageSelected(int position) al método onPageSelected(int position) .

Si desea obtener una instancia real del fragmento actual para interactuar con él directamente, puede crear su propio FragmentPagerAdapter que debería almacenar en caché los fragmentos creados:

public abstract class CachingFragmentPagerAdapter extends FragmentPagerAdapter { private final SparseArray<Fragment> registeredFragments = new SparseArray<>(); public CachingFragmentPagerAdapter(FragmentManager fm) { super(fm); } @Override public Object instantiateItem(ViewGroup container, int position) { Fragment fragment = (Fragment) super.instantiateItem(container, position); registeredFragments.put(position, fragment); return fragment; } @Override public void destroyItem(ViewGroup container, int position, Object object) { registeredFragments.remove(position); super.destroyItem(container, position, object); } public Fragment getRegisteredFragment(int position) { return registeredFragments.get(position); } public SparseArray<Fragment> getRegisteredFragments() { return registeredFragments; } }

De esta manera tienes que

  1. extienda su MainThreeTabAdapter desde CachingFragmentPagerAdapter
  2. agregar addOnPageChangeListener a ViewPager
  3. encuentre e interactúe con el fragmento en el método onPageSelected como sigue:

    public void onPageSelected(int position) { final Fragment fragment = adapter.getRegisteredFragment(position); if (fragment instanceof NewsFragment) { //... } else ... }


Si asumo que está usando un TabLayout con su ViewPager, debería usar addOnTabSelectedListener (). Esto manejará tanto un clic de tabulación explícito como un deslizamiento.

mTabLayout.setupWithViewPager(mViewPager); mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { Logger.d(TAG, "tabSelected: " + tab.getPosition()); } @Override public void onTabUnselected(TabLayout.Tab tab) { Logger.d(TAG, "tabUnselected: " + tab.getPosition()); } @Override public void onTabReselected(TabLayout.Tab tab) { Logger.d(TAG, "tabReselected: " + tab.getPosition()); } });


mViewPager.setAdapter(mSectionsPagerAdapter); mViewPager.setOffscreenPageLimit(4); mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { _position = position; switch (position) { case 0: _header.setButtonVisible(1, View.GONE); break; case 1: _header.setButtonVisible(1, View.GONE); break; case 2: _header.setButtonVisible(1, View.VISIBLE); break; case 3: _header.setButtonVisible(1, View.VISIBLE); break; } } @Override public void onPageScrollStateChanged(int state) { } });