Fav*_*las 6 tabs android android-fragments android-viewpager
我执行与标签类似,由谷歌提供的实施ViewPager 这里.
我的应用有以下行为.我的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());
}
}
Run Code Online (Sandbox Code Playgroud)
这是创建片段的适配器:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
最后,片段(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);
}
}
Run Code Online (Sandbox Code Playgroud)
问题是我onCreateView的所有人总是被叫两次,第二次被叫,信息就丢失了.我已经调试并看到了这种行为,
当我旋转屏幕时,例如在FragmentA中并选择第三个选项卡时,会发生以下情况:
01 ManagerTabs -> onSaveInstanceState
02 FragmentA -> onSaveInstanceState
03 ManagerTabs -> onCreateView
04 ManagerTabs -> onViewCreated
Run Code Online (Sandbox Code Playgroud)
在04调用(ManagerTabs - > onViewCreated)中,mTabHost.setCurrentTab(currentTab);调用但在内部onTabChanged,我得到一个java.lang.NullPointerException因为适配器内的所有片段都是null.
我该怎么办,如果我旋转屏幕,我可以保持当前选定的标签?
era*_*tin 14
屏幕旋转后,FragmentPagerAdapter将创建新实例.但是它ViewPager恢复了它包含的所有片段的状态和状态.ViewPager不调用适配器getView()方法.因此仅Fragment[] currentFragment包含null值.
您可以通过其他方式获取当前片段.
如果使用FragmentPagerAdapter:
FragmentPagerAdapter在它传递给的片段上设置标签FragmentManager.此id取决于页面索引.如何生成此id,您可以在最新的支持库的源代码中看到.
要实现此目的,只需在ManagerTabs片段中添加以下方法:
public Fragment getCurrentPagerFragment(int position) {
String fragmentTag = "android:switcher:" + mPager.getId() + ":" + position;
return getChildFragmentManager().findFragmentByTag(fragmentTag);
}
Run Code Online (Sandbox Code Playgroud)
如果使用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);
}
Run Code Online (Sandbox Code Playgroud)
最后:
现在使用上面的方法来获取当前片段.在你的情况下:
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;
}
}
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7727 次 |
| 最近记录: |