片段设计:通过在单个活动中显示/隐藏片段来适应多个屏幕布局?对问题一的答复 编辑 一

我试图了解如何使用片段来创建能够很好地适应多个屏幕和布局的应用程序。我研究了几个例子:

  1. Android 开发人员指南上的 Fragments 文档。
  2. 谷歌IO应用程序
  3. 片段样本来自ActionBar Sherlock

所有这些都提倡多种方法:Activity

  • 在大屏幕上,显示具有多个 s 的单个ActivityFragment
  • 在较小的屏幕上,将 s 拆分为多个 s。FragmentActivity

我想到了另一种方法 - 一个:Activity

  • 有一个单曲,里面有所有的s。ActivityFragment
  • 根据屏幕大小和方向,显示/隐藏相应的 (s) (使用 / )。FragmentFragmentTransaction.show()FragmentTransaction.hide()

要使用 Android 开发者指南使用的相同“新闻文章列表/文章内容”示例进行说明,请执行以下操作:

  • 使活动同时包含 和 。NewsArticleListFragmentArticleReaderFragment
  • 在选项卡上,始终显示两个片段。
  • 在手机上,最初隐藏。从列表中选择文章时,将隐藏并显示 。ArticleReaderFragmentArticleListFragmentArticleReaderFragment

有没有人使用过类似的方法?这种方法可能有什么实际的缺点吗?与多活动方式相比,它看起来更好/更糟吗?例如,片段不能在XML中显示/隐藏 - 必须用于此目的。FragmentTransaction


编辑1:假设场景的描述

想象一下,一个应用程序可以在屏幕上一次显示最多三个“窗格”。此外,这些是需要考虑的因素:

  • 手机一次只能显示一个窗格(无论纵向/横向如何)
  • 7 英寸平板电脑可以显示 2 个窗格,在纵向模式下垂直拆分,在横向模式下水平拆分。
  • 一个10+英寸的平板电脑可以显示2个窗格,在纵向中垂直分割;3 个窗格在横向上水平拆分。

为简单起见,让我们将电视屏幕排除在讨论之外。

现在,将其转换为设计:

  • 我们有三个片段:Frag1,Frag2和Frag3。
  • 在最简单的情况下,所有三个片段都在一个活动中(我们称之为活动A)。这是10英寸的横向表壳。
  • 另一个“简单”的情况是当每个片段都在自己的活动中时 - ActivityA包含Frag1;活性B包含Frag2,ActivityC包含Frag3。

到目前为止,我们还没有考虑与Android开发人员指南中提供的新闻阅读器示例显着不同的任何内容。唯一的主要区别是有个片段而不是两个。

现在,7英寸的标签只能容纳2个碎片。这将如何工作?请注意,此处有两种可能的组合:

  1. 正在显示 Frag1 和 Frag2。
  2. 正在显示 Frag2 和 Frag3。

我只是无法解决这个问题。我是否在活动 A 中完成所有这些操作?我是否只是创建一个全新的 ActivityD?我需要创建多少个布局(我数了大约8个)?是不是太过分了?

我确实意识到我上面提出的单活动方法可能也不适合这种情况 - 因为显示/隐藏片段本身就不是微不足道的。

关于如何在不被布局和组合淹没的情况下处理这个问题的任何建议?


答案 1

@Taylor Clark的这个答案非常翔实。但是,这并不是像我在原始问题中所问的那样,实际分享使用单一活动方法的经验。我开始修改Android开发人员指南中的新闻阅读器示例,以使用单活动方法,并提出了一个可行的解决方案。

还有待观察的是,这种方法比多活动方法更可取的用例是什么(或者是否存在任何此类情况)。另外,我还没有详细查看我的问题的编辑1中描述的3窗格方案。

我希望很快发布我的整个项目,但以下是我如何做到这一点的快速概述:

  • 单 : 新闻动态Activity
  • 两个片段:和TitlesListFragmentDetailsFragment
  • 这两个片段始终存在于 中。根据当前的双窗格性,我显示/隐藏相应的片段。NewsActivity

我遇到的一些问题:

是否将布局指定为双窗格:

在原始新闻阅读器示例中,双窗格布局具有用于保存新闻详细信息的。我们通过测试此框架布局是否存在来确定我们当前是否处于双窗格布局中。FrameLayout

但是,在我的解决方案中,这两个片段始终存在于所有布局中。我通过在那些布局中包含一个带有id和我想要成为双窗格并在单窗格布局中省略此视图来解决这个问题。然后,这是一个问题ViewdualPaneandroid:visibility="gone"

mDualPane = findViewById(R.id.dualPane)!=null;

编辑:

有比拥有虚拟视图更好的方法来指定双窗格。我更喜欢的是创建一个布尔资源。例如,我有一个如下:config.xml

<resources>
    <bool name="dual_pane">false</bool>
</resources>

然后,我可以将其他文件放在诸如,或等文件夹中,并将布尔值调整为或根据需要进行调整。config.xmlvalues-xlarge-landvalues-portvalues-sw600dptruefalse

然后,在代码中,这是一个问题getResources().getBoolean(R.bool.dual_pane);

关闭详细信息片段

这是一个区分收盘价和收盘价的问题。最后,我不得不按如下方式覆盖:ActivityFragmentonBackPressed()

  • 在双窗格模式下,只需调用super.onBackPressed();
  • 在单窗格模式下,如果我们处于 ,则调用TitlesListFragmentsuper.onBackPressed();
  • 在单窗格模式下,如果我们处于 ,则将其视为关闭片段。这意味着隐藏它并显示 .DetailsFragmentTitlesListFragment

这并不理想,但这是我能想到的最好的。

编辑

根据评论中@SherifelKhatib的建议,有一种更简洁的方法来处理后退按钮按下:只需添加到Fragment backstack中,即显示/隐藏细节片段的事务。这样,当您按下后退按钮时,片段事务将被反转。如果您希望在其他按钮单击时手动弹出后堆栈,也可以手动弹出。


答案 2

通常,应用程序被拆分为多个活动,因为每个活动都表示用户可以执行的特定“事情”。例如,在电子邮件应用程序中,定义的一组操作可以是:

  1. 查看邮件列表
  2. 查看邮件的详细信息
  3. 撰写对电子邮件的答复。

每个操作都可以是其自己的活动,显示单个(或一组)片段。但是,如果您具有屏幕空间,则将消息列表的查看和消息详细信息合并到一个可以显示/隐藏“详细信息视图”片段的单个活动中是有意义的。从本质上讲,片段允许您一次向用户显示多个“活动”。

做出决定时要考虑的事项:

  1. 无法提供 xml 中指定的片段参数
  2. 如果您的决定是基于屏幕方向,则始终可以使用资源限定符指向具有更多/更少片段的另一个布局(例如,layout-land-large)
  3. 无法维护片段 活动
  4. 碎片是否协同工作,为用户提供简化的体验?
  5. 有没有一个时间,你的一个碎片将永远消失?如果是这样,也许是时候进行新的活动了
  6. 随心所欲。如果应用程序交换片段是“自然的”,那就去做吧。请记住,如果您发现自己做了很多事情,也许单独的活动是更合适的解决方案

我通常对平板电脑版本的应用程序采用“多个片段方法”,对手机采用“每个活动一个片段”,这听起来与您列出的第一种方法一致。并不是说第二个没有时间和地点,但我可以看到实现变得混乱!

很抱歉冗长的回复!也许你可以告诉你更多关于你的特定用例?希望这有帮助!


对问题一的答复 编辑 一


以下是我想象您的应用程序项目的设置方式:

源文件:

yourapp.package.phone: NewsActivity1, NewsActivity2, NewsActivity3

yourapp.package.tablet: NewsMultipaneActivity

资源

布局/

activity_news.xml- phone version, only includes Fragment1
activity_news_detail.xml- phone version, only includes Fragment2
activity_news_<something>.xml- phone version, only includes Fragment3

布局-大/

activity_news.xml- 7" tablet version, includes Fragment2 and an empty fragment container. Split vertically

布局-大地/

activity_news.xml- same as layout-large, but with the split being horizontally

布局-超大-陆地/

activity_news.xml- 10"+ tablet version, contains all three fragments split horizontally

那么这里发生了什么呢?

  • 如果你的应用在手机上运行,请启动“新闻活动”1
  • 如果您的应用程序在平板电脑上运行,请启动新闻多元活动

只要文件名相同,Android就会根据屏幕大小和方向为您交换布局。由于 Fragment2 将始终显示,因此您可以将其“硬编码”到平板电脑布局中。然后,您可以使用 FragmentTransactions 根据需要在容器中的 Fragment1 和 Fragment3 之间切换

请务必查看 http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources,了解如何利用资源限定符来缓解不同屏幕和方向的一些麻烦


推荐