13

我在思考如何Fragment在典型的列表细节设计模式中正确管理 s 时遇到了麻烦。

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

<?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.xmlres/values-w600dp/

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

例子

但是,这就是我遇到麻烦的地方:

  • 我是否将“主要”Activity用于列表 + 可选的详细信息布局,而将另一个“详细信息”Activity用于纵向、仅详细信息布局?这似乎是片段指南示例所做的。我已经让这种方法可以正常工作,但是当方向改变时,我如何保持我的细节片段的状态?

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

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

    考虑图像中的情况——当细节可见时从横向旋转到纵向应该显示细节单窗格,但是如何正确管理后退堆栈和ActionBar主页图标以显示列表单窗格?旋转回横向还需要撤消我之前所做的任何回栈操作,因为两个片段将同时可见。

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

4

2 回答 2

6

我通过多活动路线解决了这个问题。 请参阅我对“在活动之间保留片段状态”的回答

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

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

我仍然想知道这种类型的单/双窗格布局方案所需的回栈操作是否可行,或者单活动方法是否需要onBackPressed手动覆盖和模拟回栈。

于 2012-09-17T19:21:44.660 回答
4

可以只使用一个 Activity,但您必须在纵向时自己管理 backstack。

当您描述应用程序的行为时,可能有 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。您将在您的 backstack 中拥有 FA-FB2 并隐藏 FB。

如果你再次改变方向(期待状态 D),你可以使用onSaveInstanceState()从 backstack 中弹出 FB2 popBackStack(),从而再次拥有 FA 和 FB。在删除 FB2 之前,您可能还需要将其内容复制到 FB。当应用再次处于状态 D 时,FB 将拥有其 FrameLayout。

还有一些其他的过渡和情况需要你处理,但主要的想法就是这样。

这不是一个非常优雅的解决方案,所以我确信它必须是一种更好,也许更有效(例如不复制片段)的方法来解决这个问题。

于 2013-05-24T18:45:57.230 回答