当屏幕方向改变时,片段回退栈未被恢复

6
我有一个FragmentActivity,当用户在应用程序中导航时,我将当前的Fragment替换为用户选择的Fragment,并将事务添加到后退堆栈。一切都很好,用户可以通过按返回按钮返回到先前的Fragment。
问题出现在设备方向改变时:假设用户看到的第一个Fragment是A,然后他导航到B,再从B到C。C内部的内容在横向模式下更容易欣赏,并且C有一个特殊的横向布局,因此用户旋转设备。我期望用户以新方向处于C状态。但实际上,用户在横向模式下看到的是A。现在他需要重新导航从A到B然后到C,才能以横向模式看到C。
我希望在方向更改后保留后退堆栈。
如果我在清单文件中使用configChange="orientation",则后退堆栈将被保留,但由于Fragment未重新创建,它无法加载新方向的正确布局。我想我可以使用一些难看的技巧来强制重新创建Fragment,但我认为应该有更好的解决方案来实现如此简单的事情。
显然,我做错了什么,因为在此页面中,有一种解释说:

-> Fragment Manager在两个Fragment上都调用onSaveInstanceState()。
-> Activity和两个Fragments被销毁。
-> 创建Activity的新实例。
-> 使用新的Fragment实例重新创建后退堆栈。

听起来像是我期望的行为,但这在我的应用程序中没有发生。我错过了什么吗? 如何实现这种行为?
我在SO上看到了一些类似的问题,但迄今为止都没有帮助我解决这个问题。任何帮助将不胜感激。

你的问题中实际上没有足够的信息来回答它。最有可能的是,无论是从头开始还是从方向更改重新创建,托管活动始终会创建并交换片段A。不过,我们确实需要一些代码来(反)确认这一点。其次,“configChange =”方向“”不会有任何影响,因为['屏幕大小'](http://goo.gl/f7SYLr)也会从纵向变为横向(反之亦然)。自Android 3.2以来就是这种情况... - MH.
是的,我的意思是将android:configChanges="orientation|keyboardHidden|screenSize"添加到清单中,它确实可以保持片段不变,但不会重新创建它们。您想看到我的活动的哪个部分?我没有覆盖onSaveInstance或onRestoreInstace。 - Alex Terreaux
2个回答

10

我认为您在添加/替换片段之前没有检查savedInstanceState。请尝试以下操作:

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Check that the activity is using the layout version
    // with the fragment_container_main FrameLayout
    if (findViewById(R.id.fragment_container_main) != null) {


        // If we're being restored from a previous state,
        // then we don't need to do anything and should return or else
        // we could end up with overlapping fragments.
        if (savedInstanceState != null) { //Do nothing, Android has got your back.

        } else {
            FragmentOne fragmentOne = new FragmentOne();

            // Add the fragment to the fragment_container_main FrameLayout
            getFragmentManager().beginTransaction()
                    .add(R.id.fragment_container_main,
                            fragmentOne,
                            "FRAG_ONE").commit();
        }
    }
}

3
这不完全是这样,但你的答案帮助我找到了真正的问题。原来导航抽屉片段在方向改变后被重新创建,因此它触发了onNavigationDrawerItemSelected,这总是替换Android正在恢复的片段。我通过在我的导航抽屉片段中添加setRetainInstance(true)来解决了这个问题。 - Alex Terreaux
谢谢提示 ;) - Alex Terreaux

4
原来导航抽屉片段在方向改变后被重新创建,因此它触发了onNavigationDrawerItemSelected,这总是会替换Android正在恢复的片段。我通过在我的导航抽屉片段中添加setRetainInstance(true)来解决这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接