0 前言背景
本文档为多窗口适配指导文档。当前仅重点介绍有关分屏(split-screen)的相关说明,后续逐步补充其他模式的说明。
使用对象
使用Android平台的研发人员和测试人员等。
适用范围
该规范适用于基于Android平台的产品开发。
术语定义
规则:编程时必须遵守的约定
说明:某个规则的具体解释
错误示例:违背某条规则的例子
正确示例:遵循某条规则的例子
例外情况:相应的规则不适用的场景信任边界:位于信任边界之内的所有组件都是被系统本身直接控制的。所有来自不受控的外部系统的连接与数据,包括客户端与第三方系统,都应该被认为是不可信的,要先在边界处对其校验,才能允许它们进一步与本系统交互。
非信任代码:非产品包中的代码,如通过网络下载到本地虚拟机中加载并执行的代码。
1 多窗口介绍
多窗口的定义:屏幕同时显示多个Activity,并且Activity窗口可在一定范围内放大缩小。N
版本多窗口支持三种模式:
1.1 分屏(split-screen)模式
支持2个窗口同时显示(竖屏上下,横屏左右)
支持窗口缩放功能
1.2 自由(freeform)模式
多个窗口同时显示 (类似Windows)
支持窗口最大化、关闭、调整大小和位置、自定义标题栏区域
1.3 画中画(Picture-in-Picture)模式窗口悬浮在topmost
2 多窗口分屏使用指导2.1如何开启多窗口分屏
多窗口分屏开启方式分为以下两种:
长按Recent启动
最近任务列表拖拽标题栏到上窗口(竖屏时)或左窗口(横屏时)
2.2 如何退出多窗口分屏
多窗口分屏退出方式分为以下两种:
长按Recent退出
竖屏时,拖动分割线到顶部或底部退出。横屏时,拖动分割线到左侧或右侧退出。
2.3 如何缩放分屏窗口大小随窗口宽高变化,动态切换资源,如layout方向;竖屏支持3档,横屏支持1档
3 多窗口开发注意事项
3.1如何配置是否支持多窗口
对于targetSDKVersion为N,按如下规则配置:
说明:N版本API Activity新增resizeableActivity属性,用来标示Activity是否支持多窗口。若应用targetSDKVersion为N,则该应用下所有Activity的resizeableActivity属性均默认为true,即该应用下的所有Activity均能支持多窗口显示。
若root Activity的resizeableActivity属性为true,则和root Activity处于同一Task的其他Activity也能继承该属性值,即也能支持多窗口显示。

如图所示,若Activity1配置resizeableActivity为true,Activity1、Activity2、Activity3均处于同一Task,则Activity2和Activity3均能在多窗口下显示(即使Activity2和Activity3没有配置resizeableActivity属性)。
若Activity2需全屏显示,则需按以下步骤配置:
1、设置resizeableActivity为false
<activityandroid:name="com.exmaple.Activity2"
android:resizeableActivity="false
2、Activity1启动Activity2时,设置FLAG_ACTIVITY_NEW_TASK,Activity2运行在单独的Task,即和Activity1不在同一Task。
Intent intent= newIntent(this,Activity2.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
对于targetSDKVersion低于N,注意如下事项:说明:targetSDKVersion低于N版本的应用,且能支持横竖屏转向(入口Activity),则能支持分屏模式(split-screen),并Toast提示“app may not work with split-screen”。否则,全屏显示,并Toast提示“this app does not support multi-window”。targetSDKVersion低于N版本的应用,对应Activity属性screenOrientation配置不同值,则对分屏模式的支持程度也不同,具体见下表:
注:Y支持分屏N不支持分屏
3.2 多窗口下Activity生命周期注意事项
说明:N版本多窗口下运行的两个同时可见的Activity,只有一个处于Resumed状态,有别于华为多窗口的方案(两个可见的Activity同时处于Resumed状态)。如果是视频、社交、浏览器等类型的应用,在N版本设备多窗口下运行,建议在onStart/onStop中处理play/pause逻辑,而不要在onResume/onPause方法中处理,以保证:
1、 视频类应用在失去焦点时,能正常播放
android:resizeableActivity="false" />
Intent intent=newInten
2、 社交类应用在失去焦点时,能继续收到消息、实时刷新
3、 浏览器类应用在失去焦点时,能正常播放网页视频、动画等其他类型的应用,在保证用户体验的前提下,可根据自身业务逻辑处理。
3.3 如何知道是否处于多窗口模式
说明:N版本API Activity类新增inMultiWindow方法,判断当前Activity是否处于多窗口模
式(split-screen,freeform,pip)
3.4 如何知道是否处于PiP模式
说明:N版本API Activity类新增inPictureInPicture方法,判断当前Activity是否处于PiP模式。
3.5 如何监听是否进入多窗口模式
说明:N版本API Activity类新增onMultiWindowModeChanged方法,监听Activity是否进入
多窗口模式。
}
注:inMultiWindow为true,则表示处于多窗口模式(split-screen,freeform,pip);否则,已退出多窗口模式。
3.6 如何监听是否进入PiP模式
说明:N版本API Activity类新增onPictureInPictureChanged方法,监听Activity是否进入
PiP模式。
注:inPictureInPicture为true,则表示处于Pip模式;否则,已退出Pip模式。如果Activity要进入PiP模式,可通过调用 方法,使Activity自身
进入PiP模式,前提条件是该Activity的 为true。
3.7 分屏模式下同应用的两个不同Activity可支持相邻显示
说明:N版本API Intent类新增Flag:FLAG_ACTIVITY_LAUNCH_ADJACENT,该Flag仅用于多窗口下的分屏模式(split-screen)。分屏模式下,若上窗口Activity1启动Activity2时设置FLAG_ACTIVITY_LAUNCH_ADJACENT,则Activity2在下窗口下显示,同时上窗口依然显示Activity1,即两者相邻显示。使用时FLAG_ACTIVITY_LAUNCH_ADJACENT要结合FLAG_ACTIVITY_NEW_TASK使用,以确保新Activity运行在单独的Task中。
startActivity(intent);
Android N7.0多窗口适配开发指导
3.8 多窗口Configuration变化注意事项
说明:多窗口下对应用窗口大小缩放,会触发Configuration变化,可能的变化有screenSize、smallestScreenSize、layoutDirection、screenLayout、orientation,建议Activity的manifest配置configChanges,否则Activity将被销毁重建,可能导致卡顿和跟手性差。
示例代码:
3.9 如何设置多窗口缩放时Window背景
说明:多窗口缩放时,通过设置R.styleable#Window_windowBackground,来设置窗口背景样式。若未设置,则默认读取R.styleable#Window_windowBackgroundFallback值。示例代码:
<activity
android:name=".MyActivity"
android:configChanges="screenSize|smallestScreenSize|
layoutDirection|screenLayout|orientation"/>
<stylename="MyTheme"parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Drawable to use in the background while the window is resizing on
Android N. -->
<itemname="android:windowBackgroundFallback">@color/green</item>
<itemname="android:windowBackground">@color/green</item>
</style>
3.10 如何通过 layout设置多窗口布局
说明:N版本API新增layout布局,对layout属性值进行设置,可配置activity的显示位置和窗口大小。
defaultHeight: freeform模式下,activity的初始高度值
defaultWidth: freeform模式下,activity的初始宽度值
gravity: freeform模式下,activity的初始位置属性。minimalSize:freeform或split-screen模式下,activity的最小高度和宽度值。split-screen模式下,如果移动分隔线对窗口缩放,若缩放大小低于minimalSize,则系统强制对activity进行裁剪压缩。
示例代码:
3.11 如何通过代码设置多窗口布局说明:同3.10
示例代码:
<activityandroid:name=".MyActivity">
<layoutandroid:defaultHeight="500dp"
android:defaultWidth="600dp"
android:gravity="top|end"
android:minimalSize="450dp"/>
</activity>
// Define the bounds.
Rect bounds = new Rect(500, 300, 100, 0);
// Set the bounds as an activity option.
ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchBounds(bounds);
Intent intent = new Intent(this, MyActivity.class);
startActivity(intent, options.toBundle());
3.12 多窗口模式应用特性变化注意事项
说明:多窗口下Activity以下特性变化将不再生效:
系统UI(status bar、nav bar...)的自定义和可见度变化,不再生效
WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER,设置桌面背景为应用背景不
再生效
沉浸式Immersive Mode,不再生效
对Activity属性android:screenOrientation设置,不再生效。比如ActivityA已运行在多窗口
下,同时AndroidManifest.xml中对Activity A的android:screenOrientation设置为portrait,实际情况是多窗口下Activity A不限制转向,横竖屏均显示。
3.13 自由模式下 caption/title区域如何显示content说明:自由模式下,右上角可显示caption/title区域,如果应用需要在caption/title显示content
(类似Chrome选项卡),可调用N版本API Activity类新增overlayWithDecorCaption方法。
3.14 应用如何适配多窗口动态变化布局
说明:应用在多窗口下按如下原则验证适配是否正常:
- 1、 全屏下启动应用,长按Recent启动多窗口,验证应用是否能正常切换到多窗口下显示。
-
2、 全屏下按Recent显示最近任务列表,拖拽应用标题栏到屏幕高亮区域,验证应用是否能
正常在多窗口下显示。
- 3、 拖动分割线,对窗口大小缩放,验证UI是否显示正常,功能是否能正常使用。
- 4、 如果应用定义minimalSize,则验证窗口大小是否能缩放到低于minimalSize值。
- 5、 性能测试,验证窗口缩放时,UI重绘是否存在性能问题。
以Nexus 6P为例,在竖屏可进行3个档位缩放,横屏固定1个档位(档位可配置)。在滑动条拖动时,layout的大小会发生变化;方向可能会变化(取决于长宽比较),将导致与屏幕方向不一致。Activity的configuration会变化(参考3.8),res资源目录可能会发生切换(取决于res配置)。
应用应尽量使用一套布局(或横竖两套)来做界面适配,兼容多种layout尺寸。若应用在不同档位显示时,存在UI显示异常(比如布局挤压、控件被遮挡等),可参考对应档位的layout做资源适配。例如下图Nexus 6p,可在sw320目录做适配,满足横屏和竖屏的50%档:
影响类:Activity
调用示例:overlayWithDecorCaption(true)
Nexus 6P | 分屏窗口调整时layout变化 |
竖屏 | 50%档:sw324dp,放大1档:sw411dp,缩小1档:sw213dp |
横屏 | 50%档:sw336dp |
参考资料
1. http://developer.android.com/preview/samples.html
2. https://www.google.com/design/spec/layout/split-screen.html#split-screen-layout