折叠屏适配说明更新时间: 2024-12-16 15:02:00

一、折叠屏介绍

折叠屏是一种柔性屏,可以进行弯曲、折叠,比如上下折叠,左右折叠等,其中 MIX FOLD 就是一款左右内折叠设备,MIX FOLD 的展开状态和折叠状态样式与屏幕大小如下:

外屏:6.52英寸,分辨率:2520x840

内屏:8.01英寸,分辨率:2480x1860

上传文件

上传文件

对于折叠屏设备,可以通过如下方法来判断

//可通过反射调用 SystemProperties 的 persist.sys.muiltdisplay_type 属性值来进行判断
boolean isFoldDisplay = SystemProperties.getInt("persist.sys.muiltdisplay_type", 0) == 2;

二、折叠屏UX设计与适配

1、应用连续性

在可折叠设备上运行时,应用可以自动从一个屏幕转换到另一个屏幕,为了提供出色的用户体验,请务必要确保当前任务能在转换后继续无缝执行,应用应在同一位置以相同状态恢复,并且依然保持可用良好的布局。

三方应用支持连续性,需要在 AndroidManifest.xml 文件的 application 或者 activity 标签中添加 resizeableActivity=true 的属性:

<application
android:resizeableActivity="true">

<activity
android:resizeableActivity="true" />
</application>

若应用的 targetSDK 为 24 或以上,即便不设置 resizeableActivity 属性,其默认也为 true。

在设备发生屏幕切换后,应用应能妥善地保存界面状态或者支持配置变更。

1.1、保存界面状态

在应用的 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);
}

1.2、支持配置变更

应用也可以支持配置变更,保持 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();
}

1.3、页面布局适配

Android 10 (API 级别 29) 或更高版本支持更多种宽高比。对于可折叠设备而言,设备类型可以是超长、超薄的屏幕(例如屏幕宽高比为 21:9 的折叠设备),也可以是 1:1的屏幕,如要与尽可能多的设备兼容,需要尽量多针对以下屏幕宽高比测试自己的应用:

上传文件

如果无法支持上述某些高宽比,可以使用 maxAspectRatio 以及 minAspectRatio 来指明自己应用可以处理的最高宽高比和最低宽高比,此属性需要在 AndroidManifest.xml 文件的application或者 activity 标签中添加。结合未来设备可能的形态,安卓的建议是对屏幕尺寸支持的最小范围为 1:1 到 2.4 之间:

<application
android:maxAspectRatio="2.4">

<activity
android:maxAspectRatio="2.4" />
</application>

1.4、常见问题

  • 是否可以单独适配应用连续性,而不支持分屏或自由窗口?

当resizeableActivity设置为了true,则表明应用同时支持了分屏功能,如果应用本身不打算支持分屏或自由小窗口,那么可以单独声明一个属性来指明已对折叠屏连续性进行了适配。

在AndroidManifest.xml中application作用域中声明一个meta-data:

<meta-data    android:name="android.supports_size_changes" android:value="true" />
  • 在屏幕切换后,为什么获取的屏幕大小没有变化?

可能是使用的 context 不对,需要使用 activity 类型的 context,比如使用 activity 上下文从资源中获取窗口大小(px):

activity.getResources().getDisplayMetrics().widthPixels
activity.getResources().getDisplayMetrics().heightPixels
  • 应用已经设置了resizeableActivity 为 true,在屏幕折叠后为什么还是会被重启?

可能是因为应用被配置到了黑名单,可以联系我们验证,确认没问题即可移除黑名单

  • 应用如何判断当前处于小屏或者大屏?

应用页面初始化时,可以读取一次当前设备配置信息保存一下

mConfiguration = new Configuration(getResources().getConfiguration());

每次设备折叠状态发生变化时,在 onConfigurationChanged 回调方法中进行判断:

@Override
protected void onConfigurationChanged(Configuration newConfig) {

int changes = mConfiguration.updateFrom(newConfig);

boolean screenLayoutChanged = (changes & ActivityInfo.CONFIG_SCREEN_SIZE) != 0;
if (screenLayoutChanged) {
// screenLayoutChanged为true,说明系统的屏幕尺寸发生了变化
int screenSize = newConfig.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
// screenSize: Configuration.SCREENLAYOUT_SIZE_NORMAL为小屏,Configuration.SCREENLAYOUT_SIZE_LARGE为大屏
}

}

详细请参考Google官方文档:应用连续性

2、多应用分屏与自由窗口

2.1、掌上 PC 支持多个自由窗口模式

应用需要支持 resizeable,系统可以根据用户操作场景触发多个应用的自由窗口同时显示在前台,自由窗口的宽高比为 9:16,如已经适配自由窗口则默认适配 PC 模式。

详细请参考自由窗口适配文档:全局自由窗口适配说明

2.2、支持分屏和自由窗口模式

应用需要支持 resizeable,系统可以根据用户操作场景触发应用的分屏和自由窗口相互切换。

在 MIX FOLD 折叠屏设备上,屏幕展开状态下,分屏模式为左右分屏,而宽度且支持三个档位调节,应用可以通过最小宽度限定符的方式来进行布局的兼容适配。

以笔记应用为例,竖屏状态下:

处于左边档位时为 sw240dp

上传文件

处于中间档位(默认)时为 sw333dp

上传文件

处于右边档位时为 sw427dp

上传文件

同样的,横屏状态下,分屏三个档位对应的 small width 分别为 sw321dp,sw446dp,sw571dp。

详细请参考分屏适配文档:分屏功能适配说明

2.3、常见问题

  • 如何判断是否处于掌上 PC 模式?
//true则表示进入掌上 PC模式
boolean onPcMode = (context.getResources().getConfiguration().uiMode & 0x2000) != 0;
  • 如何区分自由窗口模式和 PC 自由窗口模式

反射调用 Activity 的 getWindowingMode 方法

int mode = Activity.getWindowingMode();
mode的值为 5,表示自由窗口模式
mode的值为 100,表示PC自由窗口模式
  • 多个窗口同时显示,如何判断焦点窗口

可以通过 Activity 的 onWindowFocusChanged 方法来判断

@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Log.d("MyActivity", "onWindowFocusChanged hasFocus :" + hasFocus);
}

3、窗口间数据拖放

窗口间的数据拖放,本质就是应用间的数据分享,应用适配的时候需要关注拖动权限。

3.1、读写公有目录文件需要申请读写外部存储权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

3.2、对于拖拽分享应用私有目录文件,使用 FileProvider 方式进行分享

开始执行拖放操作时,来源应用必须设置 DRAG_FLAG_GLOBAL 标志,以示用户可以将数据拖动到其他应用,而且来源应用必须同时设置 DRAG_FLAG_GLOBAL_URI_READ 和 DRAG_FLAG_GLOBAL_URI_WRITE 标志或者设置其中任一项,具体取决于目标应用对数据应具有的读写权限。

目标应用必须在处理用户拖入应用的数据之前调用 requestDragAndDropPermissions()。

详细请参考官方文档:拖放

官方 demo 实现:DragAndDropAcrossApps

三、测试

应用完成基本适配工作之后,可以通过以下方式进行测试验证。

1、Android Studio 3.5 提供多种可折叠模拟器,选择折叠设配进行测试

上传文件

2、通过 adb 动态修改分辨率

将手机分辨率在 1860x2480 和 880x2640 两个分辨率之间进行切换,模拟屏幕折叠与展开状态

//切换到展开状态
adb shell wm size 1860x2480

//切换到折叠状态
adb shell wm size 880x2640

3、小米云测平台真机测试

https://testit.miui.com/remote

四、联系我们

有任何问题可以随时联系我们:mi-support-thirdapps@xiaomi.com

邮件主题:小米折叠屏+APP名称