Android ViewPager с вкладкой не поддерживает состояние после поворота экрана
я реализую ViewPager с вкладками, похожими на реализацию, предоставленную Google здесь.
мое приложение имеет следующее поведение. Мой ViewPager имеет 3 "страницы" (fragA, fragB, fragC), и я реализую 3 вкладки поверх ViewPager. Разница между реализацией google и моей заключается в том, что вкладки не используются для навигации между фрагментами. Например, нажатие одной из моих вкладок загружает другой набор данных на видимый фрагмент. Я могу fragA с выбранным tab3, fragB с выбранным tab2 и fragC с выбранным tab1.
проблема в том, когда я поворачиваю экран. Если я на FragmentA
при выборе третьей вкладки, когда я поворачиваю экран, я остаюсь в том же фрагменте, но теперь выбрана первая вкладка. Я хочу сохранить ту же вкладку, выбранную при вращении экрана.
это мой класс для управления вкладками:
public class ManagerTabs extends Fragment {
private TabHost.TabContentFactory mFactory = new TabHost.TabContentFactory() {
@Override
public View createTabContent(String tag) {
View v = new View(getActivity());
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
};
public static ManagerTabs newManager() {
return new ManagerTabs();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.datatabs, container, false);
createTabs();
createPager();
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState != null) {
currentPage = savedInstanceState.getInt("currentPage", currentPage);
currentTab = savedInstanceState.getInt("currentTab", currentTab);
mTabHost.setCurrentTab(currentTab);
}
mPager.setCurrentItem(currentPage);
}
private void createPager() {
mPager = (ViewPager) view.findViewById(R.id.datapager);
pagerAdapter = new PagerAdapter(getChildFragmentManager());
mPager.setAdapter(pagerAdapter);
IconPageIndicator indicator = (IconPageIndicator) rootView.findViewById(R.id.indicator);
indicator.setViewPager(pager);
indicator.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
currentTab = mTabHost.getCurrentTab();
currentPage = mPager.getCurrentItem();
switch (currentPage) {
case 0:
((FragmentA) pagerAdapter.getCurrentFragment(currentPage)).getData(currentTab);
break;
case 1:
((FragmentB) pagerAdapter.getCurrentFragment(currentPage)).getData(currentTab);
break;
case 2:
((FragmentC) pagerAdapter.getCurrentFragment(currentPage)).getData(currentTab);
break;
}
}
});
}
private void createTabs() {
mTabHost = (TabHost) view.findViewById(android.R.id.tabhost);
mTabHost.setup();
mTabHost.addTab(mTabHost.newTabSpec(getString(R.string.day))setIndicator(getString(R.string.day)).setContent(mFactory));
mTabHost.addTab(mTabHost.newTabSpec(getString(R.string.month)).setIndicator(getString(R.string.month)).setContent(mFactory));
mTabHost.addTab(mTabHost.newTabSpec(getString(R.string.year)).setIndicator(getString(R.string.year)).setContent(mFactory));
mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
public void onTabChanged(String tag) {
currentTab = mTabHost.getCurrentTab();
currentPage = mPager.getCurrentItem();
switch (currentPage) {
case 0:
((FragmentA) pagerAdapter.getCurrentFragment(currentPage)).getData(currentTab);
break;
case 1:
((FragmentB) pagerAdapter.getCurrentFragment(currentPage)).getData(currentTab);
break;
case 2:
((FragmentC) pagerAdapter.getCurrentFragment(currentPage)).getData(currentTab);
break;
}
}
});
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("currentPage", mPager.getCurrentItem());
outState.putInt("currentTab", mTabHost.getCurrentTab());
}
}
и это адаптер, который создает фрагменты:
public class PagerAdapter extends FragmentPagerAdapter implements IconPagerAdapter{
private Fragment[] currentFragment = new Fragment[3];
public PagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int index) {
Fragment fragment;
switch (index) {
case 0:
fragment = FragmentA.newInstance();
break;
case 1:
fragment = FragmentB.newInstance();
break;
case 2:
fragment = FragmentC.newInstance();
break;
default:
fragment = null;
break;
}
currentFragment[index] = fragment;
return fragment;
}
@Override
public int getIconResId(int index) {
switch (index) {
case 0:
return R.drawable.fraga;
case 1:
return R.drawable.fragb;
case 2:
return R.drawable.fragc;
default:
return -1;
}
}
@Override
public int getCount() {
return 3;
}
public Fragment getCurrentFragment(int currentFrag) {
return currentFragment[currentFrag];
}
public Fragment[] getCurrentFragment() {
return currentFragment;
}
}
и, наконец, фрагмент (FragmentA, FragmentB и FragmentC) почти идентичны:
public class FragmentA extends Fragment {
public static FragmentA newInstance() {
return new FragmentA();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.datafragment, container, false);
mTabHost = (TabHost) ((View) container.getParent().getParent()).findViewById(android.R.id.tabhost);
if (savedInstanceState != null) {
currentTab = savedInstanceState.getInt("currentTab");
}
populateLayout(currentTab);
return rootView;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("currentTab", currentTab);
}
}
проблема в том, что все мои onCreateView
всегда вызываются дважды, и во второй раз, когда они вызываются, информация теряется. Я отладил и увидел это поведение,
когда я поворачиваю экран, например, во фрагменте и с третьей выбранной вкладкой, это происходит:
01 ManagerTabs -> onSaveInstanceState
02 FragmentA -> onSaveInstanceState
03 ManagerTabs -> onCreateView
04 ManagerTabs -> onViewCreated
в вызове 04 (ManagerTabs - > onViewCreated), mTabHost.setCurrentTab(currentTab);
называется, но внутри onTabChanged
, Я получаю java.lang.NullPointerException
потому что все фрагменты внутри адаптер-ноль.
что я могу сделать, чтобы при повороте экрана я мог поддерживать текущую выбранную вкладку?
1 ответов
после поворота экрана новый экземпляр - это. Но ... --4--> восстанавливает свое состояние и состояние всех фрагментов, которые он содержит. ViewPager
не вызывает адаптеры getView()
метод. Поэтому Fragment[] currentFragment
содержит