片段设计:通过在单个Activity中显示/隐藏片段来适应多种屏幕布局?

cur*_*zen 38 java android android-layout android-fragments

我试图了解如何使用Fragments创建适应多个屏幕和布局的应用程序.我研究了几个例子:

  1. Android Developer指南中的Fragments文档.
  2. Google IO应用
  3. 来自ActionBar Sherlock的碎片样本.

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

  • 在大屏幕上,显示Activity具有多个Fragments 的单个屏幕
  • 在较小的屏幕上,将Fragments 分成多个Activitys.

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

  • 有一个单独Activity的所有Fragments.
  • 根据屏幕大小和方向,显示/隐藏适当Fragment的(使用FragmentTransaction.show()/ FragmentTransaction.hide()).

为了说明Android开发人员指南使用的相同"新闻文章列表/文章内容"示例:

  • News活动同时包含ArticleListFragmentArticleReaderFragment.
  • 在选项卡上,始终显示两个片段.
  • 在手机上,ArticleReaderFragment最初是隐藏的.从列表中选择文章时,将ArticleListFragment隐藏该文章ArticleReaderFragment并显示该文章.

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


编辑1:假设情景的描述

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

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

为简单起见,让我们不要讨论电视屏幕.

现在,将其翻译为设计:

  • 我们有三个片段:Frag1,Frag2和Frag3.
  • 在最简单的情况下,所有三个片段都在一个Activity中(我们称之为ActivityA).这是10英寸的风景案例.
  • 另一个"简单"的情况是每个Fragment都在自己的Activity中 - ActivityA包含Frag1; ActivityB包含Frag2,ActivityC包含Frag3.

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

现在,7英寸标签的情况下,只能容纳2个碎片.这怎么样?请注意,这里有两种组合:

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

我只是无法绕过这个.我是否在ActivityA中完成所有这些操作?我只是创建了一个全新的ActivityD吗?我需要创建多少个布局(我计算在8左右)?是不是太多的permeations?

我确实意识到我上面提出的单活动方法也可能不适合这种情况 - 因为显示/隐藏片段本身并不重要.

有关如何处理这个问题的任何建议,而不会被布局和组合所淹没?

cur*_*zen 16

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

还有待观察的是,这种方法优于多活动方法(或者是否存在任何此类情况)的用例是什么.另外,我没有仔细查看我的问题的编辑1中描述的3窗格场景.

我希望尽快发布我的整个项目,但这里是我如何进行的快速概述:

  • 单身Activity:NewsActivity
  • 两个碎片:TitlesListFragmentDetailsFragment
  • 这两个片段总是存在于NewsActivity.根据当前的双窗格,我显示/隐藏适当的片段.

我遇到的一些问题:

将布局指定为双窗格或不:

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

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

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

编辑:

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

<resources>
    <bool name="dual_pane">false</bool>
</resources>
Run Code Online (Sandbox Code Playgroud)

然后我可以将更多的config.xml文件夹一样values-xlarge-land,values-portvalues-sw600dp等,并调整布尔值,truefalse作为我的愿望.

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

关闭详细信息片段

这是区分Activity近距离和Fragment近距离的问题.最后,我不得不覆盖onBackPressed()如下:

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

这不是理想的,但它是我能想到的最好的.

编辑:

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


Tay*_*ark 10

通常,应用程序被拆分为活动,因为每个应用程序代表用户可以执行的特定"事物".例如,在电子邮件应用程序中,一组定义的操作可以是:

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

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

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

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

我通常对平板电脑版本的应用程序使用"多片段方法",为手机使用"每片一片"片段,这听起来与您列出第一种方法一致.不是第二个没有时间和地点,但我可以看到实施变得混乱快!

对不起,罗嗦的回复!也许您可以详细说明您的具体用例?希望这可以帮助!


回答问题编辑一


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

源文件:

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
Run Code Online (Sandbox Code Playgroud)

布局大/

activity_news.xml- 7" tablet version, includes Fragment2 and an empty fragment container. Split vertically
Run Code Online (Sandbox Code Playgroud)

布局大的土地/

activity_news.xml- same as layout-large, but with the split being horizontally
Run Code Online (Sandbox Code Playgroud)

布局XLARGE土地/

activity_news.xml- 10"+ tablet version, contains all three fragments split horizontally
Run Code Online (Sandbox Code Playgroud)

那么这里发生了什么?

  • 如果您的应用在手机上运行,​​请启动NewsActivity1
  • 如果您的应用在平板电脑上运行,请启动NewsMultipaneActivity

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

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