如何使用非常深的导航编写Android多窗格应用程序

Kev*_*ead 11 android android-fragments

TL; DR: 具有类似Spotify iPad应用程序的深度导航的多窗格应用程序应该如何在Android上运行,以及如何实现这一点?

长版本: 我正在开发一个应用程序,用户可以看到项目列表,然后可以深入研究这些项目.这些项目详细信息页面可以再次打开相关项目的列表,这些项目又包含详细信息页面等.作为一个手机应用程序,这些将是可能看起来像彼此链接的单独活动: 用户单击Overview中的Item#2并获取详细信息页面,然后单击那里的 这里,物品清单是开放的,用户选择看

在模型中,用户看到初始概览,然后从第一个列表中选择"项目#2".将打开一个新活动,向他显示第2项的详细信息.在这里,他选择查看与项目#2相关的事物列表.第三张图片中新开的活动显示了这个列表,点击一个打开了这个东西的详细信息.他可以根据自己的喜好深入浏览内容.

这通常适用于通常的Android活动.我正在努力将应用程序带到平板电脑,并正在考虑如何最好地实现这一点.计划是创建具有相同概念的多窗格布局.它与iPad Spotify应用程序的工作方式非常相似(一旦创建特定于平板电脑的布局,它们将如何将其带入Android会很有趣).

在平板电脑布局中,每次单击项目或列表名称都会打开相应的子项目,作为从右侧激活的新窗格.与上例中相同的工作流程如下所示:

最初的多窗格平板电脑布局 用户选择项目#2,并在右窗格中打开项目详细信息页面 在详细信息页面上,用户选择 点击Thing#3可在右侧窗格中打开事物详细信息

我不确定如何最好地实现这种导航模式.具有有限导航深度的多窗格应用程序(如GMail)可以使用包含所有片段的静态ViewGroup(LinearLayout可以)构建,并且深入导航会将下一个容器的内容替换为右侧,并为此设置动画(请参阅CommonWares在SO)上的实现.

这表明自定义ViewGroup将是最佳选择.如果必须显示一个子页面(即"事物列表"),那么它会在ViewGroup中创建一个新子项,该子项的宽度是屏幕的一半,然后滚动可见区域,以便与之交互的窗格并且新的孩子是可见的.要将此正确链接到FragmentTransaction,以便后端堆栈正常工作,我猜它会是这样的:

View newPane = container.addChild();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(newPane, new ListOfThingsFragment(2));
ft.remove(paneOnRight, fragmentOnRight);
ft.commit();
container.animateToRight();
Run Code Online (Sandbox Code Playgroud)

我没有看到在FragmentTransaction中做动画的方法.

欢迎反馈.我的雇主对我们开发的开放式采购框架总体上是有利的,所以如果这是一个更广泛的兴趣,如果我能提出一个可重用的解决方案,我很乐意分享它.

Bud*_*ius 6

我有一些研究时间,并提出了一个解决这个问题的方法(这个问题我希望看到长时间的解决方案,甚至在你问之前).我无法真正显示整个代码,因为有一些IP边界,但我会在这里将这个动画的主要部分用于工作.

这里有两种主要工具:setCustomAnimationsLayoutTransition 是的,据我已经能够做到这一点,你需要单独设置动画,使其工作.

因此,让我们看一些代码,您将使用水平LinearLayout定义XML,并确保在其上包含以下行.

android:animateLayoutChanges="true"
Run Code Online (Sandbox Code Playgroud)

这将自动生成一个标准LayoutTransition,该标准会转换停留在布局中的片段/视图以及正在包含或从布局中删除的片段/视图的alpha(in或out).试试看.

所以在这个布局膨胀后,我们将捕获这个LayoutTransition并根据我们的需求进行欺骗:

LayoutTransition lt = myLinearLayout.getLayoutTransition();
lt.setAnimator(LayoutTransition.APPEARING, null);
lt.setAnimator(LayoutTransition.DISAPPEARING, null);
lt.setStartDelay(LayoutTransition.CHANGE_APPEARING, 0);
lt.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
Run Code Online (Sandbox Code Playgroud)

使用该代码,我们将删除alpha动画并消除转换中的任何延迟(因为我们希望所有翻译一起触发).

现在只需要几个简单的片段事务就可以使它工作,在初始化过程中我们会扩展该布局并在其上放置一些片段:

setContentView(R.layout.main); // the layout with that Linear Layout
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.main, frag1, FRAG_1_TAG); // it's good to have tags so you can find them later
ft.add(R.id.main, frag2, FRAG_2_TAG);
ft.add(R.id.main, frag3, FRAG_3_TAG);
ft.hide(frag3);
ft.commit();
Run Code Online (Sandbox Code Playgroud)

现在在交易上它很简单:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.push_left_in, R.anim.push_left_out, R.anim.push_right_in, R.anim.push_right_out);
Fragment left = getFragmentManager().findFragmentByTag(FRAG_1_TAG);
Fragment right = getFragmentManager().findFragmentByTag(FRAG_3_TAG);

ft.hide(left);
ft.show(right);

ft.addToBackStack(null);
ft.commit();
Run Code Online (Sandbox Code Playgroud)

最后的笔记:

为了进行更深入的导航,只需FragmentTransactions要将片段添加到LinearLayout和/ hidedetach左侧片段即可.

另外,要使片段在线性布局上工作对于在运行时设置其LinearLayout.LayoutParams.weight非常重要,类似于以下代码应用于片段视图

((LinearLayout.LayoutParams) view.getLayoutParams()).weight = 1;
Run Code Online (Sandbox Code Playgroud)

使它在手机上工作也只是应用常见的多屏支持模式.

最后一点,在设备轮换期间要小心正确管理布局状态,因为并非所有系统都自动处理.

快乐的编码!


cod*_*oda 4

我们的应用程序遇到了同样的问题。我们给自己设定的约束:

  • 动态窗格数
  • 每个窗格的大小可以不同
  • 方向变化时,窗格内的片段必须正确保留。

鉴于这些限制,我们构建了一个称为 PanesLayout 的新布局。您可以在这里查看:

https://github.com/cricklet/Android-PanesLibrary

它基本上允许您轻松添加任意数量的动态大小的窗格并将片段附加到这些窗格。希望你觉得它有用!:)