Внутренний фрагмент ViewPager, как сохранить состояние?
В моем приложении активность фрагмента содержит два фрагмента: фрагмент A и фрагмент B. Фрагмент B - это пейджер представления, содержащий 3 фрагмента.
![enter image description here]()
В моей деятельности, чтобы предотвратить повторное создание фрагмента при изменении конфигурации:
if(getSupportFragmentManager().findFragmentByTag(MAIN_TAB_FRAGMENT) == null) {
getSupportFragmentManager().beginTransaction().replace(R.id.container, new MainTabFragment(), MAIN_TAB_FRAGMENT).commit();
}
Код для фрагмента B:
public class MainTabFragment extends Fragment {
private PagerSlidingTabStrip mSlidingTabLayout;
private LfPagerAdapter adapter;
private ViewPager mViewPager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_tab, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
this.adapter = new LfPagerAdapter(getChildFragmentManager());
this.mViewPager = (ViewPager) view.findViewById(R.id.viewpager);
this.mViewPager.setAdapter(adapter);
this.mSlidingTabLayout = (PagerSlidingTabStrip) view.findViewById(R.id.sliding_tabs);
this.mSlidingTabLayout.setViewPager(this.mViewPager);
}
}
Код адаптера:
public class LfPagerAdapter extends FragmentPagerAdapter {
private static final int NUM_ITEMS = 3;
private FragmentManager fragmentManager;
public LfPagerAdapter(FragmentManager fm) {
super(fm);
this.fragmentManager = fm;
}
@Override
public int getCount() {
return NUM_ITEMS;
}
@Override
public Fragment getItem(int position) {
Log.d("TEST","TEST");
switch (position) {
case 1:
return FragmentC.newInstance();
case 2:
return FragmentD.newInstance();
default:
return FragmentE.newInstance();
}
}
}
Моя проблема в том, что я не могу сохранить состояние пейджера представления и его дочерние фрагменты при изменении ориентации.
Очевидно, это вызывается при каждом повороте:
this.adapter = new LfPagerAdapter(getChildFragmentManager());
что приведет к воссозданию всего пейджера, верно? В результате
getItem(int position)
будет вызываться при каждом ротации, и фрагмент будет создан с нуля и потеряет свое состояние:
return FragmentC.newInstance();
Я попытался решить это с помощью
if(this.adapter == null)
this.adapter = new LfPagerAdapter(getChildFragmentManager());
в onViewCreated
, но результатом было то, что при вращении фрагменты внутри пейджера, где удалены.
Любые идеи о том, как правильно сохранить состояние внутри пейджера?
Ответы
Ответ 1
Вам нужно будет сделать 2 вещи, чтобы решить проблему:
1) Вместо onViewCreated
вы должны использовать метод onCreate
для создания экземпляра LfPagerAdapter
;
то есть:.
public class MainTabFragment extends Fragment {
private PagerSlidingTabStrip mSlidingTabLayout;
private LfPagerAdapter adapter;
private ViewPager mViewPager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
this.adapter = new LfPagerAdapter(getChildFragmentManager());
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_tab, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
this.mViewPager = (ViewPager) view.findViewById(R.id.viewpager);
this.mViewPager.setAdapter(adapter);
this.mSlidingTabLayout = (PagerSlidingTabStrip) view.findViewById(R.id.sliding_tabs);
this.mSlidingTabLayout.setViewPager(this.mViewPager);
}
}
2) Вам нужно расширить FragmentStatePagerAdapter
вместо FragmentPagerAdapter
Ответ 2
Android автоматически обновит вашу активность при настройке без этой строки android:configChanges="keyboardHidden|orientation|screenSize"
в вашем манифестах, чтобы вы могли обрабатывать onConfiguration
самостоятельно.
Единственный способ использовать onSaveInstanceState()
в вашей деятельностиFragement для сохранения состояния viewPager (например, текущей позиции) и фрагментов, где вам нужно сохранить материал
Пример того, как вы можете сохранить текущую позицию viewpager и восстановить ее onConfiguration
изменить
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
int position = mViewPager.getCurrentItem();
outState.Int("Key", position );
}
@Override //then restore in on onCreate();
public void onCreated(Bundle savedInstanceState) {
super.onCreated(savedInstanceState);
// do stuff
if (savedInstanceState != null) {
int position= savedInstanceState.getInt("Key");
mViewPager.setCurrentItem(position)
}
}
Конечно, это очень простой пример.
Ps: для восстановления во фрагменте используйте метод onActivityCreated() вместо метода onCreate().
Вот еще один пример того, как сохранить состояние: Нажмите меня!
Ответ 3
Запишите этот внутренний тег активности в manifest.xml: -
android:configChanges="orientation|screenSize"
Это позволит сохранить состояние фрагмента.