简体   繁体   English

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

[英]ViewPager inside fragment, how to retain state?

In my application the fragment activity holds two fragments, Fragment A and Fragment B. Fragment B is a view pager that contains 3 fragments. 在我的应用程序中,片段活动包含两个片段,片段A和片段B.片段B是包含3个片段的视图寻呼机。

在此输入图像描述

In my activity, to prevent that the fragment is recreated on config changes: 在我的活动中,为了防止在配置更改时重新创建片段:

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

Code for Fragment B: 片段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);
    }
}

Code for the adapter: 适配器代码:

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

My problem is that I am not able to retain the state of the view pager an its child fragments on orientation changes. 我的问题是我无法保持视图分页器的状态,它的子片段在方向更改上。

Obviously this is called on every rotation: 显然每次轮换都要调用它:

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

which will cause the whole pager to be recreated, right? 这将导致整个寻呼机被重建,对吧? As a result 结果是

getItem(int position)

will be called on every rotation and the fragment will be created from scratch and losing his state: 将在每次轮换时调用,片段将从头开始创建并丢失其状态:

return FragmentC.newInstance();

I tried solving this with: 我尝试解决这个问题:

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

in onViewCreated but the result was that on rotation the fragments inside the pager where removed. onViewCreated但结果是在旋转时, onViewCreated的片段被移除。

Any ideas how to correctly retain the state inside the pager? 任何想法如何正确保留寻呼机内的状态?

You will need to do 2 things to resolve the issue: 您需要做两件事来解决问题:

1) You should use onCreate method instead of onViewCreated to instantiate LfPagerAdapter ; 1)您应该使用onCreate方法而不是onViewCreated来实例化LfPagerAdapter ;

ie: 即:

    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) You will need to extend FragmentStatePagerAdapter instead of FragmentPagerAdapter 2)您需要扩展FragmentStatePagerAdapter而不是FragmentPagerAdapter

Android will automatically recreate your activity on configuration without this line android:configChanges="keyboardHidden|orientation|screenSize" in you manifest so that you can handle onConfiguration change yourself. Android将自动重新创建您的配置活动,而不显示此行中的android:configChanges="keyboardHidden|orientation|screenSize" ,以便您可以onConfiguration处理onConfiguration更改。

The only way then is to use onSaveInstanceState() in both your activityFragement to save viewPager state(current position for example) and in fragments where you need to save stuff 唯一的方法是在您的activityFragement中使用onSaveInstanceState()来保存viewPager状态(例如当前位置)以及需要保存东西的片段

Example on how you can save current position of viewpager and restore it onConfiguration change 有关如何保存viewpager的当前位置并将其恢复到onConfiguration更改的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)
        }
    }

Of course, this is a very basic example. 当然,这是一个非常基本的例子。

Ps: to restore in fragment use onActivityCreated() instead of onCreate() method. Ps:在片段中恢复使用onActivityCreated()而不是onCreate()方法。

Here is another example on how to retain state : Click me! 这是另一个如何保持状态的例子: 点击我!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM