web-dev-qa-db-ja.com

FragmentPagerAdapter-ユーザーが新しいタブに移動したときにスワイプまたはタブクリックを検出する方法

次のように、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;
    }
}
_

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);
_
18
dowjones123

getItem()メソッドは、ビューの作成時にのみ呼び出されます。 getItem()が呼び出されない理由を理解するには、ViewPagerのデフォルトの動作を理解すると役立ちます。デフォルトでは、ViewPagerの特定のページにいる場合、この特定のページの前後のページも作成されます。名前が3つのフラグメントがあり、この順序で[a、b、c]があり、ページbにいた場合、ViewPagerのデフォルトの動作により、フラグメントaおよびcはgetItem(int)。フラグメントはすでに作成されているため、getItem()への別の呼び出しはありません

余談:この動作は ViewPager.setOffScreenLimit() で修正できます

ユーザーがページを切り替えたときに通知を受けるために実際にしたいことは、 ViewPager.addOnPageChangeListener() を使用して OnPageChangeListenerViewPagerに設定することです。ページが選択されています。

26
Andrew Orobator
    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) {

        }
    });
3

まず、次の宣言済みフィールドがあると思います

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

このようにして

  1. MainThreeTabAdapterからCachingFragmentPagerAdapterを拡張します
  2. addOnPageChangeListenerViewPagerに追加します
  3. 次のようなonPageSelectedメソッドでフラグメントを見つけて操作します。

    _public void onPageSelected(int position) {
        final Fragment fragment = adapter.getRegisteredFragment(position);
        if (fragment instanceof NewsFragment) {
            //...
        } else ...
    }
    _
2
Igor Tyulkanov

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