ViewPager里面的片段,如何保留状态?

时间:2014-11-18 12:00:04

标签: android android-fragments fragmentpageradapter

在我的应用程序中,片段活动包含两个片段,片段A和片段B.片段B是一个包含3个片段的视图寻呼机。

enter image description here

在我的活动中,为了防止在配置更改时重新创建片段:

if(getSupportFragmentManager().findFragmentByTag(MAIN_TAB_FRAGMENT) == null) {
    getSupportFragmentManager().beginTransaction().replace(R.id.container, new MainTabFragment(), MAIN_TAB_FRAGMENT).commit();
}

片段B的代码:

public class MainTabFragment extends Fragment {

    private PagerSlidingTabStrip mSlidingTabLayout;
    private LfPagerAdapter adapter;
    private ViewPager mViewPager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_tab, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {

        this.adapter = new LfPagerAdapter(getChildFragmentManager());

        this.mViewPager = (ViewPager) view.findViewById(R.id.viewpager);
        this.mViewPager.setAdapter(adapter);

        this.mSlidingTabLayout = (PagerSlidingTabStrip) view.findViewById(R.id.sliding_tabs);
        this.mSlidingTabLayout.setViewPager(this.mViewPager);
    }
}

适配器代码:

public class LfPagerAdapter extends FragmentPagerAdapter {

    private static final int NUM_ITEMS = 3;

    private FragmentManager fragmentManager;

    public LfPagerAdapter(FragmentManager fm) {
        super(fm);
        this.fragmentManager = fm;
    }

    @Override
    public int getCount() {
        return NUM_ITEMS;
    }

    @Override
    public Fragment getItem(int position) {
        Log.d("TEST","TEST");
        switch (position) {
            case 1:
                return FragmentC.newInstance();
            case 2:
                return FragmentD.newInstance();
            default:
                return FragmentE.newInstance();
        }
    }
}

我的问题是,我无法保留视图寻呼机的状态,它的子片段会在方向更改时保留。

显然每次轮换时都会调用它:

this.adapter = new LfPagerAdapter(getChildFragmentManager());

会导致重新创建整个寻呼机,对吗?结果

getItem(int position)
每次轮换都会调用

,片段将从头开始创建并失去状态:

return FragmentC.newInstance();

我尝试用以下方法解决这个问题:

if(this.adapter == null)
    this.adapter = new LfPagerAdapter(getChildFragmentManager());
onViewCreated中的

,但结果是旋转了寻呼机内部的碎片。

如何正确保留寻呼机内的状态?

2 个答案:

答案 0 :(得分:27)

您需要做两件事来解决问题:

1)您应该使用onCreate方法而不是onViewCreated来实例化LfPagerAdapter;

即:

    public class MainTabFragment extends Fragment {

    private PagerSlidingTabStrip mSlidingTabLayout;
    private LfPagerAdapter adapter;
    private ViewPager mViewPager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
        this.adapter = new LfPagerAdapter(getChildFragmentManager());
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_tab, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {


        this.mViewPager = (ViewPager) view.findViewById(R.id.viewpager);
        this.mViewPager.setAdapter(adapter);

        this.mSlidingTabLayout = (PagerSlidingTabStrip) view.findViewById(R.id.sliding_tabs);
        this.mSlidingTabLayout.setViewPager(this.mViewPager);
    }
}

2)您需要延长FragmentStatePagerAdapter而不是FragmentPagerAdapter

答案 1 :(得分:1)

Android会自动重新创建您的配置活动,而不会显示此行android:configChanges="keyboardHidden|orientation|screenSize",以便您可以自行处理onConfiguration

唯一的方法是在您的activityFragement中使用onSaveInstanceState()来保存viewPager状态(例如当前位置)以及需要保存内容的片段

如何保存viewpager的当前位置并将其还原onConfiguration更改

的示例
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
            int position = mViewPager.getCurrentItem();
            outState.Int("Key", position );
    }

    @Override //then restore in on onCreate();
    public void onCreated(Bundle savedInstanceState) {
        super.onCreated(savedInstanceState);
        // do stuff
        if (savedInstanceState != null) {
              int  position= savedInstanceState.getInt("Key");
            mViewPager.setCurrentItem(position)
        }
    }

当然,这是一个非常基本的例子。

Ps:在片段中恢复使用onActivityCreated()而不是onCreate()方法。

以下是另一个关于如何保留状态的示例:Click me!