一、自由窗口简介
- 小窗
- 迷你小窗
二、为什么要做“自由窗口”
- 在多任务处理场景下,小窗意在解决临时使用某个应用的场景,例如:在使用游戏应用时,不便离开,但想发消息给朋友,此时就可以借助小窗打开第二应用;
- 迷你小窗意在解决应用临时挂机的场景,例如:等待网约车、等待游戏更新、观看直播等。
三、如何使用“自由窗口”
四、自由窗口技术适配指南
- MIUI的小窗是基于Android的多窗口Freeform方案实现的。
- 小窗目前主要问题是应用兼容性导致的一系列问题,内容显示不全、Touch事件不响应等等,其实根本原因是应用没有很好的支持、适配多窗口、多分辨率,如下是小窗适配的一些参考性适配指南。
1、google多窗口开发适配指南
多窗口适配支持文档:
https://developer.android.com/guide/topics/ui/multi-window#dnd
支持不同屏幕分辨率的开发技巧文档:
https://developer.android.google.cn/training/multiscreen/screensizes
2、应用声明是否支持自由窗口
如果您的应用以 API 级别 24 或更高级别为目标平台,那么您可以配置该应用的 activity 是否支持以及如何支持多窗口显示,自由窗口也是google多窗口的一种,所以goolge多窗口适配方案同样适用,可以在清单的<activity>或<application>元素中设置此属性,以启用或停用多窗口显示:
android:resizeableActivity=["true" | "false"]
如果将此属性设置为 true,则activity 能以分屏和自由窗口模式启动。如果将此属性设置为 false,则 activity 不支持多窗口模式。如果此值为 false,并且用户尝试在多窗口模式下启动 activity,则 activity 会全屏显示。
如果您的应用以 API 级别 24 为目标平台,但您未指定此属性的值,则其值默认设为 true。
3、判断应用进入退出自由窗口模式
public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
}
每当 Activity 进入或退出多窗口模式时,系统都会调用此方法。当 Activity 进入多窗口模式时,系统会向该方法isInMultiWindowMode传递 true 值,退出多窗口模式时则传递 false 值。
可以通过newConfig中的mWindowingMode窗口模式来判断是否进入退出自由窗口,其中自由窗口的mWindowingMode为freeform,全屏的mWindowingMode为fullscreen,其他窗口模式可打印newConfig来查看,其中mWindowingMode是非public的,可以通过newConfig.toString().contains("mWindowingMode=freeform")间接获取。
4、获取自由窗口的Task大小
public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
}
public void onConfigurationChanged(Configuration newConfig) {
}
可以通过newConfig 对象中的mBounds以及sw获取自由窗口的窗口大小,应用可以通过窗口的大小进行UI布局适配。
5、小窗上操作杆区域遮挡应用内容适配方案
- 应用全屏沉浸模式
app的根布局加上 android:fitsSystemWindows="true"
- 应用全屏非沉浸模式
不需要处理
6、焦点窗口适配
迷你小窗和小窗都有可能成为不是焦点窗口(Focus Window),小窗、迷你窗和底部的全屏应用是可以随意进行焦点切换的,操作哪个窗口哪个窗口就是焦点窗口,所以就要保证应用在没有焦点的前提下也是可以正常运行的,特别是视频,游戏类app,比如说某款游戏在失去焦点时会停止绘制,造成游戏界面黑屏等问题。焦点窗口进行切换时系统会回调Activity.onWindowFocusChanged(boolean hasFocus)方法。
7、Stop Playback
问题描述:
在切换到Multi Window状态下焦点发生变化/Switch/Resize时视频停止播放。
修改建议:
播放视频的Activity不要在其onPause()中暂停视频,建议在onStop()中处理暂停,在onStart()中播放。
从Android P开始,应用可以增加支持Multi-resume属性,支持以后,在多窗口中的应用都会处于Resume状态,而非pause状态。
8、小窗上下杆子的背景色
应用可以通过设置状态栏,导航航栏的颜色调整上下杆子的背景色,但是不是绝对的,
横屏游戏等特殊场景上下杆子的背景色系统侧做了处理,是固定不变的。
9、适配Activity大小切换时不重启, 正确处理Configuration变化
强烈建议应用适配Activity窗口大小切换时不重启,遵循google规范,在android:configChanges 属性增加 screenSize|screenLayout|orientation|smallestScreenSize,并在Activity的onConfigurationChanged回调中更新宽高刷新各个子布局。
10、 Display APIs
- 获取屏幕大小
R版本之前:Display.getRealSize()、Display.getRealMetrics()。
R版本之后:WindowManager.getMaximumWindowMetrics() 。
- 获取当前窗口大小
R版本之前: Display.getSize() 。
R版本之后:WindowManager.getCurrentWindowMetrics() 。
11、注意事项
所有的Configuration对象要用接口入参newConfig对象做相关的处理逻辑,不要通过context.getResources().getConfiguration()等方式去获取,可能存在Configuration内容还没有被系统更新的情况。
五、联系我们
如遇技术问题,请联系 qujianjiang@xiaomi.com ;libowen1@xiaomi.com。