0

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

上下文: 该应用程序由一个带有 ViewPager 的 Activity 组成,该 ViewPager 包含 3 个选项卡。Tab1 使用一个名为 PageFragmentListener 的接口在按下按钮时在同一个 Tab 中的 2 个不同片段之间进行切换。当应用程序首次加载时,Fragment1 在 Tab1 中膨胀。点击按钮后,Fragment2 在 Tab1 中被充气。我希望 Fragment1 在此之后永久保留在 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;
    }
}
4

2 回答 2

0

在旋转时保留片段状态的简单解决方案是调用

setRetainInstance(true);

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

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

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

getFragmentManager.popBackStack();
于 2016-05-11T07:01:56.943 回答
0

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

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

然后我使用这个值来确定在 MyAdapter 中返回哪个 Fragment:

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

这似乎可行,但我觉得设置此标志是解决此问题的一种非常不雅的方式。

于 2016-05-12T00:04:01.227 回答