web-dev-qa-db-fra.com

FragmentPagerAdapter - comment détecter un glissement ou un clic d'onglet lorsque l'utilisateur accède à un nouvel onglet?

J'ai un MainActivity qui a trois fragments dans un FragmentPagerAdapter comme ci-dessous. Comment savoir quand un utilisateur passe du 1er fragment au second ou du deuxième au troisième, soit en glissant, soit en cliquant sur l'onglet? J'ai vu que la méthode getItem() n'est pas toujours appelée car j'ai déclaré 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;
    }
}

Dans la onCreate() de MainActivity

    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

La méthode getItem() n'est appelée que lors de la création d'une vue. Pour comprendre pourquoi getItem() n'est pas appelé, il est utile de comprendre le comportement par défaut d'un ViewPager. Par défaut, lorsque vous êtes sur une page particulière d'un ViewPager, il crée également les pages qui se trouvent avant et après cette page particulière. Si vous deviez avoir 3 fragments nommés et dans cet ordre [a, b, c], et que vous étiez à la page b, en raison du comportement par défaut des fragments ViewPager a et c seraient déjà créés avec un appel à la fonction getItem(int). Parce que les fragments sont déjà créés, vous n'obtiendrez pas un autre appel à getItem()

En plus: ce comportement peut être modifié avec ViewPager.setOffScreenLimit()

Ce que vous voulez réellement faire pour être averti lorsqu'un utilisateur change de page, c'est définir OnPageChangeListener sur ViewPager en utilisant ViewPager.addOnPageChangeListener() pour être averti lorsqu'une page est sélectionnée.

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
Hamidreza Sadegh

Tout d'abord, je suppose que vous avez les champs déclarés suivants

ViewPager pager;
TabLayout tabs;
MainThreeTabAdapter adapter;

Vous devez ensuite créer votre instance d'adaptateur et la définir sur pager. Ici, vous pouvez ajouter un écouteur appelant addOnPageChangeListener

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

Toujours lorsque la page passe à une nouvelle en faisant glisser ou en cliquant sur l'onglet, la méthode onPageSelected(int position) sera appelée.

Si vous voulez que l'instance réelle du fragment actuel interagisse directement avec lui, vous pouvez créer votre propre FragmentPagerAdapter qui devrait mettre en cache les fragments créés:

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 cette façon, vous devez

  1. étendez votre MainThreeTabAdapter à partir de CachingFragmentPagerAdapter
  2. ajoutez addOnPageChangeListener à ViewPager
  3. rechercher et interagir avec un fragment dans la méthode onPageSelected comme suit:

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

Si, comme je suppose que vous utilisez un TabLayout avec votre ViewPager, vous devez utiliser addOnTabSelectedListener (). Cela gérera à la fois un clic d'onglet explicite ou un balayage.

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