Jak zmienić stronę ViewPager?

150

Używam ViewPagera w mojej aplikacji i definiuję go w głównym działaniu. Wewnątrz onCreatemetody ładuję pewną liczbę stron z SharedPreferences i przekazuję to do PagerAdapter:

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

Problem polega na tym, że gdybym zmienił tę liczbę w Preferencjach (lub innym działaniu) na inny indeks strony, który wcześniej przeglądałem, moja aplikacja ulega awarii, ponieważ ten indeks jest poza zakresem, kiedy wracam do działania z tym ViewPager. Można to naprawić po prostu zmieniając aktywną stronę ViewPager. Czy jest na to sposób?

rzymski
źródło

Odpowiedzi:

394

Nie jestem pewien, czy w pełni rozumiem pytanie, ale z tytułu Twojego pytania domyślam się, że właśnie tego szukasz pager.setCurrentItem( num ). Umożliwia to programowe przełączanie się na inną stronę w ramach ViewPager.

Musiałbym zobaczyć ślad stosu z logcat, aby być bardziej szczegółowym, jeśli to nie jest problem.

Mark Allison
źródło
3
Tak, właśnie tego potrzebuję. Ustawiłem to na 0w onPausemetodzie i nie ma awarii. Dzięki.
Roman
1
Rzeczywiście jest bardzo mniej dokumentacji na ViewPager. +1 za to.
Arnab Chakraborty
1
jeśli załadowanie strony zajmuje Twojemu pagerowi dużo czasu, to możesz użyć setOffscreenPageLimit (1), ponieważ domyślnie przeglądaj pager wczytuj stronę +1 i -1 z aktualnej pozycji
Ajay Pandya
To nie działa, po prostu pojawia się błąd informujący, że fragment został już dodany.
BlondeSwan
24

przesuń w prawo

viewPager.arrowScroll (View.FOCUS_RIGHT);

przesuń w lewo

viewPager.arrowScroll (View.FOCUS_LEFT);

Abror Esonaliyev
źródło
krótkie i czyste!
dakshbhatt21
1
Prawie uważam, że powinna to być akceptowana odpowiedź. Jest to o wiele bardziej praktyczne niż ustawienie bieżącego elementu.
Peter
18

Bez sprawdzania kodu myślę, że opisujesz to, że Twoje strony nie są zsynchronizowane i masz nieaktualne dane.

Mówisz, że zmieniasz liczbę stron, a następnie ulega awarii, ponieważ uzyskujesz dostęp do starego zestawu stron. Wydaje mi się, że nie dzwoniszpageAdapter.notifyDataSetChanged() po zmianie danych.

Kiedy viewPagerpokazujesz stronę 3 z zestawu 10 stron i zmieniasz zestaw na tylko 5, a następnie zadzwoń notifyDataSetChanged(), zobaczysz, że przeglądasz teraz stronę 3 nowego zestawu. Jeśli poprzednio przeglądałeś stronę 8 starego zestawu, po włożeniu nowego zestawu i wywołaniu notifyDataSetChanged()zobaczysz, że teraz przeglądasz ostatnią stronę nowego zestawu bez awarii.

Jeśli po prostu zmienisz bieżącą stronę, możesz po prostu maskować problem.

Richard P.
źródło
1
plus 1 dla notifyDataSetChanged ()
madhu527
@Richard Ratujesz mojego dnia, kolego. 10000+ zanotifyDataSetChanged()
Ali
15

aby przejść na inną stronę, wypróbuj ten kod:

viewPager.postDelayed(new Runnable()
{
    @Override
    public void run()
    {
        viewPager.setCurrentItem(num, true);
    }
}, 100);
David Figueroa
źródło
1
Idealny! Próbowałem go użyć bez metody postDelay i nie działa. Czy wiesz, dlaczego działa z tą metodą? Dzięki! :)
Georgi Koemdzhiev
To samo pytanie ... dlaczego pozycja zmienia się z tym opóźnieniem, a nie inaczej?
Kalyan Raghu
@GeorgiKoemdzhiev Ponieważ widok nie jest jeszcze zakończony, gdy dzwoniszviewPager.setCurrentItem
Zohab Ali
3

Dodatkowa odpowiedź

Początkowo miałem problem z uzyskaniem odwołania do ViewPagermetody innych klas, ponieważ addOnTabSelectedListenerutworzono anonimową klasę wewnętrzną, która z kolei wymagała ViewPagerzadeklarowania zmiennej final. Rozwiązaniem było użycie zmiennej składowej klasy i nie używanie anonimowej klasy wewnętrznej.

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
źródło