首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

HarmonyOS Next开发学习手册——智慧多窗

  • 25-02-22 07:21
  • 3585
  • 13344
blog.csdn.net

智慧多窗是一种多任务处理解决方案,它允许用户在同一时间、同一屏幕上以悬浮窗或分屏的方式同时运行多个应用窗口。在智慧多窗的显示模式下,用户可以根据自己的需求,合理安排应用窗口的位置和大小。

悬浮窗

悬浮窗是一种在设备屏幕上悬浮的、非全屏的应用窗口。一般用于在已有全屏任务运行的基础上,临时处理另一个任务,或短时间多任务并行使用。如浏览网页的同时回复消息。

针对手机,一个屏幕内最多支持显示一个悬浮窗;在折叠屏手机展开态、平板类设备上,一个屏幕内最多支持显示两个悬浮窗。在超出悬浮窗显示最大个数限制时,打开新的悬浮窗会替换最近久未操作的悬浮窗。

悬浮窗的类型

悬浮窗的常见类型主要分为如下两种:

  • 竖向悬浮窗:一般用于新闻资讯、社交以及购物类应用等场景。

  • 横向悬浮窗:主要用于横向游戏和视频全屏播放的场景。

悬浮窗的触发及恢复方式

悬浮窗的触发方式有以下两种:

  • 手势触发:应用全屏时从屏幕底部向上滑至右上方热区,松手后可开启悬浮窗模式。

  • 通知消息下拉触发:在系统接收到通知消息未收起时,可直接下拉此通知消息开启悬浮窗模式。

悬浮窗的恢复方式主要有以下两种:

  • 多任务中心中恢复:对于已开启悬浮窗模式的应用,在进入多任务中心时,悬浮窗应用同全屏应用一起显示在多任务中心,用户选择点击悬浮窗应用卡片时可恢复悬浮窗模式。

  • 侧边条恢复:对于已开启悬浮窗模式的应用,其最小化后会暂存在屏幕上的侧边条中,点击或者长按侧边条可展开任务选择界面,选择点击侧边条中悬浮窗应用卡片时可恢复悬浮窗模式。

分屏

分屏一般用于两个应用长时间并行使用的场景。例如边看购物攻略、边浏览商品;边看视频、边玩游戏;看学习类视频的同时做笔记等。

分屏的触发方式

分屏通过手势触发:应用全屏时,从屏幕底部向上滑至左上方热区,进入待分屏状态,点击桌面另一个支持分屏的应用图标或卡片,可形成分屏。

应用声明支持智慧多窗

当应用需要智慧多窗的能力时,可以通过在 module.json5配置文件 中对应标签添加相关字段声明支持。

声明支持悬浮窗

开发者可以通过在module.json5配置文件中 abilities标签 下的supportWindowMode属性增加“floating”字段或使用默认值以声明应用支持悬浮窗。

supportWindowMode属性主要标识当前UIAbility所支持的窗口模式,支持的字段及含义如下表所示。

字段说明
fullscreen窗口支持全屏显示。
split窗口支持分屏显示。
floating支持悬浮窗显示。

在应用声明支持智慧多窗后,还可根据业务场景的需要配置是否支持横向悬浮窗或上下分屏模式。

当应用需要支持横向悬浮窗时,开发者可以通过在module.json5配置文件中abilities标签下的preferMultiWindowOrientation属性增加“landscape”或者“landscape_auto”配合API以声明应用支持横向悬浮窗或上下分屏模式。

preferMultiWindowOrientation属性主要标识当前UIAbility组件多窗布局方向,支持的字段及含义如下表所示。

配置值说明效果
portrait多窗布局方向为竖向。建议竖向游戏类应用配置。手机
手势触发悬浮窗:竖向悬浮窗
手势触发分屏:不支持
分屏样式切换:不涉及
折叠屏手机展开态
手势触发悬浮窗:竖向悬浮窗
手势触发分屏:形成左右分屏
分屏样式切换:不支持样式切换
landscape多窗布局方向为横向,配置后支持横向悬浮窗和上下分屏。建议横向游戏类应用配置。手机
手势触发悬浮窗:横向悬浮窗
手势触发分屏:不支持
分屏样式切换:不涉及
折叠屏手机展开态
手势触发悬浮窗:横向悬浮窗
手势触发分屏:形成上下分屏
分屏样式切换:不支持样式切换
landscape_auto多窗布局动态可变为横向,需要配合API( enableLandscapeMultiWindow  /  disableLandscapeMultiWindow )使用。建议视频类应用配置。系统识别应用为横向全屏播放:
手机
手势触发悬浮窗:横向悬浮窗
手势触发分屏:形成上下分屏
分屏样式切换:不涉及
折叠屏手机展开态
手势触发悬浮窗:横向悬浮窗
手势触发分屏:形成上下分屏
分屏样式切换:支持样式切换
系统识别应用为非横向全屏播放:
同配置为default
default缺省值,参数不配置时默认为default。 建议其他应用类配置。折叠屏手机折叠态 & 手机 手势触发悬浮窗:竖向悬浮窗 手势触发分屏:
形成上下分屏
分屏样式切换:不涉及
折叠屏手机展开态
手势触发悬浮窗:竖向悬浮窗
手势触发分屏:形成左右分屏
分屏样式切换:支持样式切换

声明支持分屏

开发者可以通过在module.json5配置文件中 abilities标签 下的supportWindowMode属性增加“split”字段或使用默认值以声明应用支持分屏。

supportWindowMode属性主要标识当前UIAbility所支持的窗口模式,支持的字段及含义如下表所示。

字段说明
fullscreen窗口支持全屏显示。
split窗口支持分屏显示。
floating支持悬浮窗显示。

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

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

悬浮窗的比例

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

设备竖向悬浮窗宽高比横向悬浮窗宽高比
手机3:4.57516:9
折叠屏手机展开态9:1616:9

说明

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

分屏的比例

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

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

默认形成分屏后分屏比例为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装饰的数据本身是状态变量,所以窗口尺寸发生变化时,会引起组件的重新渲染,开发者可以根据最新的窗口尺寸动态调整应用布局。
// EntryAbility.ets
import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';

export default class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage): void {
    console.info('Ability onWindowStageCreate.');
    windowStage.getMainWindow().then((windowClass) => {
      // 获取窗口尺寸,存入AppStorage
      AppStorage.setOrCreate('winWidth', windowClass.getWindowProperties().windowRect.width);
      AppStorage.setOrCreate('winHeight', windowClass.getWindowProperties().windowRect.height);
      // 监听窗口尺寸变化
      windowClass.on('windowSizeChange', (windowSize) => {
        AppStorage.setOrCreate('winWidth', windowSize.width);
        AppStorage.setOrCreate('winHeight', windowSize.height);
      });
    });
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error('Failed to load the content. Cause: ' + JSON.stringify(err));
        return;
      }
      console.info('Succeeded in loading the content.');
    });
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

// Index.ets
@Entry
@Component
struct Index {
  // 初始化参数,这里会初始化为AppStorage中存储的值
  @StorageLink('winWidth') winWidth: number = 1260;
  @StorageLink('winHeight') winHeight: number = 2224;

  aboutToAppear() {
    console.info('Current window size. width: ' + this.winWidth + ', height: ' + this.winHeight);
  }

  build() {
    Row() {
      // 根据winWidth、winHeight动态调整应用布局
      // ...
    }
    .size({
      width: px2vp(this.winWidth),
      height: px2vp(this.winHeight)
    })
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

顶部窗口控制条避让适配智慧多窗

顶部窗口控制条是应用窗口处于智慧多窗模式下,应用顶部的操作横条

顶部窗口控制条示意图如下所示:

顶部横条的避让可通过以下两种方式适配:

  • 使用窗口的避让能力:通过 setWindowLayoutFullScreen 设置窗口布局是否为沉浸式布局。

沉浸式布局是指应用布局不避让状态栏、导航栏以及智慧多窗顶部横条,这可能发生组件与顶部横条的重叠,导致文字遮挡、点击事件冲突等情况。非沉浸式布局是指布局避让状态栏、导航栏以及智慧多窗顶部横条,组件不会与其重叠。因此可设置isLayoutFullScreen值为false使窗口的布局为非沉浸式布局。

示例:

// Index.ets
import { BusinessError } from '@kit.BasicServicesKit';
import { window } from '@kit.ArkUI';

@Entry
@Component
struct Index {
  @State message: string = '非沉浸式布局';
  private windowClass: window.Window | undefined = undefined;

  aboutToAppear(): void {
    try {
      window.getLastWindow(getContext(this), (err: BusinessError, data) => {
        const errCode: number = err.code;
        if (errCode) {
          console.error('Failed to obtain the top window. Cause: ' + JSON.stringify(err));
          return;
        }
        this.windowClass = data;
        console.info('Succeeded in obtaining the top window. Data: ' + JSON.stringify(data));
      });
    } catch (exception) {
      console.error('Failed to obtain the top window. Cause: ' + JSON.stringify(exception));
    }
  }

  private setWindowLayoutFullScreen(isLayoutFullScreen: boolean) {
    if (!this.windowClass) {
      return;
    }
    try {
      this.windowClass.setWindowLayoutFullScreen(isLayoutFullScreen, (err: BusinessError) => {
        const errCode: number = err.code;
        if (errCode) {
          console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(err));
          return;
        }
        console.info('Succeeded in setting the window layout to full-screen mode.');
      });
    } catch (exception) {
      console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(exception));
    }
  }

  build() {
    Stack({ alignContent: Alignment.TopStart }) {
      Column() {
        Text(this.message)
          .fontSize(25)
          .fontWeight(FontWeight.Bold)
          .margin({
            top: '2%',
            bottom: '40%'
          })

        Button() {
          Text('设置窗口为沉浸式布局')
            .fontSize(18)
            .fontWeight(FontWeight.Normal)
        }
        .type(ButtonType.Normal)
        .borderRadius(15)
        .margin({ top: 20 })
        .stateStyles({
          normal: {
            .backgroundColor('#ff6b89d4')
          },
          pressed: {
            .backgroundColor('#ffc81f2a')
          }
        })
        .width('60%')
        .height('6%')
        .onClick(() => {
          this.setWindowLayoutFullScreen(true);
          this.message = '沉浸式布局';
        })

        Button() {
          Text('设置窗口为非沉浸式布局')
            .fontSize(18)
            .fontWeight(FontWeight.Normal)
        }
        .type(ButtonType.Normal)
        .borderRadius(15)
        .margin({ top: 20 })
        .stateStyles({
          normal: {
            .backgroundColor('#ff6b89d4')
          },
          pressed: {
            .backgroundColor('#ffc81f2a')
          }
        })
        .width('60%')
        .height('6%')
        .onClick(() => {
          this.setWindowLayoutFullScreen(false);
          this.message = '非沉浸式布局';
        })
      }
      .width('100%')
    }
    .backgroundColor('#fceaeaea')
    .height('100%')
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 应用主动避让:应用不使用窗口避让能力(即设置窗口为沉浸式布局),还通过 getWindowAvoidArea 接口可获取屏幕顶部需要规避的矩阵区域topRect,获取到该值后应用可对应做布局避让。同时可通过 on(‘avoidAreaChange’) 监听系统规避区域变化以进行布局的动态调整。
// Index.ets
import { BusinessError } from '@kit.BasicServicesKit';
import { window } from '@kit.ArkUI';

@Entry
@Component
struct Index {
  @State topSafeHeight: number = 0;

  aboutToAppear(): void {
    try {
      let windowClass: window.Window | undefined = undefined;
      window.getLastWindow(getContext(this), (err: BusinessError, data) => {
        const errCode: number = err.code;
        if (errCode) {
          console.error('Failed to obtain the top window. Cause: ' + JSON.stringify(err));
          return;
        }
        windowClass = data;
        windowClass.setWindowLayoutFullScreen(true);
        this.topSafeHeight = px2vp(windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRect.height);
        windowClass.on('avoidAreaChange', (data) => {
          if (data.type == window.AvoidAreaType.TYPE_SYSTEM) {
            this.topSafeHeight = px2vp(data.area.topRect.height)
          }
        })
        console.info('Succeeded in obtaining the top window. Data: ' + JSON.stringify(data));
      });
    } catch (exception) {
      console.error('Failed to obtain the top window. Cause: ' + JSON.stringify(exception));
    }
  }

  build() {
    Stack({ alignContent: Alignment.TopStart }) {
      // 顶部避让区域
      Row() {
      }
      .height(this.topSafeHeight)
      .width("100%")

      // 根据topSafeHeight动态调整应用布局
      // ...
    }
    .height('100%')
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

鸿蒙全栈开发全新学习指南

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以要有一份实用的鸿蒙(HarmonyOS NEXT)学习路线与学习文档用来跟着学习是非常有必要的。

针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

本路线共分为四个阶段:

第一阶段:鸿蒙初中级开发必备技能

在这里插入图片描述

第二阶段:鸿蒙南北双向高工技能基础:gitee.com/MNxiaona/733GH

第三阶段:应用开发中高级就业技术

第四阶段:全网首发-工业级南向设备开发就业技术:gitee.com/MNxiaona/733GH

《鸿蒙 (Harmony OS)开发学习手册》(共计892页)

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:gitee.com/MNxiaona/733GH

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH

鸿蒙入门教学视频:

美团APP实战开发教学:gitee.com/MNxiaona/733GH

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing?,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:gitee.com/MNxiaona/733GH

鸿蒙开发学习资料领取!!!
微信名片
注:本文转载自blog.csdn.net的OpenHarmony_小贾的文章"https://blog.csdn.net/maniuT/article/details/140593748"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top