【问题标题】:Android fragment navigation for tablets - single or multiple activities?平板电脑的 Android 片段导航 - 单个或多个活动?
【发布时间】:2014-06-18 07:37:22
【问题描述】:

我想实现这样的导航(下图),其中片段 A、B、C、D 表示向下导航到应用程序的信息层次结构。

在手机上只有一个片段可见,而在平板电脑上则有两个片段可见。

我看过的所有教程和文档(例如thisthis)都提到了Master-Detail 视图,其中似乎左侧有一个主片段,右侧有一个详细视图,但是似乎没有人指定如何从细节中深入挖掘。

事实上,平板电脑的 GMail 应用程序就像我自己的应用程序一样工作。假设片段 A 是帐户和文件夹列表,片段 B 是电子邮件列表,片段 C 是对话本身。

此屏幕是带有片段 A 和 B 的配置

这个屏幕有片段 B 和 C

问题是:我是否应该使用单个 Activity 来实现这一点,其中

  • 对于手机,我将为片段设置一个 FrameLayout
  • 对于平板电脑,我将有两个 FrameLayouts 用于“左”和“右”片段?

如果是这样,我将如何插入新片段?在 FragmentTransaction 中,我有两个可用的操作 - add()replace()

  • 如果我使用add(),那么下面的片段似乎还活着(它们不会进入暂停状态)并保持完整状态(但可能会浪费一些资源)(所以在片段D中,所有的C、B和 A 仍然存在),并且在后退按钮上,滚动状态和加载的数据仍然存在
  • 如果我使用replace(),那么前一个片段将被删除,因此任何时候顶部都只会有一个(在手机上)片段,而在后退按钮上,事务将被撤销,旧片段添加回来,但它不会记住它之前的状态

这些选项对我来说似乎都不合适。教程在 FragmentTransaction 中使用 replace() - 但是它们如何恢复前一个片段的状态,例如在手机的 GMail 应用程序中,片段 B 从服务器加载并无限滚动,然后当我用片段 C 替换它时然后往回走,B应该会出现在它离开的地方,对吧?

我真的不知道该做什么或去哪里看,请指教。

【问题讨论】:

    标签: android android-layout android-fragments android-navigation


    【解决方案1】:

    只使用 1 个活动,但每个活动都有不同的 FragmentTransactions。使用 LinearLayout 作为 Activity 的根,我们称之为 R.id.content 并创建一个新的 XML 值,如下所示:

    • /values/device.xml

      <item type="bool" format="boolean" name="isPhone">true</item>

    • /values-sw600dp/device.xml

      <item type="bool" format="boolean" name="isPhone">false</item>

    那么您的交易将是这样的:

      FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
      Frag_C f = new Frag_C();
      if(getResources().getBoolean(R.bool.isPhone)){ // phone
         ft.replace(R.id.content, f, Frag_C.TAG);
      }else { // tablet
         Fragment left = getSupportFragmentManager().findFragmentByTag(Frag_A.TAG);
         Fragment right = f;
         ft.hide(left);
         ft.add(R.id.content, right, FRAG_C.TAG);
      }
      ft.addToBackStack(null).commit();
    

    最后一点,在对每个片段进行膨胀时,您必须设置 LinearLayout 的布局参数WEIGHT 来控制片段的宽度。类似的东西:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       View v = inflater.inflate(layoutId(), container, false);
       ((LinearLayout.LayoutParams) v.getLayoutParams()).weight = 1;
    }
    

    所以 fragA 的权重为 1,然后 B=2,然后 C=4,然后 D=8(例如)。所以左边片段的宽度是 33%,右边是 66%。根据需要改变值。

    如果您想知道如何为这些交易设置动画,请参考我在https://stackoverflow.com/a/14155204/906362之前给出的这个答案

    【讨论】:

    • 也感谢您指出我可以在一个 FragmentTransaction 中修改多个片段的想法。
    • 官方 Android 文档声明您应该使用 2 个活动,如下所述:developer.android.com/guide/practices/…
    【解决方案2】:

    我对您的问题进行了一些研究,我认为相同的程序不适用于电话和桌子,但如果是这样,请查看:

            FragmentManager fragmentManager = getFragmentManager();
            fragmentManager.beginTransaction()
                    .replace(R.id.frame_container, fragment).commit();
    

    这是负责更改片段的部分代码,最初取自Here

    本教程包含完成平板电脑设计的所有步骤。

    每当我需要安卓帮助时,我都会参考这个网站! 享受吧!!

    【讨论】:

      【解决方案3】:

      如您所知,段适用于reusing GUI parts

      尽管我必须承认,我没有看到直接解决 A-B B-C C-D 场景的代码示例或教程,但这甚至可以跨越活动。如果活动 1 可以使用 B 的段实例,那么活动 2 也可以使用自己的 B 段实例。您将获得额外的好处,即能够从您的应用程序内部(和外部)的其他位置直接链接到活动 2。

      在活动 1 之外定义 B 段,并在 A-B 和 B-C 中使用。然后startActivityForResult()活动2,它实例化另一个B段。当用户使用后退按钮时,他们应该以 B 段的最新状态进入活动 1。

      您甚至可以尝试在一个活动中重复使用所有片段......但我没有看到任何优势,除了可能是 GUI 过渡动画。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-03
        • 2018-07-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-19
        相关资源
        最近更新 更多