如何在单/双窗格布局中管理UI状态和后端堆栈

时间:2012-09-14 20:40:40

标签: android android-fragments android-lifecycle android-orientation

我无法理解如何在典型的列表详细设计模式中正确管理Fragment

我的布局工作正常,横向视图(双窗格)的结构如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout ... >
    <FrameLayout android:id="@+id/list" ... />
    <FrameLayout android:id="@+id/container" ... />
</LinearLayout>

对于肖像视图(单个窗格),像这样:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="@+id/container" ... />

我在refs.xml中也有一个res/values-w600dp/,以确保根据设备的屏幕宽度加载相应的布局。

选择列表项时,横向视图应并排显示列表和详细信息,而纵向视图应仅显示全屏详细信息。如果未选择任何内容,则横向视图应显示左侧的左侧和右侧的空白区域,而纵向视图应仅显示全屏列表。

example

然而,这是我遇到麻烦的地方:

  • 我是否对列表+可选的详细信息布局使用“主”Activity,为肖像,仅详细信息布局使用另一个“详细信息”Activity?这似乎是Fragments guide示例的作用。我已经得到了这个普遍的工作,但是当方向改变时,我如何保持我的细节片段的状态?

    考虑上面显示的相反情况 - 从纵向旋转到横向,同时细节可见意味着细节Activity需要finish(),以便主Activity可以显示双窗格布局,但这也会破坏详细信息片段及其savedInstanceState。如果用户在详细信息片段中的EditText字段中键入了信息,然后旋转设备,当我将详细信息片段添加到主(双窗格)时,如何保留详细信息片段的整个UI状态{{ 1}}

  • 我是否只使用一个Activity并自行管理Activity?这允许我在方向改变时保留细节UI的状态(因为Android会自动处理),但是当它返回到堆栈时会变得很混乱。

    考虑图像中的情况 - 当细节可见时应从横向旋转到纵向应显示单窗格显示详细信息,但如何正确管理后堆栈和Fragment主页图标以显示列出单窗格?旋转回横向还需要撤消我之前执行的任何后向堆栈操作,因为两个片段将立即可见。

经过一番搜索后,我发现了两个类似的问题(Switch from dual pane to single pane on orientation change maintaining fragment stackRetain Fragment state between Activities),但我的情况略有不同,因为我并没有尝试改进这项功能,而是最好的预先计划。我错过了什么?当然,Android可以同时管理后台堆栈(如多个ActionBar案例中) UI状态(如单Activity案例中),对吧?

2 个答案:

答案 0 :(得分:6)

我通过多个活动路线解决了这个问题。 See my answer to "Retain Fragment state between Activities"

关键是使用FragmentManager.saveFragmentInstanceState()来保存片段UI的状态,并使用Fragment.setInitialSavedState()在另一个活动中实例化相同的片段时恢复它。

出于我的目的,我发现我需要在两种情况下保存UI状态。我在片段中创建了一个辅助方法public void saveState(),并在使用onPause()附加新实例之前立即从片段自己的replace()方法以及我的“main”活动中调用它。片段到双窗格布局。

我仍然有兴趣知道这种单/双窗格布局方案所需的后台操作是否可行,或者单活动方法是否需要覆盖onBackPressed并手动模拟后栈。

答案 1 :(得分:4)

可以只使用一个活动,但您必须自己以纵向方式管理背斜。

当您描述应用程序的行为时,可能有4种状态:

  • 状态A:肖像,显示列表片段。
  • 状态B:纵向,显示背面堆栈上列表片段的详细信息片段。
  • 状态C:横向,显示左侧的列表片段和右侧的空白区域。
  • 状态D:横向,并排显示列表片段和细节片段。

想象一下,你处于状态D(两个片段,我们称之为FA和FB),你改变了手机的方向。以下状态应为状态B,但问题是您的纵向布局只有一个FrameLayout。使用以下作为单一窗格布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="@+id/list" ... />

Android将重新创建FA并将其附加到FrameLayout。另一方面,FB也将被重新创建,但不会关联容器,因此它不会显示出来。此时,您可以创建另一个片段,FB2与FB具有相同的内容,并使用它来替换FA。你将在你的靠背堆中安装FA-FB2并隐藏FB。

如果再次更改方向(期望状态D),则可以使用onSaveInstanceState()从后台堆栈popBackStack()弹出FB2,从而再次使用FA和FB。在删除FB2之前,您可能还希望将其内容复制到FB。当应用程序再次处于状态D时,FB将具有其FrameLayout。

还有一些其他过渡和情况需要你照顾,但主要的想法是。

这不是一个非常优雅的解决方案,因此我确信它必须是更好的,可能更高效(没有复制片段)的方法来解决这个问题。