FragmentPagerAdapter – как обнаружить салфетки или вкладку, когда пользователь переходит на новую вкладку?

У меня есть MainActivity , у которого есть три фрагмента в FragmentPagerAdapter как MainActivity ниже. Как я могу узнать, когда пользователь переходит от 1-го фрагмента к второму или от второго к третьему, либо с помощью прокрутки, либо с помощью щелчка по вкладке? Я видел, что метод getItem() не вызывается всегда, поскольку я объявил 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; } } 

В MainActivity's 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); 

Метод getItem() вызывается только при создании представления. Чтобы понять, почему getItem() не вызывается, он помогает понять поведение по умолчанию ViewPager . По умолчанию, когда вы находитесь на определенной странице ViewPager он также создает страницы, которые находятся до и после этой конкретной страницы. Если у вас должно было быть 3 фрагмента, названных и в этом порядке [a, b, c], и вы были на странице b, из-за поведения по умолчанию для фрагментов ViewPager a и c уже были бы созданы с вызовом getItem(int) . Поскольку фрагменты уже созданы, вы не получите другого вызова getItem()

Кроме того: это поведение можно изменить с помощью ViewPager.setOffScreenLimit()

То, что вы на самом деле хотите сделать, чтобы получать уведомления, когда пользователь переключает страницы, – это установить OnPageChangeListener в ViewPager используя ViewPager.addOnPageChangeListener() чтобы получать уведомление, когда выбрана страница.

Прежде всего, я предполагаю, что у вас есть следующие объявленные поля

 ViewPager pager; TabLayout tabs; MainThreeTabAdapter adapter; 

Затем вам нужно создать экземпляр адаптера и установить его в пейджер. Здесь вы можете добавить прослушиватель вызова addOnPageChangeListener

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

Всегда, когда страница переключается на новую, нажимая или нажимая на вкладку, onPageSelected(int position) метод onPageSelected(int position) .

Если вы хотите, чтобы фактический экземпляр текущего фрагмента взаимодействовал с ним напрямую, вы можете создать свой собственный FragmentPagerAdapter который должен кэшировать созданные фрагменты:

 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; } } 

Таким образом, вы должны

  1. MainThreeTabAdapter свой MainThreeTabAdapter от CachingFragmentPagerAdapter
  2. Добавить addOnPageChangeListener в ViewPager
  3. Найти и взаимодействовать с фрагментом в onPageSelected например, следующим образом:

     public void onPageSelected(int position) { final Fragment fragment = adapter.getRegisteredFragment(position); if (fragment instanceof NewsFragment) { //... } else ... } 
  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) { } }); 

Если, как я полагаю, вы используете TabLayout с ViewPager, вы должны использовать addOnTabSelectedListener (). Это будет обрабатывать как явный щелчок на вкладке, так и салфетки.

 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()); } });