我的应用有以下行为.我的ViewPager有3个“页面”(fragA,fragB,fragC),我在ViewPager上面实现了3个标签.谷歌的实现和我的实现之间的区别在于标签不用于在片段之间导航.例如,按下我的一个选项卡,在可见片段上加载一组不同的数据.我可以选择tab3选择fragA,选择tab2选择fragB,选择tab1选择fragC.
问题是当我旋转屏幕时.如果我在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,Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.datafragment,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总是被调用两次,第二次调用它们时,信息就会丢失.我已经调试并看到了这种行为,
当我旋转屏幕时,例如在FragmentA中并选择第三个选项卡时,会发生以下情况:
01 ManagerTabs -> onSaveInstanceState 02 FragmentA -> onSaveInstanceState 03 ManagerTabs -> onCreateView 04 ManagerTabs -> onViewCreated
在04调用(ManagerTabs – > onViewCreated),mTabHost.setCurrentTab(currentTab);在onTabChanged中被调用,我得到一个java.lang.NullPointerException,因为适配器内的所有片段都是null.
我该怎么办,如果我旋转屏幕,我可以保持当前选定的标签?
解决方法
您可以通过其他方式获取当前片段.
如果使用FragmentPagerAdapter:
FragmentPagerAdapter在它传递给FragmentManager的片段上设置标签.此id取决于页面索引.如何生成此ID,您可以在source of the latest support lib中看到.
要实现此目的,只需在ManagerTabs片段中添加以下方法:
public Fragment getCurrentPagerFragment(int position) { String fragmentTag = "android:switcher:" + mPager.getId() + ":" + position; return getChildFragmentManager().findFragmentByTag(fragmentTag); }
如果使用FragmentStatePagerAdapter:
它不会在片段上设置标签.使用FragmentStatePagerAdapter,我们可以使用其instantiateItem(ViewGroup容器,int位置)调用来获取.它返回对位置位置的片段的引用.如果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; } } });