FragmentPagerAdapter - как определить салфетки или щелчок на вкладке, когда пользователь переходит на новую вкладку?
У меня есть MainActivity
, который имеет три фрагмента в FragmentPagerAdapter
, как показано ниже. Как я могу узнать, когда пользователь переходит от 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 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);
Ответы
Ответ 1
Метод getItem()
вызывается только при создании представления. Чтобы понять, почему getItem()
не вызывается, он помогает понять поведение по умолчанию ViewPager
. По умолчанию, когда вы находитесь на определенной странице ViewPager
, он также создает страницы, которые находятся до и после этой конкретной страницы. Если бы у вас было 3 фрагмента, названных и в этом порядке [a, b, c], и вы были на странице b, из-за поведения по умолчанию фрагментов ViewPager a и c уже были бы созданы с вызовом getItem(int)
, Поскольку фрагменты уже созданы, вы не получите другой вызов getItem()
Кроме того: это поведение можно изменить с помощью ViewPager.setOffScreenLimit()
Что вы на самом деле хотите сделать, чтобы получать уведомления, когда пользователь переключает страницы, нужно установить OnPageChangeListener
в ViewPager
используя ViewPager.addOnPageChangeListener()
, чтобы получать уведомления о выборе страницы.
Ответ 2
Прежде всего, я предполагаю, что у вас есть следующие объявленные поля
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)
.
Если вы хотите, чтобы фактический экземпляр текущего фрагмента взаимодействовал с ним напрямую, вы можете создать свой собственный 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;
}
}
Таким образом, вы должны
- расширьте
MainThreeTabAdapter
от CachingFragmentPagerAdapter
- добавить
addOnPageChangeListener
в ViewPager
-
найти и взаимодействовать с фрагментом в onPageSelected
, например, следующим образом:
public void onPageSelected(int position) {
final Fragment fragment = adapter.getRegisteredFragment(position);
if (fragment instanceof NewsFragment) {
//...
} else ...
}
Ответ 3
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) {
}
});
Ответ 4
Если, как я полагаю, вы используете 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());
}
});