次のように、MainActivity
に3つのフラグメントを持つFragmentPagerAdapter
があります。ユーザーがスワイプまたはタブをクリックして、1番目のフラグメントから2番目または2番目から3番目のフラグメントに移動したことを確認するにはどうすればよいですか? 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;
}
}
_
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()
で修正できます
ユーザーがページを切り替えたときに通知を受けるために実際にしたいことは、 ViewPager.addOnPageChangeListener()
を使用して OnPageChangeListener
をViewPager
に設定することです。ページが選択されています。
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) {
}
});
まず、次の宣言済みフィールドがあると思います
_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 ...
}
_
ViewPagerでTabLayoutを使用していると思われる場合、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());
}
});