Skip to content
maqingqing edited this page Aug 18, 2017 · 3 revisions

适配 Android N 多窗口特性的 5 个要诀

英文原文:5 tips for preparing for Multi-Window in Android N

作者:Ian Lake, Google Android 技术推广工程师

翻译:Guokai Han

如果你看了What’s New in Android N这个视频,你会无意中发现了多窗口支持

使用多窗口分屏功能,能够并排地同时看到两个应用。你可能非常兴奋,想知道这是如何做到的,于是立刻去查阅文档,看看是什么新 API 实现了这一独特功能。

结果却发现并没有出现很多新的 API 。只有少量用于定制是否完全支持多窗口的 XML 属性以及少量用于检查当前是否处于多窗口模式的 Activity 方法。那这个魔法到底打是哪来的?其实魔法一直都在那

所谓的魔法就是 Android 的资源系统。资源系统中最强大的部分之一是提供替代资源(alternate resources )的能力——基于不同条件改变大小、布局、绘制、菜单等等。

**多窗口就是利用了这个资源系统 – 基于窗口大小来调整配置。**除了屏幕大小,最小宽度(即宽度或高度的最小值)和朝向(orientation)也会在调整窗口大小时更新。

这引出了我们第一个要诀。

要诀1:使用正确的上下文

使用适合的上下文(Context)加载合适的资源。如果你使用 Activity 上下文处理填充布局、获取资源等工作,这就对了。

然而,如果使用的是 Application 上下文处理 UI 相关的事情,你会发现加载的资源无法感知到多窗口。除了不会使用 Activity 主题的问题,你可能会加载了完全错误的资源!最好让你的 UI 资源与 Activity 上下文在一起。

要诀2:正确地处理配置变化

使用了正确的上下文,你要确保依据窗口大小获取正确的资源(无论之前是全屏还是两个应用的分屏)。重新加载这些资源的过程是基于你如何处理运行时变化的。

默认情况是你的整个 activity 被销毁然后再重建。这个过程会恢复你在 onSaveInstanceState() 方法中保存的所有状态,以及重新加载所有资源/布局。这个特性很好,你清楚所有事情都与新的配置一致并且配置的每种类型都被处理了。

不用说你也知道,每次配置变化的处理应该快速且流畅。请确保你没有在 onResume() 方法中做太多工作,并考虑使用 loaders 来保证配置变化时数据的连续。

你依然可以自己处理配置变化,在这种情况下你的 Activity (和 Fragment) 将收到 onConfigurationChanged() 方法回调而不是先销毁再重建,并且你需要手工管理视图更新,重新加载资源等工作。

要捕获多窗口相关的配置变化,你需要在 manifest 文件中添加一个 android:configChanges 属性,并至少设置这些值:

XHTML

<activity android:name=".MyActivity" android:configChanges="screenSize|smallestScreenSize |screenLayout|orientation" />

请确保你处理了所有可能需要变化的资源(当你自己负责处理配置变化时,这是你的责任了)。

这包括重新加载那些之前被认为是不变的资源。考虑一下你在 valuesvalues-sw600dp 中设置的大小。在非多窗口环境下,你无法在运行时切换它们,因为最小宽度是不变的(它总是设备的最小宽度)。然而在多窗口环境下,你可以且必需随着应用大小的调整而切换这些资源。

要诀3:处理所有朝向

回想下本文开头的介绍,我们谈到当窗口大小调整时朝向也会随之改变。没错,即使设备处于横屏的时候,应用也可能处于“竖屏”的朝向。

其实“竖屏”真正的意义仅仅是高度大于宽度,“横屏”的意义是宽度大于高度。所以从这个定义来考虑,在应用调整大小时,可能会从一个朝向转到另一个朝向就说得通了。

这也就是意味着朝向之间的转换应该尽可能平滑。引用 material design 规范中分屏部分的描述

改变设备的朝向不应该导致 UI 发生非预期的改变。例如,在某个分屏中(竖屏模式下)正在显示视频的应用,在旋转到横屏模式时,不应该自动进入全屏播放状态。

注意:如果你想要你的应用在全屏状态时(非多窗口)仍有这种类型的功能,你可以使用 inMultiWindowMode() 方法检查你当前所处的准确状态。

使用 android:screenOrientation 锁定屏幕朝向也会受到多窗口的影响。对于不是针对(target为) Android N 的应用,添加 android:screenOrientation 意味着你的应用根本不支持多窗口 – 这总是会强制用户离开多窗口模式。但在针对 Android N 的应用则稍有不同 – 在这种情况下不是不支持多窗口,而是处于多窗口模式时你在 android:screenOrientation 中设置的任何朝向都会被忽略。

请记住,无论应用是否针对 Android N,在多窗口模式下在运行时锁定朝向的 setRequestedOrientation() 方法都是无效的。

要诀4:针对所有屏幕尺寸构建响应式 UI

朝向并非是面向分屏设计的唯一问题。多窗口是平板 UI (tablet UI) 第一次遇到被缩小到微型尺寸的情况(你有平板 UI 吧?毕竟,14亿设备中的 12.5% 也是很多的设备)。

如果你已经在构建响应式 UI ,能够适应可用的空间,手机和平板有相对类似的布局,你会发现你已经为多窗口环境做了很好的准备。作为建议,把 UI 缩小到 220dp 的宽/高,然后让应用从这个大小扩展到全屏大小是你现在可做的事情

然而,如果你的手机和平板 UI 差异巨大,请不要迫使用户在这两者之间切换 – 而是以平板 UI 为主并想办法缩小它。有许多响应式 UI 模式可供你参考,它们可以为用户提供流畅的调整大小体验 – 再次说明,这些并不需要使用 Android N 的 API。

要诀5:由其它应用启动的 Activity 必需总是支持多窗口

在多窗口环境下,你的整个任务(task)都代表的是一个单窗口。这就是为什么如果要启动一个显示在(多窗口)旁边的 activity 需要启动一个新的任务 – 新任务才能是新窗口。

反过来也是如此,来自同一个页面中引用的内容:

如果你在一个任务堆栈中启动一个新的 activity,这个 activity 会替换屏幕上的当前 activity ,并且会继承所有它的多窗口属性

这意味着,如果你有一个能够被其它应用启动的 activity ,这个 activity 会继承调用方 activity 同样的多窗口属性。这些属性包括最小尺寸。如果使用的是 startActivityForResult() ,这种情况下你的 activity 必需是同一个任务堆栈的一部分,甚至在 implicit intent 的情况下也是如此。你无法确定别人是否使用了 FLAG_ACTIVITY_NEW_TASK

因此,所有这些直到最小尺寸的 activity (以及由 activity 启动的 activity)都必需支持多窗口。所以请彻底测试!

全面测试!

针对多窗口环境的最佳准备工作就是测试你的应用。即使没有修改任何代码,也没有配置过 Android N SDK ,只要把现有的应用安装到 Android N 设备或模拟器上就是很好的第一步,也是最容易做的事情。