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

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

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

在模型中,用户看到一个初始概览,然后从第一个列表中select“Item#2”。 一个新的活动打开,显示项目#2的细节。 在这里,他select查看与项目#2有关的事物列表。 第三张图中的新开放活动显示了这个列表,点击一个打开了这个东西的细节。 他可以像他喜欢的一样深入浏览内容。

这与通常的Android活动相得益彰。 我正在将应用程序带到平板电脑上,并正在考虑如何最好地实现这一点。 计划是用相同的概念创build一个多窗格布局。 它与iPad Spotify应用程序的工作方式非常相似(一旦他们创build平板电脑特定的布局,看看他们如何将这些应用程序带到Android上将会非常有趣)。

在平板电脑布局中,每次单击某个项目或列表名称时,都会打开相应的子项目,作为从右侧进行animation的新窗格。 上例中的工作stream程如下所示:

初始多窗格平板电脑布局用户选择项目#2,并在右侧窗格中打开项目详细信息页面在详细信息页面上,用户选择“物品清单”,右侧窗格向左移动,物品列表在右侧窗格中打开点击Thing#3在右窗格中打开事情的详细信息

我不确定如何最好地实现这个导航模式。 具有有限导航深度(如GMail)的多窗格应用程序可以使用包含所有片段的静态ViewGroup(LinearLayout将会正常)来构build,并且更深入导航会将下一个容器的内容replace为右侧,并为其添加animation(请参阅在SO上的CommonWares实现 )。

这表明一个自定义的ViewGroup将是一条路。 如果它必须显示一个子页面(即“物品列表”),那么它将在ViewGroup中创build一个新的子元素,这个子元素是该子元素的屏幕宽度的一半,然后滚动可见区域,以便刚刚与之交互的窗格和新的孩子是可见的。 要正确地将它链接到FragmentTransaction,以便后端堆栈正常工作,我想这将是这样的:

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

我没有看到在FragmentTransaction中做animation的方法。

反馈欢迎。 我的雇主对于我们开发的开源采购框架总体上是有利的,所以如果这是一个更广泛的利益,如果我能想出一个可重用的解决scheme,我很乐意分享它。

Solutions Collecting From Web of "如何编写具有非常深的导航的Android多窗格应用程序"

我们遇到了与我们的应用程序相同的问题。 我们给自己的限制:

  • dynamic数字的窗格
  • 每个窗格可以有不同的大小
  • 窗格内的碎片必须正确保留在方向更改上。

鉴于这些限制,我们build立了一个新的布局,我们称之为PanesLayout。 你可以看看这里:

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

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

我花了一些研究时间,想出了一个解决这个问题的办法(一个问题,即使在你提出问题之前,我也希望看到这个解决scheme的时间很长)。 我不能真正显示整个代码,因为有一些IP边界,但我将它放在这里animation的主要部分工作。

有两个关键的工具: setCustomAnimationsLayoutTransition是的,就我所能做到的,你需要分开设置animation来使它工作。

所以让我们来看一些代码,您将使用水平LinearLayout定义您的XML,并确保在其中包含以下行。

 android:animateLayoutChanges="true" 

这将自动生成一个标准的LayoutTransition ,它可以转换布局中的片段/视图,以及布局中包含或从布局中移除的片段/视图。 试一试。

所以在这个布局膨胀之后,我们会捕获这个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); 

通过这段代码,我们删除了alphaanimation并从转换中消除了任何延迟(因为我们希望所有的转换都一起触发)。

现在只需几个简单的片段事务就可以工作,在初始化过程中,我们膨胀了这个布局并在其上放置了一些片段:

 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(); 

现在在交易这是一个简单的:

 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(); 

最后说明:

进行更深入的导航只需要触发FragmentTransactions来将片段添加到LinearLayout中,并hidedetach左侧片段。

另外为了使碎片在线性布局上工作,在运行时设置LinearLayout.LayoutParams.weight很重要,类似于以下代码应用于碎片视图

 ((LinearLayout.LayoutParams) view.getLayoutParams()).weight = 1; 

使其在手机上工作,这只是一个应用常见的多屏幕支持模式的问题。

最后一点,在设备旋转过程中,要小心妥善pipe理布局状态,因为它不是全部由系统自动处理。

快乐的编码!

对animation部分的部分回答:您可以使用FragmentTransaction完成animation:

 ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right); 

更新:请参阅Reto Meier自己关于片段animation的答案: https : //stackoverflow.com/a/4819665/1007169