文档管理中心

应用布局适配智慧多窗

应用布局适配智慧多窗的意义

由于应用从全屏进入智慧多窗(悬浮窗/分屏)模式后,窗口尺寸、宽高比例会发生变化,所以需要开发者适配应用窗口在不同尺寸、不同比例下的自适应布局,以确保应用窗口在各种形态下都能呈现出最佳的视觉效果,提供更好的用户体验。

悬浮窗的比例

不同设备支持悬浮窗的比例如下所示:

展开
版本 设备 竖向悬浮窗宽高比 横向悬浮窗宽高比
- 手机 3:4.575 16:9
- 双折叠手机展开态、三折叠手机双屏态(M态) 9:16 16:9
HarmonyOS 7.0.0以下 三折叠手机三屏态(G态)、Tablet设备 9:16 16:9
HarmonyOS 7.0.0及以上 三折叠手机三屏态(G态)、Tablet设备 9:16、3:4、3:2 16:9
说明
  • 顶部窗口控制条的避让区域不包含在应用布局区域内,窗口高度去除避让区域的32vp为应用布局区域的高度。

  • 手机:悬浮窗模式下,应用窗口真实宽度为屏幕宽度。竖向时,高度根据宽高比3 : 4.575动态调整;横向时,高度根据宽高比16 : 9动态调整(该比例超出屏幕时,以当前全屏屏幕比例计算)。手机设备默认支持以上两种比例,以下为特殊形态设备作说明。

  • 双折叠手机展开态、三折叠手机双屏态(M态):悬浮窗模式下,应用窗口真实宽度为折叠屏手机折叠态时的屏幕宽度。竖向时,高度根据宽高比9 : 16动态调整;横向时,高度根据宽高比16 : 9动态调整。

  • 搭载HarmonyOS 7.0.0以下的三折叠手机三屏态(G态)、Tablet设备:悬浮窗模式下,窗口尺寸根据屏幕尺寸进行动态调整。

  • 搭载HarmonyOS 7.0.0及以上的三折叠手机三屏态(G态)、Tablet设备:竖向悬浮窗新增比例3:4和3:2,窗口尺寸根据屏幕尺寸进行动态调整,用户可通过拖拽悬浮窗边框进行调节宽高比例。

  • 外屏为小方形屏的阔折叠手机,在外屏中不支持智慧多窗。阔折叠手机折叠状态请参考阔折叠应用开发,三折叠手机折叠状态请参考三折叠应用开发

分屏的比例

目前支持两种分屏样式:“上下分屏”和“左右分屏”。

分屏比例指的是分屏下两应用间尺寸的比例,调整分屏比例会调整应用窗口的大小。

默认形成分屏后分屏比例为1:1,拖动中间的分屏条可以改变分屏比例档位。手机“上下分屏”可调节档位1:2、1:1、2:1,“左右分屏”可调节档位为1:1。手机折叠屏展开态可调节档位只有1:1。

展开
设备 默认分屏比例 分屏可调节档位
手机 1:1

“上下分屏”: 1:1, 1:2, 2:1

“左右分屏”: 1:1

手机折叠屏展开态 1:1 “上下分屏”和 “左右分屏”: 1:1

应用布局可以通过自适应布局和响应式布局来更新自身布局,避免出现截断、挤压、堆叠等现象。

应用布局适配智慧多窗的方案

无论是悬浮窗还是分屏,当应用进入智慧多窗模式时,应用的窗口尺寸发生变化,所以应用需要根据不同的窗口尺寸调整自身布局。

主要可以通过窗口的on('windowSizeChange')方法实现对窗口尺寸大小变化的监听。再根据窗口的尺寸变化,更新调整自身应用布局以实现适配。

主要步骤和示例如下:

  1. 在onWindowStageCreate方法中,获取Window对象。

  2. 通过getWindowProperties方法返回值中的windowRect获取窗口尺寸,写入AppStorage中用于UI侧窗口尺寸的首次初始化赋值。

  3. 使用on('windowSizeChange')注册窗口尺寸变化时的监听,并写入AppStorage中供UI侧布局使用。

  4. UI侧通过@StorageLink绑定窗口尺寸后,AppStorage中属性key值对应的数据一旦改变,UI侧会同步修改。

  5. @StorageLink装饰的数据本身是状态变量,所以窗口尺寸发生变化时,会引起组件的重新渲染,开发者可以根据最新的窗口尺寸动态调整应用布局。

收起
自动换行
深色代码主题
复制
  1. // EntryAbility.ets
  2. import { UIAbility } from '@kit.AbilityKit';
  3. import { window } from '@kit.ArkUI';
  4. export default class EntryAbility extends UIAbility {
  5. onWindowStageCreate(windowStage: window.WindowStage): void {
  6. console.info('Ability onWindowStageCreate.');
  7. windowStage.getMainWindow().then((windowClass) => {
  8. // 获取窗口尺寸,存入AppStorage
  9. AppStorage.setOrCreate('winWidth', windowClass.getWindowProperties().windowRect.width);
  10. AppStorage.setOrCreate('winHeight', windowClass.getWindowProperties().windowRect.height);
  11. // 监听窗口尺寸变化
  12. windowClass.on('windowSizeChange', (windowSize) => {
  13. AppStorage.setOrCreate('winWidth', windowSize.width);
  14. AppStorage.setOrCreate('winHeight', windowSize.height);
  15. });
  16. });
  17. windowStage.loadContent('pages/Index', (err) => {
  18. if (err.code) {
  19. console.error('Failed to load the content. Cause: ' + JSON.stringify(err));
  20. return;
  21. }
  22. console.info('Succeeded in loading the content.');
  23. });
  24. }
  25. }
收起
自动换行
深色代码主题
复制
  1. // Index.ets
  2. @Entry
  3. @Component
  4. struct Index {
  5. // 初始化参数,这里会初始化为AppStorage中存储的值
  6. @StorageLink('winWidth') winWidth: number = 1260;
  7. @StorageLink('winHeight') winHeight: number = 2224;
  8. aboutToAppear() {
  9. console.info('Current window size. width: ' + this.winWidth + ', height: ' + this.winHeight);
  10. }
  11. build() {
  12. Row() {
  13. // 根据winWidth、winHeight动态调整应用布局
  14. // ...
  15. }
  16. .size({
  17. width: this.getUIContext().px2vp(this.winWidth),
  18. height: this.getUIContext().px2vp(this.winHeight)
  19. })
  20. .backgroundColor('#fceaeaea')
  21. }
  22. }

请输入您想要搜索的关键词