一、概述
1、小米大屏设备介绍
1.1、折叠屏形态与尺寸
折叠屏是一种柔性屏,可以进行弯曲、折叠,比如上下折叠,左右折叠等。
Xiaomi MIX Fold 和 Xiaomi MIX Fold 2 均为左右内折叠设备,其展开状态和折叠状态屏幕大小和分辨率如下:
机型 | 外屏 | 内屏 | ||
尺寸 | 分辨率 | 尺寸 | 分辨率 | |
Xiaomi MIX Fold | 6.52英寸 | 2520x840 | 8.01英寸 | 2480x1860 |
Xiaomi MIX Fold 2 | 6.56英寸 | 2520x1080 | 8.02英寸 | 2160x1914 |
判断是否为折叠屏设备的接口为:
//可通过反射调用 SystemProperties 的 persist.sys.muiltdisplay_type 属性值来进行判断
boolean isFoldDisplay = SystemProperties.getInt("persist.sys.muiltdisplay_type", 0) == 2;
折叠/展开态的判断接口为:
// 0 UNKNOWN
// 1 折叠
// 2 半折(MIX Fold 2支持)
// 3 展开
final int posture = Settings.Global.getInt(this.getContentResolver(), "device_posture", 0);
1.2、平板设备形态与尺寸
小米平板设备屏幕大小和分辨率信息如下:
尺寸 | 分辨率 | |
小米平板5 | 11 英寸 | 2560 x 1600 |
小米平板5 Pro | 11 英寸 | 2560 x 1600 |
小米平板5 Pro 5G | 11 英寸 | 2560 x 1600 |
小米平板5 Pro 12.4 | 12.4 英寸 | 2560 x 1600 |
判断是否为平板设备的接口为:
public static boolean isTablet(){
/**应用需反射调用*/
return SystemProperties.get("ro.build.characteristics").contains("tablet");}
应用也可以动态判断当前窗口显示在大屏下:
public static boolean isTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;}
1.3、可扩展性
小米大屏设备品类形态未来将会有更多丰富的产品,因此应用适配后需要支持一定程度拉伸。
2、文档适用对象
需要适配小米大屏设备应用的第三方开发者、UX设计师、系统工程师、测试。
二、UX设计与软件形态适配建议
1、基础体验设计
1.1、字体
- 优先调用系统默认字体来保证整台设备的阅读体验一致性,除非有特殊需求;
- 排版及字号字重应保证清晰可读;
- 在折叠屏上,建议保持内外屏字号大小一致,展开大屏字号大小如要放大,最大不能超过外屏小屏的1.2倍。
1.2、图片、视频
- 这些资源不应该出现变形、模糊或者显示不全的问题,影响体验;
- 在折叠屏上,建议图片、视频等信息内容在内外屏采用动态布局,保持图片视频等内容大小一致;展开大屏的图片视频等内容大小如要放大,最大不能超过屏幕高度。
1.3、弹窗
- 弹窗在应用设计中比较常见,如运营内容、广告营销等,建议弹窗大小适中,且有清晰的供用户关闭的按钮;
- 在折叠屏上,建议弹窗大小内外屏保持一致;展开大屏的弹窗如要放大,最大不能超过屏幕高度的70%。
2、页面布局设计
2.1、动态布局
- 大屏设备能够在竖屏和横屏之间无缝切换,折叠屏设备还能够在内屏和外屏之间无缝切换,拥有强大的功能和内容体验。
- 应用可能会遇到以下几种窗口情况:
基于以上情况,推荐几种布局方式 :
A.拉伸
仅卡片区域、显示区域等拉伸,文字大小图标大小均保持一致。
B.缩放
根据窗口区域等比缩放内容信息。
C.拓展/增量/减量
根据窗口区域增加或减少项,项的尺寸大小保持不变。
D.重新布局
根据窗口区域重新对内容进行布局,以适应更好的信息阅读。
3、不同类型应用适配建议
针对不同行业,不同类型应用,我们推荐以下五种布局方案:多列布局,Tab拉伸布局,分栏布局,左右布局和横屏拉宽。
适配方式 | 应用所属行业 |
多列布局 | 金融理财,居家生活,时尚购物,影音视听,医疗健康,学习教育 |
Tab拉伸布局 | 新闻资讯,图书阅读,摄影摄像,短视频 |
分栏布局 | 聊天社交,效率办公 |
左右布局 | 实用工具,音乐,时钟,天气,体育运动 |
横屏拉宽 | 游戏,旅游交通 |
针对以上适配方式,具体描述和详细示意图如下:(左图为APP在手机上的效果,中图为APP在折叠屏内屏上的效果,右图为APP在大屏设备上的效果)
A.多列布局
在应用首页,此类适配下顶部和底部的Tab拉伸到适合大屏设备页面的大小,同时首页主要功能键/APP推荐位置数量增加。
B.Tab拉伸
Tab拉伸适配下,页面主要内容不变,页面两侧加上与主要页面背景色同色/相近的背景,同时顶部和底部的Tab拉伸到适合大屏设备页面的大小。顶部按键数量相比于手机可有相应提升。
C. 分栏布局
分栏适配下,大屏设备上的页面分栏模式与电脑端的IM社交应用保持一致。
D.左右布局
左右布局下,顶部和底部的Tab拉伸到适合大屏设备页面的大小,内部页面左右分列,左侧展示主要的文字性内容,右侧展示相应的图片,视频等。
E.横屏拉宽
此类适配下,APP界面在大屏设备内横屏时,横向铺满屏幕。
三、通用开发适配指南
1、屏幕尺寸兼容性
应用resizeable能力支持
运行 Android 的设备多种多样,尤其是当前已出现或未来可能出现的折叠屏设备,它们有着不同的屏幕尺寸和像素密度,而且在折叠屏设备从展开到折叠的切换过程中,同一个设备可能出现多种屏幕尺寸的使用状态。您在做app设计和开发的时候应该考虑支持不同屏幕尺寸和像素密度,以确保界面能够在各类屏幕上美观地呈现。
折叠屏之所以需要适配,是因为我们的应用有可能在运行的过程中,所在的屏幕尺寸发生了变化,这种情况对现有项目多少都会产生一些问题。 所以折叠屏适配的本质是: 当应用运行时,屏幕的尺寸、密度或比例发生了变化,应用能够继续在变化后的屏幕上正常显示和正常运行。
允许改变应用尺寸要适配折叠屏,首先是要让应用支持动态改变尺寸,我们需要根据应用面向的API Level (targetSdkVersion)进行支持resizeable能力在 manifest 中的 Application 或对应的 Activity 下声明:
- 如果应用程序面向API Level 24以上(targetSdkVersion>=24),系统将默认应用支持resizeable能力。
- 如果应用程序面向API Level 24以下(targetSdkVersion< 24),需要应用在manifest中显式的声明android:resizeableActivity=true, 才可以支持resizeable能力 。
android: resizeableActivity = ["true" | "false"]
备注:虽然安卓提供了申请受限屏幕能力,但强烈建议您为应用设计resizeable能力,因为一旦您声明了受限屏幕比例(最大或最小)这意味着,当您的app运行在一个屏幕比例超出了您声明的范围,您的应用程序在屏幕上将出现黑边等现象。
详细信息请参阅Android开发者指南: https://developer.android.google.cn/guide/practices/screens_support
2、横竖屏状态获取
需要通过判断AppWindow的宽高比判断是横屏还是竖屏。
(1)宽:高 >= 1为横屏
(2)宽:高 < 1为竖屏
传递给应用的Configuration中的orientation会标识当前是横屏还是竖屏 。
(1)Configuration.ORIENTATION_LANDSCAPE为横屏
(2)Configuration.ORIENTATION_PORTRAIT为竖屏
3、横屏适配情况标记
应用主动适配大屏设备横屏,采用适配全屏的多列布局、Tab拉伸、分栏布局、左右布局、横屏拉宽等方式,需要在AndroidMainfest.xml文件设置标记。设置了此标记,横屏下会优先使用应用自己适配的横屏布局,而不是进入平行窗口下的横屏模式。
<!-- support landscape for large screen(PAD) -->
<meta-data
android:name="LandscapeForPad"
android:value="true" />
4、折叠屏连续性支持
折叠连续性的定义:应用在可折叠设备上运行时,当屏幕发生折叠/展开动作,处于前台的应用会从一个屏幕转换到另一个屏幕,为提供出色的用户体验,确保当前应用能在转换后能连续无缝、正常地运行,应用应在同一位置以相同状态恢复,并且依然保持可用良好的UI布局。
三方应用需在 AndroidManifest.xml 文件的 application层级中添加 android.supports_size_changes或者miui.supportAppContinuity
属性,以便声明应用支持连续性:
<application>
<meta-data
android:name="android.supports_size_changes"
android:value="true" />
</application>
<application>
<meta-data
android:name="miui.supportAppContinuity"
android:value="true" />
</application>
Activity的配置应该尽量支持resizeableActivity。应用需要在 AndroidManifest.xml 文件的 application 或者 actvivity 标签中添加 resizeableActivity=true 的属性。若应用不支持多窗口(例如小窗、分屏等)而声明了resizeableActivity=false,则在折叠屏折叠/展开场景中,可能出现UI布局问题、或者进入到原生的安卓兼容模式(SizeCompatMode)。
<application
android:resizeableActivity="true">
<activity
android:resizeableActivity="true" />
</application>
若应用的 targetSDK 为 24 或以上,即便不设置 resizeableActivity 属性,其默认值也为 true。
在设备发生屏幕切换后,应用应能妥善地保存界面状态或者支持配置变更。
保存界面状态 在应用Activity 被系统销毁重走生命周期时,应用需要及时保存和恢复 Activity 的界面状态,应用可以在 onSaveInstanceState 和 onRestoreInstanceState 方法中保存和恢复数据状态:
@Override
public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
支持配置变更 应用也可以支持配置变更,保持 Activity 不重走生命周期,这时需要应用在 AndroidManifest.xml 中配置如下 configChanges 属性:
<activity android:configChanges="screenSize|smallestScreenSize|screenLayout" />
添加 android:configChanges 后,Activity 或者 Fragment 就会收到 onConfigurationChanged() 的回调,此方法会收到传递的Configuration
对象,从而指定新设备配置。通过读取Configuration
中的字段确定新配置,然后通过更新界面所用资源进行适当的更改。调用此方法时,Activity 的Resources
对象会相应地进行更新,并根据新配置返回资源,以便您在系统不重启 Activity 的情况下轻松重置界面元素。
代码示例:
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Toast.makeText(this, "onConfigurationChanged newWidth="
+ newConfig.screenWidthDp + ", newHeight="
+ newConfig.screenHeightDp, Toast.LENGTH_SHORT).show();
}
MIUI针对折叠屏设备新增了针对app侧的wm_on_configuration_changed_called回调EventLog,结合系统侧configuration_changed回调EventLog日志和"Config changes"调用的SystemLog,可以方便您快速定位、排查与onConfigurationChanged回调有关的问题。
Log示例:
// 系统侧触发configurationChanged事件日志(EventLog)
07-20 12:43:31.521 1000 2677 2778 I configuration_changed: 536874240
// App侧触发configurationChanged回调事件日志(EventLog),4个参数分别代表userId、目标Activity、Configuration、耗时。
07-20 12:43:31.701 10086 5585 5585 I wm_on_configuration_changed_called: [0,com.miui.home.launcher.Launcher,{1.0 ?mcc?mnc [zh_CN] ldltr sw696dp w696dp h738dp 440dpi lrg hdr widecg port ?pc finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1914, 2160) mAppBounds=Rect(0, 0 - 1914, 2116) mMaxBounds=Rect(0, 0 - 1914, 2160) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=home mAlwaysOnTop=undefined mRotation=ROTATION_0 mInSplitScreen=false} as.2 s.24 fontWeightAdjustment=0 themeChanged=0 themeChangedFlags=0 extraData = Bundle[{}] dt/m/d},96]
// Config changes关键字SystemLog
2022-07-14 09:54:11.891 2485-2638/system_process I/ActivityTaskManager: Config changes=20000d00 {1.0 ?mcc?mnc [zh_CN] ldltr sw696dp w696dp h738dp 440dpi lrg hdr widecg port ?pc finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1914, 2160) mAppBounds=Rect(0, 0 - 1914, 2116) mMaxBounds=Rect(0, 0 - 1914, 2160) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_0 mInSplitScreen=false} as.2 s.8214 fontWeightAdjustment=0 themeChanged=0 themeChangedFlags=0 extraData = Bundle[{}] dt/s/d}
适配调试命令
在对三方应用折叠屏连续性支持情况测试的过程中,我们发现部分应用虽自行处置了配置变更,在AndroidManifest.xml中配置了screenSize|smallestScreenSize|screenLayout等configChanges属性,并回调onConfigurationChanged方法对屏幕做了适配,Activity不会重建,也不会重走生命周期。但应用的Activity仍然存在很多控件显示问题。
为了带给用户良好的使用体验,我们在系统中忽略了这部分app的configChanges属性配置,强制让应用的Activity执行重建,并重走生命周期,以达到界面完美显示的效果,我们将这种行为称为relaunch。
为了方便您在我们的设备上进行适配,我们提供了如下命令帮助您屏蔽上述的relaunch行为。
屏蔽relaunch行为,是我们在经过充分测试评估后,认为您的应用即使执行relaunch,也无法达到连续性适配测试标准,甚至因relaunch重走生命周期,导致折叠展开后亮屏变慢、回到桌面、闪退、ANR等问题,因此屏蔽relaunch行为,旨在屏蔽上述亮屏变慢、回到桌面、闪退、ANR等一系列连续性、稳定性问题。
如果您希望通过relaunch重建Activity生命周期来适配折叠屏连续性,您需要关注上述的连续性、稳定性问题,避免在重建Activity生命周期中执行耗时操作,影响折叠展开时的应用性能、亮屏速率等,并避免在onDestroy里调用finish,以免折叠展开后回到桌面。
通过如下命令,您的应用在没有配置screenSize|smallestScreenSize|screenLayout等configChanges属性的情况下,折叠展开操作时仍能正常回调onConfigurationChanged方法,Activity不会重建,生命周期不会重走,但与此同时,在折叠屏折叠展开操作时可能会有通知提醒您应用显示存在异常,需要重启。您无需理会上述系统通知,它不会对您的适配造成任何影响。
adb shell wm dump -setForceDisplayCompatMode 应用包名 blocklist
上述命令会导致您的应用无法执行relaunch重建,即使您的应用没有配置screenSize|smallestScreenSize|screenLayout等configChanges属性,但您的应用仍能正常回调onConfigurationChanged方法。为了您的应用能自行处置screenSize|smallestScreenSize|screenLayout等configChanges属性,您可以直接使用下面的命令,该命令会将您的应用恢复到Android 原生的处置配置变更的流程,便于您进行适配工作。与此同时,该命令会帮助您屏蔽掉重启通知,以免对您的适配工作造成打扰。
adb shell wm dump -setForceDisplayCompatMode 应用包名 allowlist
如果您希望恢复relaunch状态,可执行如下命令(尽管我们不建议您这么做,仍然希望您能通过configChanges进行适配工作):
adb shell wm dump -setForceDisplayCompatMode 应用包名 relaunchlist
请注意:以上命令行为不会在设备中持久化保存,在设备重启后就会失效。如有需要,您可再次执行上述命令。此外,执行命令后,您需要将您的应用从最近任务移除后重新启动,来保证命令生效。
如您已完成应用连续性适配,可以联系我们,在测试您的应用达到连续性标准后,我们会通过云控的方式将您的应用从relaunch名单中移除,待您的设备收到云控更新后,您的应用将不会再执行relaunch行为。
页面布局适配 Android 10 (API 级别 29) 或更高版本支持更多种宽高比。对于可折叠设备而言,设备类型可以是超长、超薄的屏幕(例如屏幕宽高比为 21:9 的折叠设备),也可以是 1:1 的屏幕,如要与尽可能多的设备兼容,需要尽量多针对以下屏幕宽高比测试自己的应用:
如果无法支持上述某些高宽比,可以使用 maxAspectRatio
以及 minAspectRatio
来指明自己应用可以处理的最高宽高比和最低宽高比,此属性需要在 AndroidManifest.xml 文件的 application 或者 actvivity 标签中添加。例如:
<application
android:maxAspectRatio="2.4">
<activity
android:maxAspectRatio="2.4" />
</application>
详细信息请参阅Android开发者指南:https://developer.android.com/guide/topics/ui/foldables?hl=zh-cn#%E5%BA%94%E7%94%A8%E8%BF%9E%E7%BB%AD%E6%80%A7
5、H5页面适配
我们推荐项目使用响应式设计,实现同一页面自动适配多种屏幕尺寸的效果。
5.1、元标签设置
通常情况下,开发者应使用元标签将视口大小调整为屏幕宽度,以确保元素尺寸按照预期显示。
<meta name="viewport" content="width=device-width,initial-scale=1">
开发者可以提供额外的参数来限制用户的缩放行为,一般来说这样做可以优化普通用户体验,减少误操作,但会影响视力障碍用户进行缩放操作,造成访问性问题。
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
5.2、使用相对 CSS 长度单位
我们推荐开发者在响应式开发中尽量使用相对长度单位,包括:em
、rem
、 %
、 vw
、 vh
。以下是这些单位的一般使用场景。
em | 尺寸与当前字体大小相关 |
rem | 尺寸相对固定,基于断点与屏幕宽度成阶梯性相关 |
% | 尺寸与父元素相关 |
vw | 区别于 rem ,尺寸与屏幕宽度成线性相关 |
vh | 尺寸与屏幕高度成线形相关 |
上述的只是一般情况,实际开发中使用哪个单位还需视设计要求而定,合理使用长度单位能起到事半功倍的效果。
5.3、布局方式
在响应式开发中,开发者应优先使用以下方式进行布局,构建适应性更强的页面。
A. Flexbox(弹性布局)
使用 display: flex
可令容器元素启用弹性布局。即使在不确定容器内元素尺寸的情况下,开发者也可以灵活控制元素的大小比例和对齐方式。
参考资料: https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox
B. Grid(栅格布局)
Flexbox 可以很好地解决同一行/列内元素的布局问题,Grid 则更适合用于拥有多行/列的二维布局。使用 display: grid
可令容器元素启用栅格布局。开发者可灵活控制行列间距、大小比例、对齐方式。
参考资料:https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia
5.4、CSS 媒体查询
使用 CSS 媒体查询技术,可以使同一元素的样式在不同设备下有不同的表现。通常,我们使用设备屏幕宽度作为判断设备类型的依据,以下是我们推荐的断点划分规则。
屏幕宽度范围 | 设备类型 |
320 px < width ≤ 480px | 手机竖屏、折叠屏小屏竖屏 |
480 px < width ≤ 680px | 折叠屏展开竖屏 |
680 px < width ≤ 960px | 手机横屏、折叠展开横屏、折叠屏小屏横屏 |
1200px < width | 桌面端设备 |
一般情况下,建议开发者使用媒体查询统一控制根字体大小,简化适配流程。
html {
font-size: 16px;
}
@media screen and (min-width: 480px) {
html {
font-size: 17px;
}
}
@media screen and (min-width: 680px) {
html {
font-size: 18px;
}
}
5.5、Javascript 媒体查询
在一些特殊情况下,页面需要根据断点进行更加复杂的调整。如页面文案,交互逻辑等需要随断点而变化。此时需要使用 Javascript 进行更加细微的调整,我们推荐开发者使用 matchMedia
方法进行断点识别,断点划分方案建议与 CSS 方案保持一致。
参考资料: https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia
5.6、其他建议
1.使用响应式图片,用于图片进行尺寸匹配的场景。
img {
/* 按比例拉伸或缩放至父元素宽度 */
width: 100% }
img {
/* 按比例缩放至父元素宽度,不拉伸 */
max-width: 100%
}
img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
/* 按比例拉伸或缩放至父元素宽高 */
object-fit: cover;
object-position: center;
}
2.为块级元素添加 max-width
而非 width
,避免在更小尺寸的显示设备上宽度溢出。
四、平行窗口适配指南
推荐采用Android 12L方案进行适配,您可自主定义activity在左右分屏间的跳转方式。
详细适配文档可参考:https://developer.android.com/guide/topics/large-screens/activity-embedding
Sample:https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:window/window-samples/
平行窗口适配情况标记
应用主动适配12L平行窗口,需要在AndroidMainfest.xml文件设置标记。
<!-- support 12L Activity Embedding for large screen -->
<meta-data
android:name="embedded"
android:value="true" />
五、进阶开发适配指南--小窗、迷你窗及分屏
1、小窗迷你窗功能介绍
1.1、小窗
在多任务处理场景下,小窗意在解决临时使用某个应用的场景,例如:在使用游戏应用时,不便离开,但想发消息给朋友,此时就可以借助小窗打开第二应用。
1.2、迷你窗
迷你小窗意在解决应用临时挂机的场景,例如:等待网约车、等待游戏更新、观看直播等。
2、小窗迷你窗适配指南
小窗适配技术文档:https://dev.mi.com/xiaomihyperos/documentation/detail?pId=1593
MIUI的小窗是基于Android的多窗口Freeform方案实现的。
小窗目前主要问题是应用兼容性导致的一系列问题,内容显示不全、Touch事件不响应等等,其实根本原因是应用没有很好的支持、适配多窗口、多分辨率,如下是小窗适配的一些参考性适配指南。
多窗口适配支持文档: https://developer.android.com/guide/topics/ui/multi-window#dnd
支持不同屏幕分辨率的开发技巧文档: https://developer.android.google.cn/training/multiscreen/screensizes
2.1、常用适配方法
1) 如何支持小窗
支持小窗的方式非常简单,只需要声明一个属性,直接在AndroidManifest.xml中 配置属性android:resizeableActivity="true" ,不支持小窗直接配置为false,系统默认是支持小窗的。
2)判断自己是否在小窗
Activity.onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig)
Activity.isInMultiWindowMode() 判断是否处于多窗口
Activity.getWindowingMode() 当返回5时表示小窗,需要反射调用
String config = context.getResources().getConfiguration().toString();
boolean isInFreeformWindow = config.contains("freeform");
3)获取小窗的位置/大小等信息
context.getResources().getConfiguration().windowConfiguration.getBounds(),其中Configuration对象里也有小窗的模式以及bounds,所以我们也需要重写ConfigurationChanged方法,并对界面布局做相应调整,如切换布局、调整控件位置和间距等。
4)Activity大小切换时不重启适配
强烈建议应用在Activity窗口大小切换时不重启适配,遵循google规范,在android:configChanges 属性增加 screenSize|screenLayout|orientation|smallestScreenSize,并在Activity的onConfigurationChanged回调中更新宽高刷新各个子布局。
5)特别需要注意的适配点,焦点窗口适配
迷你小窗和小窗都有可能成为不是焦点窗口(Focus Window),其中迷你小窗一定是没有焦点的,小窗和小窗下面的全屏应用是可以随意进行焦点切换的,touch在哪个窗口,哪个窗口就是焦点窗口,所以就要保证应用在没有焦点的前提下也是可以正常运行的,特别是视频类app。关键方法:Activity.onWindowFocusChanged(boolean hasFocus)
6)获取屏幕宽高有些APP会跟随屏幕大小动态计算View的大小,但是有些接口在多窗口形式下面并不试用,要注意以下几点:
- 在获取Display 对象 或者获取 Resources对象时使用Activity的Context 不要使用Application的Context;
- 获取Resources对象时不要用context.getResources().getSystem()用context.getResources()就行;
- Display下有getMetrics getRealMetrics getSize getRealSize四个方法, getRealMetrics和 getRealSize 永远会返回屏幕的宽高,无论应用是否在多屏下, 而getMetrics和getSize会可以获取Activity的大小。
7)获取View的位置
获取View的位置有两个方法:
- View.getLocationInWindow(int[] outLocation) 返回距离View所在的Window左上角的距离;
- View.getLocationOnScreen 返回距离屏幕左上角的距离(由于在小窗模式下应用的位置可以移动, 所以该返回值有时并非是你想要的,所以要慎用)。
2.2、其他说明
全局自由窗口功能在MIUI12安卓Q版本以上支持。
如果应用想要启用小窗或者分屏模式下的拖拽功能,请参考如下google资料进行适配:
Android Developer上的拖放文档:https://developer.android.com/guide/topics/ui/drag-drop
AOSP里的DragAndDrop样例应用:https://cs.android.com/android/platform/superproject/+/master:development/samples/browseable/DragAndDropAcrossApps/
github Demo下载连接:https://github.com/android/user-interface-samples/tree/main/DragAndDropAcrossApps
3、分屏功能介绍
分屏场景意在解决长时间并行使用两个应用时的场景,例如:一边听网课,一边记笔记等;一边看视频,一边逛知乎、微博等。
4、分屏适配技术文档
4.1、如何支持分屏
支持分屏的方式非常简单,只需要声明一个属性。从 7.0 开始,Android 新增了一个 Activity 属性: resizeableActivity ,以声明该 Activity 是否支持多窗口显示。
android:resizeableActivity=["true" | "false"]
如果这个属性设为 true ,Activity 就可以在分屏模式下显示;设为 false ,Activity 则不会在分屏模式下显示,而是会占满整个屏幕。因此开发者可以根据具体场景,仅让部分 Activity 支持分屏。
若开发者没有为 Activity 声明该属性,Android 会根据应用的 targetSDKVersion 及 Activity 的 screenOrientation 属性来综合判断是否可以在分屏显示。关于判断的详细逻辑,可以参考官方文档:https://developer.android.com/guide/topics/ui/multi-window.html#configuring
4.2、如何进一步优化分屏模式
配置 resizeableActivity 的属性,是适配分屏的最简单方式,但如果想要提供更好的使用体验,需要开发者做一定优化工作。下面是我们了解到的一些案例(测试机型:Nexus 6 Andriod 7.1),开发者可以根据自己的业务需求,做不同程度的优化。
4.3、减少不可滑动的页面/控件
在分屏过程中,屏幕高度只有原来的一半,如果有太多的控件不响应滑动事件,那么用户将无法上下滚动应用页面,甚至无法进行下一步操作。这类页面,最常见于Splash screen、登录注册页、音乐播放页、大图区域、弹窗等。
由于用户可以自由调整分屏的窗口比例,因此开发者只要减少了不可滑动的控件,分屏的可用性就会大大提高,是性价比非常高的优化方案。
4.4、尽可能使用相对位置,以兼容多种窗口尺寸
分屏时,屏幕的高度和宽度会发生变化,因此在书写控件布局时,尽量使用相对位置,以避免窗口大小改变时,控件无法显示或显示不全。这也是一种性价比很高的优化方案,可以保证用户在分屏时能正常使用应用。
4.5、注意多窗口下 Activity 的生命周期
视频、直播等类别的应用需要特别关注这一点。Android 7.0 在分屏时会同时运行两个应用,其中用户最后操作的那个应用会处于 Resumed 状态,另一个则会处于 Paused 状态。
这会带来一些问题,以视频应用为例,如果开发者在 onPaused 中处理视频的 「暂停/播放」,那在分屏时,就会因为用户操作另一个应用,导致视频停止播放。因此我们建议开发者在 onStart/onStop 中处理视频的「暂停/播放」,或者特殊处理分屏时的 Paused 状态。详见官方文档:https://developer.android.com/guide/topics/ui/multi-window#lifecycle
4.6、处理 Configuration Changes
由于分屏过程中,允许用户调整窗口的大小,这就会导致 Configuration 的改变。Android 的默认处理方式是 relaunch 整个 Activity,从而出现页面闪一下的问题。如果想避免闪一下的问题,建议开发者自己处理 Configuration 的变化。
4.7、给内容更多空间
分屏后,屏幕空间变得非常小了,为了给内容让出更多空间,应尽量减少常驻控件。一种解决办法是在浏览内容时,隐藏底部tab等常驻控件,用户回滚时再出现,以展示更多的内容。
4.8、为分屏定制新的布局(动态布局)
动态布局指根据当前的窗口大小,重新调整页面的布局。这是一项锦上添花的优化项,开发者可以酌情考虑是否添加此优化。
4.9、MIUI 分屏支持哪些设备
搭载 Android 7.0 或以上的 MIUI 手机均支持分屏。MIUI 也将尝试将分屏移植至 Android 6.0。因此将有数千万的新老设备支持分屏。
4.10、分屏如何调试
MIUI 的分屏方案完全兼容 Android 7.0,因此可以在任意运行 Android 7.x 的设备上调试,无需为 MIUI 作特别处理。同时,以上提到的案例均能在任意 Android 7.x 设备复现。调试过程中,建议开启以下设置项:「开发者选项 > 强制将活动设为可调整大小」,然后重启手机,之后系统就会强制应用进入分屏模式,以方便开发者观察应用在分屏时的表现。
六、开发与测试方式
1、模拟器调试
1)小米折叠屏可以在Android Studio里面选择模拟折叠设备进行参照:
2)平板设备可以在Android Studio里面选择模拟平板设备进行参照:
2、命令模拟调试
1)可以通过如下adb命令来模拟小米MIX FOLD 2折叠屏手机切换折叠和展开的状态:
//切换到展开状态
adb shell wm size 1914x2160
//切换到折叠状态
adb shell wm size 1080x2520
2)可以通过如下adb命令来切换到平板设备的分辨率,例如:
//切换到2560x1600分辨率
adb shell wm size 1600x2560
3、云测平台真机测试
可以访问https://testit.miui.com/remote,进入小米云测平台:
以折叠屏为例,点击小米 MIX Fold 2机器,进入以下页面:
右侧可以上传apk文件,左侧真机可以实时操作。
4、测试用例建议
4.1、 用例1
在折叠屏的展开态下打开应用,应用的界面显示正常
1.测试步骤
(1)在折叠屏展开时,打开应用,观察各个页面的显示情况;
2.预期结果
(1)应用的所有页面均显示正常,没有任何变形、截断、模糊、缺失等问题;
4.2、用例2
在折叠屏的折叠态下打开应用,应用的界面显示正常
1.测试步骤
(1)在折叠屏折叠时,打开应用,观察各个页面的显示情况;
2.预期结果
(1)应用的所有页面均显示正常,没有任何变形、截断、模糊、缺失等问题;
4.3、用例3
在折叠屏的展开态下打开应用,应用的界面功能交互正常
1.测试步骤
(1)在折叠屏展开时,打开应用,依次点击各个页面的按钮;
2.预期结果
(1)应用的所有页面按钮均可以正常响应,没有任何无反应/crash/anr等问题;
4.4、用例4
在折叠屏的展开态和折叠态之间切换时,应用的界面显示和功能交互均正常
1.预制条件:应用已经适配了连续性
2.测试步骤
(1)在折叠屏展开时,打开应用;
(2)切换到折叠态,观察页面显示是否正常;
(3)点击页面的各个按钮,观察功能交互是否正常;
(4)在折叠态下打开应用;
(5)切换到展开态,观察页面显示是否正常;
(6)点击页面的各个按钮,观察功能交互是否正常。
3.预期结果
(1)应用在状态切换过程中,没有任何页面闪退重启、变形、截断、模糊、缺失等问题;
(2)应用界面的所有按钮功能均交互正常。
4.5、用例5
在分屏模式下,应用的界面显示和功能交互均正常
1.预制条件:应用支持分屏
2.测试步骤
(1)打开应用,进入分屏模式;
(2)观察页面显示是否正常;
(3)点击页面的各个按钮,观察功能交互是否正常。
3.预期结果
(1)应用在分屏模式下,没有任何页面变形、截断、模糊、缺失等问题;
(2)应用界面的所有按钮功能均交互正常。
4.6、用例6
进入应用的小窗模式,应用的界面显示和功能交互均正常
1.预制条件:应用支持小窗
2.测试步骤
(1)进入应用的小窗模式;
(2)观察页面显示是否正常;
(3)依次点击各个页面的按钮,观察功能交互是否正常。
3.预期结果
(1)应用在小窗模式下,没有任何页面变形、截断、模糊、缺失等问题;
(2)应用的所有页面按钮均可以正常响应,没有任何无反应/crash/anr等问题;
七、联系我们
如您在适配过程中遇到问题,辛苦联系客服,与我们取得联系。