Intereting Posts
Файл R.java не обновляется с идентификатором элемента интерфейса Лучше всего использовать плагины Android Studio или Intellij Idea wth? Android: альтернативный макет xml для ландшафтного режима Как использовать API смарт-блокировки в моем приложении для разблокировки режима разбивки? Сжатие изображения камеры перед загрузкой Dalvik ищет .so файл с расширением '.0' – почему? Использовать DLL-файлы в приложении Android. Надежный способ определения того, работает ли приложение Android в «BlueStacks», Как программно выйти из Facebook SDK 3.0 без использования кнопки входа в систему Facebook / выхода? Размер значков Android Каковы различия между FLAG_ACTIVITY_RESET_TASK_IF_NEEDED и FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP? Как вы получаете значения тега «android:» в пользовательском представлении Где установить Android SDK на Mac OS X? Вертикально-полосатый фон в XML? Является ли разработка Android на C / C ++ быстрее, чем Java?

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 всегда onCreateView дважды, а во второй раз, когда они вызываются, информация теряется. Я отлаживал и видел это поведение,

Когда я поворачиваю экран, например, в FragmentA и с выбранной третьей вкладкой, это происходит:

 01 ManagerTabs -> onSaveInstanceState 02 FragmentA -> onSaveInstanceState 03 ManagerTabs -> onCreateView 04 ManagerTabs -> onViewCreated 

В вызове 04 (ManagerTabs -> onViewCreated), mTabHost.setCurrentTab(currentTab); onTabChanged , но внутри onTabChanged я получаю onTabChanged java.lang.NullPointerException потому что все фрагменты внутри адаптера являются нулевыми.

Что я могу сделать, чтобы, если я поворачиваю экран, я могу сохранить текущую выбранную вкладку?

Solutions Collecting From Web of "Android ViewPager с вкладкой, не поддерживающей состояние после вращения экрана"

После вращения экрана создается новый экземпляр FragmentPagerAdapter . Но ViewPager восстанавливает состояние и состояние всех фрагментов, которые он содержит. ViewPager не вызывает метод getView() адаптеров. Поэтому Fragment[] currentFragment содержит только null значения.

Вы можете получить текущий фрагмент другими способами.

Если вы используете FragmentPagerAdapter :

FragmentPagerAdapter устанавливает теги на фрагменты, которые он передает в FragmentManager . Этот идентификатор зависит от индекса страницы. Как генерируется этот идентификатор, вы можете увидеть в источнике последнюю версию lib .

Для этого просто добавьте следующий метод в ваш фрагмент ManagerTabs :

 public Fragment getCurrentPagerFragment(int position) { String fragmentTag = "android:switcher:" + mPager.getId() + ":" + position; return getChildFragmentManager().findFragmentByTag(fragmentTag); } 

Если вы используете FragmentStatePagerAdapter :

Он не устанавливает метки на фрагменты. С помощью FragmentStatePagerAdapter мы можем обойтись, используя instantiateItem(ViewGroup container, int position) . Он возвращает ссылку на фрагмент в позиции position . Если FragmentStatePagerAdapter уже содержит ссылку на рассматриваемый фрагмент, instantiateItem просто возвращает ссылку на этот фрагмент и не вызывает getItem() для его повторного создания. В этом случае наш метод будет:

 public Fragment getCurrentPagerFragment(int position) { FragmentStatePagerAdapter a = (FragmentStatePagerAdapter) mPager.getAdapter(); return (Fragment) a.instantiateItem(pager, position); } 

В заключение:

Теперь используйте вышеописанный метод для получения текущего фрагмента. В твоем случае:

 mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() { public void onTabChanged(String tag) { currentTab = mTabHost.getCurrentTab(); currentPage = mPager.getCurrentItem(); Fragment currentFragment = getCurrentPagerFragment(currentPage); switch (currentPage) { case 0: ((FragmentA) currentFragment).getData(currentTab); break; case 1: ((FragmentB) currentFragment).getData(currentTab); break; case 2: ((FragmentC) currentFragment).getData(currentTab); break; } } }); 

Попробуйте добавить android: configChanges = "ориентация" к вашей деятельности.