Я стараюсь иметь такой же дизайн view pager + tabs
, что и в PlayStore 5.1.x. Вот мой макет:Показанный первый фрагмент ViewPager всегда неверен с 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>
Мой адаптер:
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;
}
}
Мои закладки и пейджера показываются правильно! но я заметил, что первый фрагмент, показанный в пейджере просмотра, всегда совпадает со вторым. Затем, когда я прокручиваю один раз, дважды и перебираю обратно на первую страницу, я обнаружил, что теперь отображается правильный фрагмент !!
Я не могу понять, почему это поведение, пожалуйста, мне нужны объяснения.
РЕШЕНИЕ
Проблема была из-за мое определение FakeFragment.newInstance()
метода.
private static int position;
public static FakeFragment newInstance(int position) {
// TODO Auto-generated method stub
FakeFragment.position = position;
return new FakeFragment();
}
Я изменил его, используя setArguments(args)
моих FakeFragment
например, а затем получить его в onCreate
методы. Теперь все работает хорошо!
Может кто-нибудь объяснить мне, почему?
Я думаю, что таким образом значение позиции будет зависеть от жизненного цикла фрагмента, так что всегда будет ожидаемой позицией, правильно?
Избавьтесь от 'private ArrayList фрагментов' и просто получив' getItem() 'возвращаемый новый экземпляр фрагмента. ** полная и целая * точка *** позади «FragmentStatePagerAdapter» - это ** NOT ** удерживать все фрагменты в памяти. Если это то, что вы хотите, тогда все равно избавитесь от 'ArrayList 'и переключите ваш адаптер как« FragmentPagerAdapter », а не« FragmentStatePagerAdapter ». Также избавьтесь от 'getItemPosition()'. [FWIW, вот серия примеров «приложений для просмотра ViewPager» (https://github.com/commonsguy/cw-omnibus/tree/master/ViewPager). –
CommonsWare
Спасибо @CommonsWare. Я выбрал «FragmentStatePagerAdapter», потому что у меня 6 страниц в моем «ViewPager», на каждой странице у меня есть «GridView» со многими данными для отображения.Вот почему я хотел использовать этот тип адаптера, чтобы воссоздать страницу или обновить ее контент только при необходимости. Вот почему я также попытался переопределить 'getItemPosition'. Возможно ли это с помощью «FragmentPagerAdapter»? Еще раз спасибо за ответ! –
Ваша реализация должна работать правильно в обоих случаях, единственной особенностью может быть скорость. Если загрузка данных стоит дорого, и вам не нужно ее каждый раз использовать 'FragmentStatePagerAdapter', используйте' Fragment.onSaveInstanceState' для хранения загруженного набора данных. –