Próbuję mieć ten sam projekt view pager + tabs
jak PlayStore 5.1.x. Oto mój plan:Pierwszy pokazany fragment programu ViewPager zawsze jest nieprawidłowy przy użyciu fragmentu FragmentStatePager
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|center_horizontal"
android:gravity="center_vertical|center_horizontal"
android:orientation="vertical">
<com.astuetz.PagerSlidingTabStrip
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/background_tabs" />
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Moja Adapter:
public class MainPagerAdapter extends FragmentStatePagerAdapter {
private ArrayList<FakeFragment> fragments;
public MainPagerAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
fragments = new ArrayList<FakeFragment>();
}
@Override
public Fragment getItem(int position) {
// TODO Auto-generated method stub
if(position < getCount()) {
FakeFragment fragment = FakeFragment.newInstance(position);
fragments.add(fragment);
}
return fragments.get(position);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return Category.values().length;
}
@Override
public CharSequence getPageTitle(int position) {
// TODO Auto-generated method stub
return Category.values()[position].getTitle();
}
@Override
public int getItemPosition(Object object) {
// TODO Auto-generated method stub
return POSITION_NONE;
}
}
Moje zakładki i pager są wyświetlane poprawnie! ale zauważyłem, że pierwszy fragment wyświetlany w okienku widokowym jest zawsze taki sam jak drugi. Następnie, gdy przesunę raz, dwa razy i przesunę z powrotem na pierwszą stronę, stwierdzam, że właściwy fragment jest teraz wyświetlany !!
Nie mogę zrozumieć, dlaczego to zachowanie, potrzebuję pewnych wyjaśnień.
ROZWIĄZANIE
Problem był z powodu mojej definicji FakeFragment.newInstance()
metody.
private static int position;
public static FakeFragment newInstance(int position) {
// TODO Auto-generated method stub
FakeFragment.position = position;
return new FakeFragment();
}
Zmieniłem go za pomocą setArguments(args)
do mojego instancji FakeFragment
, a następnie pobrać ją onCreate
metody. Teraz wszystko działa dobrze!
Czy ktoś może mi wyjaśnić, dlaczego?
Myślę, że w ten sposób wartość pozycji będzie zależała od cyklu życia fragmentu, więc zawsze będzie to oczekiwana pozycja, prawda?
Pozbądź się 'private ArrayList i po prostu' getItem() 'zwróć nowe wystąpienie fragmentu. ** ** kompletny i cały * punkt *** za 'FragmentStatePagerAdapter' to ** NOT ** przytrzymaj na wszystkich fragmentach w pamięci. Jeśli tego chcesz, to pozbyć się 'ArrayList ' i zmienić adapter na 'FragmentPagerAdapter', a nie' FragmentStatePagerAdapter'. Również pozbyć się 'getItemPosition()'. [FWIW, oto seria przykładowych aplikacji "ViewPager"] (https://github.com/commonsguy/cw-omnibus/tree/master/ViewPager). –
CommonsWare
Dzięki @CommonsWare. Wybrałem 'FragmentStatePagerAdapter', ponieważ mam 6 stron w moim' ViewPager', na każdej stronie mam 'GridView' z wieloma danymi do pokazania.Właśnie dlatego chciałem użyć tego rodzaju adaptera, aby odtworzyć stronę lub odświeżyć jej zawartość tylko w razie potrzeby. Dlatego też próbowałem przesłonić 'getItemPosition'. Czy jest to możliwe z 'FragmentPagerAdapter'? Jeszcze raz dziękuję za odpowiedź! –
Twoja implementacja powinna działać poprawnie w obu przypadkach, jedyną różnicą może być szybkość. Jeśli ładowanie danych jest drogie i nie musisz tego robić za każdym razem, użyj 'FragmentStatePagerAdapter', użyj' Fragment.onSaveInstanceState', aby zapisać załadowany zestaw danych. –