我无法理解如何在典型的列表详细设计模式中正确管理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/
,以确保根据设备的屏幕宽度加载相应的布局。
选择列表项时,横向视图应并排显示列表和详细信息,而纵向视图应仅显示全屏详细信息。如果未选择任何内容,则横向视图应显示左侧的左侧和右侧的空白区域,而纵向视图应仅显示全屏列表。
然而,这是我遇到麻烦的地方:
我是否对列表+可选的详细信息布局使用“主”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 stack和Retain Fragment state between Activities),但我的情况略有不同,因为我并没有尝试改进这项功能,而是最好的预先计划。我错过了什么?当然,Android可以同时管理后台堆栈(如多个ActionBar
案例中)和 UI状态(如单Activity
案例中),对吧?
答案 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种状态:
想象一下,你处于状态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。
还有一些其他过渡和情况需要你照顾,但主要的想法是。
这不是一个非常优雅的解决方案,因此我确信它必须是更好的,可能更高效(没有复制片段)的方法来解决这个问题。