gpt4 book ai didi

带有选项卡的 Android ViewPager 在屏幕旋转后不保持状态

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:30:27 24 4
gpt4 key购买 nike

我正在实现一个带有选项卡的 ViewPager,类似于 Google 提供的实现 here .

我的应用有以下行为。我的 ViewPager 有 3 个“页面”(fragA、fragB、fragC),我在 ViewPager 之上实现了 3 个选项卡。谷歌的实现和我的不同之处在于选项卡不用于在 fragment 之间导航。例如,按下我的一个选项卡,在可见 fragment 上加载一组不同的数据。我可以选择 tab3 的 fragA,选择 tab2 的 fragB 和选择 tab1 的 fragC。

问题出在我旋转屏幕时。如果我在 FragmentA 上选择了第三个选项卡,当我旋转屏幕时,我会停留在同一个 fragment 中,但现在选择了第一个选项卡。我想在旋转屏幕时保持选中相同的选项卡。

这是我管理选项卡的类(class):

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());
}
}

这是创建 fragment 的适配器:

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;
}
}

最后,一个 fragment (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 总是被调用两次,第二次调用时,信息丢失了。我已经调试并看到了这种行为,

当我旋转屏幕时,例如在 FragmentA 中并选择了第三个选项卡,会发生这种情况:

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

在 04 调用 (ManagerTabs -> onViewCreated) 中,调用了 mTabHost.setCurrentTab(currentTab); 但在 onTabChanged 中,我得到了一个 java.lang .NullPointerException 因为adapter里面所有的 fragment 都是null。

我该怎么做才能在旋转屏幕时保持当前选中的标签页?

最佳答案

屏幕旋转后,FragmentPagerAdapter 的新实例被创建。但是 ViewPager 恢复了它的状态和它包含的所有 fragment 的状态。 ViewPager 不调用适配器的 getView() 方法。因此 Fragment[] currentFragment 仅包含 null 值。

您可以通过其他方式获取当前 fragment 。

如果使用 FragmentPagerAdapter:

FragmentPagerAdapter 在它传递给 FragmentManager 的 fragment 上设置标签。这个 id 取决于页面索引。您可以在 source of the latest support lib 中查看此 ID 的生成方式。 .

要实现这一点,只需将以下方法添加到您的 ManagerTabs fragment 中:

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

如果使用 FragmentStatePagerAdapter:

它不会在 fragment 上设置标签。借助 FragmentStatePagerAdapter,我们似乎可以使用它的 instantiateItem(ViewGroup container, int position) 调用。它返回对位于 position 位置的 fragment 的引用。如果 FragmentStatePagerAdapter 已经持有对相关 fragment 的引用,instantiateItem 只会返回对该 fragment 的引用,并且不会调用 getItem() 来实例化它再次。在这种情况下,我们的方法将是:

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

最后:

现在使用上面的方法获取当前 fragment 。在你的情况下:

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 ViewPager 在屏幕旋转后不保持状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27619610/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com