Comment changer la page de ViewPager?

150

J'utilise ViewPager dans mon application et je le définis dans l'activité principale. À l'intérieur de la onCreateméthode, je charge un certain nombre de pages à partir de SharedPreferences, puis je le transmets à PagerAdapter:

@Override
public int getCount() {
    return numberOfPages;
}

Le problème est que si je devais changer ce nombre dans Préférences (ou une autre activité) en un autre index de page inférieur à celui que j'ai consulté auparavant, mon application se bloque car cet index est hors limites lorsque je reviens à l'activité avec ce ViewPager. Il peut être corrigé simplement en modifiant la page active de ViewPager. Y a-t-il un moyen de le faire?

romain
la source

Réponses:

394

Je ne suis pas sûr de bien comprendre la question, mais d'après le titre de votre question, je suppose que c'est ce que vous cherchez pager.setCurrentItem( num ). Cela vous permet de passer par programme à une autre page dans le ViewPager.

J'aurais besoin de voir une trace de pile de logcat pour être plus précis si ce n'est pas le problème.

Mark Allison
la source
3
Oui, c'est exactement ce dont j'ai besoin. Je l'ai mis 0dans la onPauseméthode et il n'y a pas de crash. Merci.
Roman
1
Il y a en effet très moins de documentation sur ViewPager. +1 pour ça.
Arnab Chakraborty
1
si votre téléavertisseur prend beaucoup de temps pour charger la page, vous pouvez utiliser setOffscreenPageLimit (1), car par défaut, afficher le pager charger +1 et -1 page à partir de la position actuelle
Ajay Pandya
Cela ne fonctionne pas. J'obtiens juste une erreur indiquant que le fragment a déjà été ajouté.
BlondeSwan
24

glisser vers la droite

viewPager.arrowScroll (View.FOCUS_RIGHT);

glisser vers la gauche

viewPager.arrowScroll (View.FOCUS_LEFT);

Abror Esonaliyev
la source
court et propre!
dakshbhatt21
1
Je crois presque que cela devrait être la réponse acceptée. C'est beaucoup plus pratique que de définir l'élément actuel.
Peter
18

Sans vérifier votre code, je pense que ce que vous décrivez, c'est que vos pages ne sont pas synchronisées et que vous avez des données périmées.

Vous dites que vous modifiez le nombre de pages, puis que vous vous plantez parce que vous accédez à l'ancien ensemble de pages. Il me semble que vous n'appelez pas pageAdapter.notifyDataSetChanged()après avoir modifié vos données.

Lorsque vous viewPageraffichez la page 3 d'un ensemble de 10 pages, et que vous passez à un ensemble avec seulement 5, puis appelez notifyDataSetChanged(), vous constaterez que vous visualisez maintenant la page 3 du nouvel ensemble. Si vous consultiez précédemment la page 8 de l'ancien ensemble, après avoir inséré le nouvel ensemble et appelé, notifyDataSetChanged()vous constaterez que vous visualisez maintenant la dernière page du nouvel ensemble sans planter.

Si vous modifiez simplement votre page actuelle, vous ne faites peut-être que masquer le problème.

RichardP
la source
1
plus 1 pour notifyDataSetChanged ()
madhu527
@Richard Vous sauvez mon copain de jour. 10000+ pournotifyDataSetChanged()
Ali
15

pour passer à une autre page, essayez avec ce code:

viewPager.postDelayed(new Runnable()
{
    @Override
    public void run()
    {
        viewPager.setCurrentItem(num, true);
    }
}, 100);
David Figueroa
la source
1
Parfait! J'ai essayé de l'utiliser sans la méthode postDelay et cela n'a pas fonctionné. Savez-vous pourquoi cela fonctionne avec cette méthode? Merci! :)
Georgi Koemdzhiev
Même question ... pourquoi l'article change-t-il avec ce délai et pas autrement?
Kalyan Raghu
@GeorgiKoemdzhiev Parce que la vue n'est pas encore terminée lorsque vous appelezviewPager.setCurrentItem
Zohab Ali
3

Réponse supplémentaire

À l'origine, j'avais du mal à obtenir une référence à la à ViewPagerpartir d'autres méthodes de classe parce que la addOnTabSelectedListenerclasse interne était anonyme, ce qui nécessitait à son tour que la ViewPagervariable soit déclarée final. La solution consistait à utiliser une variable membre de classe et non à utiliser la classe interne anonyme.

public class MainActivity extends AppCompatActivity {

    TabLayout tabLayout;
    ViewPager viewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
        tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
        tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
        tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);

        viewPager = (ViewPager) findViewById(R.id.pager);
        final PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
        viewPager.setAdapter(adapter);
        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));

        // don't use an anonymous inner class here
        tabLayout.addOnTabSelectedListener(tabListener);

    }

    TabLayout.OnTabSelectedListener tabListener = new TabLayout.OnTabSelectedListener() {

        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            viewPager.setCurrentItem(tab.getPosition());
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    };

    // The view pager can now be accessed here, too.
    public void someMethod() {
        viewPager.setCurrentItem(0);
    }

}
Suragch
la source