旋转

时间:2016-05-11 06:51:58

标签: android android-fragments android-viewpager android-savedstate

编辑:我很难解释这些事情,所以这里是一段视频 http://sendvid.com/mefqxd8f

上下文 该应用程序由一个具有ViewPager的Activity组成,该ViewPager包含3个选项卡。当按下按钮时,Tab1使用名为PageFragmentListener的接口在同一个选项卡中切换2个不同的片段。当应用程序首次加载时,Fragment1在Tab1中膨胀。单击按钮后,Fragment2在Tab1中膨胀。我希望片段1在此之后永久保留在Tab1中。

问题: 如果Tab3当前处于活动状态(对用户可见),然后旋转设备,Tab1将被完全销毁。重新创建它时,它会使用Fragment1使Tab1膨胀,而不是恢复Fragment2。在视频中,您会看到Tab1是蓝色而不是紫色。

问题: 有没有办法在Fragment2被销毁后将其恢复到Tab1而不是让Fragment1膨胀?我假设savedInstanceState可以某种方式使用。

class MyAdapter extends FragmentStatePagerAdapter {
    static final String TAG = "MyAdapter";
    private final FragmentManager mFragmentManager;
    public BaseFragment mFragmentA;
    public BaseFragment mFragmentB;

    /**
     *  PageFragmentListener for switching fragmentA.
     */
    public PageFragmentListener mListenerA = new PageFragmentListener() {
        @Override
        public void onSwitchToNextFragment(final String id) {
            mFragmentManager.beginTransaction().remove(mFragmentA).commit();
            if (mFragmentA instanceof FragmentA)
            {
                mFragmentA = FragmentA2.newInstance(mListenerA);    // => switch fragment a2
            }
            else if (mFragmentA instanceof FragmentA2){
                mFragmentA = FragmentA.newInstance(mListenerA);
            }
            notifyDataSetChanged();     // notify changes
        }
    };

    /**
     *  PageFragmentListener for switching fragmentB.
     */
    public PageFragmentListener mListenerB = new PageFragmentListener() {
        @Override
        public void onSwitchToNextFragment(final String id) {
            mFragmentManager.beginTransaction().remove(mFragmentB).commit();
            if (mFragmentB instanceof ItemListFragment){     // current fragment is List Fragment
                Bundle arguments = new Bundle();
                arguments.putString(Constants.ARG_ITEM_ID, id);     // selected item id
                mFragmentB = ItemOneDetailFragment.newInstance(mListenerB);       // switch detail fragment
                mFragmentB.setArguments(arguments);

            }else if (mFragmentB instanceof ItemOneDetailFragment) {      // DetailFragment
                mFragmentB = ItemListFragment.newInstance(mListenerB);    // => switch list fragment
            }
            notifyDataSetChanged();     // notify changes
        }
    };

    public MyAdapter(FragmentManager fm) {
        super(fm);
        Log.d(TAG, "MyAdapterConstructor");
        mFragmentManager = fm;
        List<Fragment> fragments = fm.getFragments();
        if(fragments != null){
            for(Fragment f : fragments){
                if (f instanceof FragmentA || f instanceof FragmentA2){
                    mFragmentA = (BaseFragment) f;
                }
                if(f instanceof ItemListFragment || f instanceof ItemOneDetailFragment){
                    mFragmentB = (BaseFragment) f;
                }
            }
        }
    }

    @Override
    public Fragment getItem(int position) {
        Log.d(TAG, "getItem()");

        if (position == 0){      // Tab-1
            if (!(mFragmentA instanceof FragmentA2)) {
                mFragmentA = FragmentA.newInstance(mListenerA);
            }
            return mFragmentA;
        }

        if (position == 1)      // Tab-2
            return FragmentB.newInstance();

        if (position == 2) {    // Tab-3
            if (!(mFragmentB instanceof ItemOneDetailFragment)){
                mFragmentB = ItemListFragment.newInstance(mListenerB);
            }
            return mFragmentB;
        }
        else{
            return null;
        }
    }

    /**
     * To set tab title.
     * @param position the currently visible ViewPager fragment
     * @return the title of the fragment
     */
    @Override
    public CharSequence getPageTitle(int position) {
        Log.d(TAG, "getPageTitle()");
        if (position == 0) {    // Tab-1
            return "Tab 1";
        }
        if (position == 1) {    // Tab-2
            return "Tab 2";
        }
        if (position == 2) {        //Tab-3
            return "Tab 3";
        }
        return null;
    }

    @Override
    public int getCount() {     // Count of Tabs
        return 3;
    }

    @Override
    public int getItemPosition(Object object) {
        Log.i("Adapter", "ItemPosition>>>" + object.toString());
        if (object instanceof ItemListFragment && mFragmentB instanceof ItemOneDetailFragment) {     //  fragment changed
            return POSITION_NONE;
        }

        if (object instanceof ItemOneDetailFragment && mFragmentB instanceof ItemListFragment) {     // fragment changed
            return POSITION_NONE;
        }

        if (object instanceof FragmentA && mFragmentA instanceof FragmentA2) {
            return POSITION_NONE;
        }

        if (object instanceof FragmentA2 && mFragmentA instanceof  FragmentA){
            return POSITION_NONE;
        }

        return POSITION_UNCHANGED;
    }
}

2 个答案:

答案 0 :(得分:0)

通过调用

来旋转时保留片段状态的简单解决方案
ComboBox

为了将片段添加到堆栈中,请尝试这样

setRetainInstance(true);

获取前一个片段(可能在调用onBackPressed()时打开)试试这个

transaction.addToBackStack(fragment.getClass.getName());

答案 1 :(得分:0)

我的(差)解决方案是创建一个名为hasSavedInstance的MainActivity静态类布尔值。我在MainActivity的onCreate()中将其设置为true,如下所示:

    if (savedInstanceState == null){
        Log.d(TAG, "onCreate() FIRST");
    }
    else{
        Log.d(TAG, "onCreate() ADDITIONAL");
        hasSavedInstance = true;
    }

然后我使用此值来确定在MyAdapter中返回哪个片段:

@Override
    public Fragment getItem(int position) {
    Log.d(TAG, "getItem()");
    if (position == 0){      // Tab-1
        Log.d(TAG, "hasSavedInstance="+MainActivity.hasSavedInstance);
        if (mFragmentA == null && MainActivity.hasSavedInstance){
            mFragmentA = FragmentA2.newInstance(mListenerA);
        }
        else if (!(mFragmentA instanceof FragmentA2)) {
            mFragmentA = FragmentA.newInstance(mListenerA);
        }
        return mFragmentA;
    }

这似乎有效但我觉得设置这个标志是解决这个问题的一种非常不优雅的方式。