前言

页面里的材质卡片调顺以后,真正进入业务场景时,沉浸光感往往会先出现在各种浮层里。

点击按钮弹出的说明气泡、承载操作项的菜单、鼠标悬浮时出现的提示,以及从底部展开的半模态页面,看起来都属于“盖在当前页面上方的一层内容”。可实际接入时,它们使用的接口、触发方式和承载的信息量并不相同。

我刚开始整理这几类组件时,也容易把注意力全部放在材质样式上。Popup 用 THIN,Menu 用 THICK,Sheet 用 ULTRA_THICK,似乎把枚举填进去就结束了。等到页面真正运行起来,新的问题很快就出现了:材质到底应该设置到按钮上,还是设置到浮层的 options 中;背景色和模糊是否还要保留;Tips 为什么在手机模拟器里没有反应;Sheet 设置材质后为什么依然像一块普通面板。

这些问题放在一起以后,我更倾向于先看浮层由谁创建,再决定材质放在哪里。

Popup、Menu、Tips 和 Sheet 都在各自的配置对象中提供了 systemMaterial。材质对象需要交给浮层本身,触发按钮只负责打开它。与此同时,浮层原有的背景色、模糊和阴影也要适当收敛,避免它们盖住系统材质。

当前实验把四种入口放在同一张页面中。Popup、Menu 和 Sheet 可以直接点击观察;Tips 依赖鼠标或手写笔悬浮事件,需要在能够触发悬浮事件的环境中运行。我的测试设备目前没有 HarmonyOS 7 实机测试权限,因此页面先在模拟器中核对接口和基础效果,浮层的材质层次与弹出动效仍需要在真机上复核。

一、四类浮层要先按触发方式分开

Popup、Menu、Tips 和 Sheet 都会覆盖在当前页面上方,但它们承担的任务差别很大。

Popup 通常围绕一个明确的宿主组件出现,适合展示简短说明、状态反馈或少量按钮。Menu 更强调操作集合,用户打开以后会从多个选项中完成一次选择。Tips 依赖悬浮事件,主要补充控件名称或短说明。Sheet 会占据更大的页面空间,可以承载表单、选项和相对完整的操作流程。

这四类浮层的材质入口也都位于自己的 options 中。

浮层常见触发方式材质入口建议起始样式更适合承载
Popup点击后切换显示状态PopupOptions.systemMaterialTHIN简短说明、状态提示
Menu点击或长按打开MenuOptions.systemMaterialTHICK一组操作选项
Tips鼠标或手写笔悬浮TipsOptions.systemMaterialTHIN控件名称、补充说明
Sheet状态绑定后展开SheetOptions.systemMaterialULTRA_THICK表单、设置、分步操作

上面这张表中的材质样式适合作为第一轮尝试。具体取值仍然要结合浮层面积、背景复杂度和内容密度来调整。

Popup 和 Tips 面积通常较小,内容也比较短,THIN 可以保留页面背景,让提示与宿主组件保持联系。Menu 的位置和背景难以提前确定,THICK 能够降低背景对菜单项的干扰。Sheet 面积更大,停留时间也更长,ULTRA_THICK 更容易建立稳定的前景区域。官方沉浸光感指南也分别使用 THINTHICKULTRA_THICK 演示了 Popup、Menu 与 Sheet 的材质配置。

Popup 的材质属于气泡本身

Popup 通过 bindPopup 绑定到宿主组件。系统气泡使用 PopupOptions,自定义气泡使用 CustomPopupOptions,两类配置都提供了 systemMaterial

Button('打开 Popup')
  .onClick(() => {
    this.showPopup = !this.showPopup;
  })
  .bindPopup(this.showPopup, {
    message: 'Popup 使用 THIN 沉浸材质',
    placement: Placement.Bottom,
    systemMaterial: this.thinMaterial
  })

这里的按钮只是触发入口。把 .systemMaterial() 设置到按钮上,只会改变按钮本身;Popup 的材质需要写进 PopupOptions

Popup 原本还支持 popupColorbackgroundBlurStyle、阴影和边框等属性。使用 systemMaterial 后,我通常会先保留最少的视觉配置。背景色、普通模糊和系统材质同时出现时,页面很难判断最终效果来自哪一层。

Menu 的材质写进 MenuOptions

Menu 可以通过 bindMenubindContextMenu 打开。菜单组件本身承载选项,触发按钮只负责显示入口。

Button('打开 Menu')
  .bindMenu(this.menuBuilder, {
    systemMaterial: this.thickMaterial
  })

菜单设计本身强调临时操作和清楚的选项层级。菜单可能覆盖图片、列表、视频或其他复杂背景,因此 THICK 是一个比较稳妥的起点。官方菜单设计指南也建议菜单采用沉浸光感样式,以增强浮层与页面之间的空间层级。

应用级状态使用 ENABLE 时,菜单控制会进入默认启用沉浸材质的范围。页面需要明确指定样式时,仍然可以通过 MenuOptions.systemMaterial 传入材质对象。DISABLE 会关闭应用中的全部沉浸式系统材质。

Tips 依赖悬浮事件

Tips 与另外三类浮层有一个明显区别。它会在鼠标或手写笔悬浮到组件上时自动显示,离开以后自动隐藏。

Button('悬浮查看 Tips')
  .bindTips('Tips 使用 THIN 沉浸材质', {
    systemMaterial: this.thinMaterial
  })

bindTips 从 API 19 开始提供,TipsOptions.systemMaterial 从 API 26.0.0 开始提供。Tips 依赖设备能够触发悬浮事件,无法产生悬浮事件的硬件环境也无法显示这类提示。

因此,手机触控场景不能把 Tips 当作点击提示使用。表格表头、图标说明、桌面端工具栏和支持鼠标输入的 2in1 页面,更适合采用 Tips。手机端需要点击后显示信息时,Popup 往往更直接。

Sheet 的材质需要覆盖整个面板

Sheet 通过 bindSheet 创建半模态页面。它会保留部分底层页面,同时在上方承载较完整的内容。复杂或冗长的流程更适合使用全模态或页面导航,Sheet 更适合相对集中的临时任务。

Button('打开 Sheet')
  .onClick(() => {
    this.showSheet = true;
  })
  .bindSheet($$this.showSheet, this.sheetBuilder(), {
    height: 380,
    backgroundColor: Color.Transparent,
    systemMaterial: this.ultraThickMaterial
  })

这里将 backgroundColor 设为透明,可以避免普通背景色直接盖住材质层。Sheet 面积较大,使用 ULTRA_THICK 后,面板内容与底层页面之间的层级会更稳定。官方示例也通过 SheetOptions.systemMaterial 为半模态页面设置了沉浸材质。

四类入口分开以后,材质的配置位置就比较清楚了:按钮负责触发,浮层 options 负责材质。

二、用一张页面统一四种浮层入口

四类浮层分别使用不同接口,如果每一种都准备一个独立工程,代码很快就会变得零散。

我更习惯把四个入口放进同一张实验页面。页面顶部先读取 MaterialState,中间依次放置 Popup、Menu、Tips 和 Sheet 四张入口卡片。所有入口共享三种材质对象,页面背景、文字和按钮样式也保持一致。

这样处理以后,大家可以在同一环境中连续操作四种浮层,也能直接比较小面积提示、菜单和大面积面板的差异。

先准备三种材质对象

Popup 与 Tips 共用 THIN,Menu 使用 THICK,Sheet 使用 ULTRA_THICK

private readonly thinMaterial: uiMaterial.Material =
  new uiMaterial.ImmersiveMaterial({
    style: uiMaterial.ImmersiveStyle.THIN
  });

private readonly thickMaterial: uiMaterial.Material =
  new uiMaterial.ImmersiveMaterial({
    style: uiMaterial.ImmersiveStyle.THICK
  });

private readonly ultraThickMaterial: uiMaterial.Material =
  new uiMaterial.ImmersiveMaterial({
    style: uiMaterial.ImmersiveStyle.ULTRA_THICK
  });

这些对象没有额外加入 materialColorcolorInvertinteractivelightEffect。浮层实验先关注材质入口、背景层次和内容可读性,其他参数暂时保持默认。

浮层面积和出现位置已经带来了足够多的变化。此时继续叠加赋色与光感,页面会很难确认差异来自组件类型还是材质参数。

Popup 需要同步显示状态

Popup 的显示状态由布尔值控制。气泡关闭以后,onStateChange 还要同步更新页面状态。

Button('打开 Popup')
  .onClick(() => {
    this.showPopup = !this.showPopup;
  })
  .bindPopup(this.showPopup, {
    message: '这是一条带有 THIN 材质的 Popup',
    placement: Placement.Bottom,
    systemMaterial: this.thinMaterial,
    onStateChange: (event) => {
      this.showPopup = event.isVisible;
    }
  })

我会保留 onStateChange。用户点击气泡外部、系统自动关闭或宿主组件状态变化以后,页面中的布尔值仍然能够与实际显示状态保持一致。

Popup 的内容比较短时,系统提供的 PopupOptions 已经够用。需要复杂布局、输入框或多个区域时,可以改用 CustomPopupOptions.builder,材质仍然写在 CustomPopupOptions.systemMaterial 中。

Menu 需要把操作结果带回页面

Menu 的价值来自选项。实验页面中的菜单会放置三个简单操作,并把最后一次选择显示在页面底部。

@Builder
private menuBuilder() {
  Menu() {
    MenuItem({ content: '复制链接' })
      .onClick(() => {
        this.lastActionText = '已选择:复制链接';
      });

    MenuItem({ content: '加入收藏' })
      .onClick(() => {
        this.lastActionText = '已选择:加入收藏';
      });

    MenuItem({ content: '稍后处理' })
      .onClick(() => {
        this.lastActionText = '已选择:稍后处理';
      });
  }
}

随后通过 bindMenu 设置材质:

Button('打开 Menu')
  .bindMenu(this.menuBuilder, {
    systemMaterial: this.thickMaterial
  })

菜单打开以后,可以重点看选项文字与背景之间的对比度,以及菜单边缘是否与页面形成清楚层级。

Tips 需要在支持悬浮的环境中操作

实验页依然保留 Tips 入口,但按钮说明会直接写明“鼠标悬浮”。

Button('鼠标悬浮查看 Tips')
  .bindTips('这是一条 THIN 材质的悬浮提示', {
    appearingTime: 300,
    disappearingTime: 100,
    enableArrow: true,
    systemMaterial: this.thinMaterial
  })

在支持鼠标或手写笔悬浮的环境中,光标停留到按钮上方后,Tips 会自动显示。手机模拟器无法产生有效悬浮事件时,这个入口不会弹出,页面本身仍然可以正常运行。

Sheet 需要留出完整内容空间

Sheet 的 builder 可以承载标题、说明、选项和按钮。当前示例使用固定高度,方便在模拟器中保持稳定布局。

@Builder
private sheetBuilder() {
  Column({ space: 16 }) {
    Text('Sheet 设置面板')
      .fontSize(22)
      .fontWeight(FontWeight.Bold);

    Text('ULTRA_THICK 材质用于降低底层页面干扰。')
      .fontSize(14);

    Button('完成')
      .onClick(() => {
        this.showSheet = false;
      });
  }
  .width('100%')
  .height('100%')
  .padding(24);
}

绑定时保持透明背景,并把材质交给 SheetOptions

.bindSheet($$this.showSheet, this.sheetBuilder(), {
  height: 380,
  dragBar: true,
  backgroundColor: Color.Transparent,
  systemMaterial: this.ultraThickMaterial
})

Sheet 内部内容需要自己处理间距、文字和操作入口。材质负责面板背景与层级,业务内容仍然由 builder 决定。

不要让普通背景样式盖住材质

Popup、Menu、Tips 和 Sheet 都允许继续设置背景色、模糊、阴影或边框。使用沉浸材质时,建议先减少这些额外属性。

当前实验遵循下面几条原则:

浮层 options 中设置 systemMaterial
↓
不额外设置不透明背景色
↓
不重复叠加普通背景模糊
↓
先使用系统材质阴影
↓
确认基础效果后再增加品牌色和自定义样式

通过 options 设置材质时,不需要考虑链式调用顺序;普通组件通过通用属性设置材质时,systemMaterial 更适合放在其他视觉属性之后。设置沉浸材质后,同时配置背景色、背景模糊、阴影和边框,可能会造成样式覆盖或结果难以判断。

三、运行时怎样判断材质是否配得合适

页面完成以后,四类浮层可以按照从轻到重的顺序操作。

我通常先打开 Popup,确认小面积气泡能否保持通透;接着打开 Menu,检查文字与操作项;最后打开 Sheet,观察大面积面板对底层页面的压制程度。Tips 则放到能够触发悬浮事件的环境中单独检查。

Popup 重点看宿主关系

Popup 出现在按钮附近,它需要让大家一眼看出提示属于哪个组件。

THIN 能够保留部分页面背景,气泡与宿主按钮之间的联系会比较自然。背景过于复杂、文字对比度不足时,可以继续尝试 REGULAR

Popup 内容变长以后,气泡尺寸也会增大。此时需要留意换行、箭头位置和屏幕边缘避让。Popup 适合短内容,承载大量操作时,Menu 或 Sheet 会更清楚。

Menu 重点看选项可读性

Menu 打开以后,视线应该自然落在菜单项上。

THICK 会减少背景干扰,适合多数操作菜单。页面背景比较简单、菜单项又很少时,REGULAR 也可能足够。菜单覆盖图片或视频时,较厚的材质通常更稳定。

我会特别检查三项内容:

  • 菜单项文字是否清楚;
  • 选中、按压和悬浮状态是否容易辨认;
  • 菜单边缘与底层页面之间是否有稳定层级。

菜单内容本身也要保持克制。与当前场景无关的选项会增加理解成本,常用操作更适合放在前面。

Tips 重点看出现时机

Tips 面积很小,THIN 通常能够提供足够的背景区分。

真正需要关注的是出现和消失时机。提示出现太快,光标经过多个控件时会频繁闪烁;出现太慢,大家又可能在看到说明前离开组件。

appearingTimedisappearingTime 可以根据桌面端操作节奏调整。Tips 只能补充短信息,内容需要点击、选择或长期保留时,更适合使用 Popup。

Sheet 重点看内容与背景的关系

Sheet 会占据较大面积,材质厚度需要帮助内容形成独立空间。

ULTRA_THICK 可以先作为起点。面板内容较少、底层背景又比较简单时,可以退回 THICK。面板中包含表单、列表或多项设置时,较厚材质更容易保证文字和控件稳定。

Sheet 还要关注面板高度、拖拽条和关闭入口。半模态页面保留了底层环境,但复杂或冗长的流程仍然更适合进入独立页面。

已有项目可以先按信息量选择

四类浮层放回项目时,可以先看内容量和交互方式。

场景更合适的入口材质起点
点击后显示一句说明PopupTHIN
鼠标经过图标显示名称TipsTHIN
展示三到六个操作项MenuTHICK
填写表单或选择多个设置SheetULTRA_THICK
内容继续增长、流程变长独立页面根据页面结构处理

我更倾向于让浮层保持单一任务。Popup 负责解释,Menu 负责选择,Tips 负责补充,Sheet 负责完成一段相对集中的操作。入口职责越清楚,材质厚度也越容易确定。

总结

Popup、Menu、Tips 和 Sheet 都能够使用沉浸材质,但它们的配置入口和操作方式各不相同。

Popup 的材质写在 PopupOptionsCustomPopupOptions 中,适合简短说明。Menu 通过 MenuOptions.systemMaterial 配置,THICK 可以帮助操作项从复杂背景中分离出来。

Tips 使用 TipsOptions.systemMaterial,它依赖鼠标或手写笔悬浮事件,更适合桌面端和支持悬浮输入的设备。Sheet 通过 SheetOptions.systemMaterial 设置整个半模态面板,透明背景配合较厚材质,可以减少普通背景色对材质的覆盖。

我在实际接入时,会先确认浮层承担什么任务,再选择材质。小面积提示先试 THIN,菜单先试 THICK,大面积 Sheet 先试 ULTRA_THICK。完成基础显示以后,再考虑品牌赋色、自动反色和自定义阴影。

当前页面在 HarmonyOS 7 模拟器中运行,可以核对 Popup、Menu 和 Sheet 的接口与基础表现。Tips 需要能够触发悬浮事件的环境。正式接入项目前,大家仍应优先在具备权限的真机上复核浮层材质、弹出动效、触控反馈与性能表现。

完整示例代码

Main.ets

/**
 * HarmonyOS 7 沉浸光感深度实战 05
 *
 * 验证环境:
 * HarmonyOS SDK API 26
 * HarmonyOS 7 模拟器
 */

import { uiMaterial } from '@kit.ArkUI';

@Entry
@Component
struct Main {
  @State private materialStateText: string =
    '当前应用尚未读取状态';

  @State private stateColor: ResourceColor =
    '#68708A';

  @State private showPopup: boolean = false;

  @State private showSheet: boolean = false;

  @State private lastActionText: string =
    '尚未执行浮层操作';

  /**
   * Popup 与 Tips 使用较薄材质。
   */
  private readonly thinMaterial: uiMaterial.Material =
    new uiMaterial.ImmersiveMaterial({
      style: uiMaterial.ImmersiveStyle.THIN
    });

  /**
   * Menu 使用较厚材质,减少复杂背景干扰。
   */
  private readonly thickMaterial: uiMaterial.Material =
    new uiMaterial.ImmersiveMaterial({
      style: uiMaterial.ImmersiveStyle.THICK
    });

  /**
   * Sheet 面积较大,使用超厚材质建立前后层级。
   */
  private readonly ultraThickMaterial: uiMaterial.Material =
    new uiMaterial.ImmersiveMaterial({
      style: uiMaterial.ImmersiveStyle.ULTRA_THICK
    });

  aboutToAppear(): void {
    this.loadMaterialState();
  }

  /**
   * 读取当前应用的材质状态。
   * DISABLE 会关闭页面中的全部沉浸式系统材质。
   */
  private loadMaterialState(): void {
    const info: uiMaterial.MaterialInfo =
      uiMaterial.getMaterialInfo();

    this.materialStateText =
      this.getMaterialStateName(info.state);

    this.stateColor =
      this.getMaterialStateColor(info.state);
  }

  private getMaterialStateName(
    state: uiMaterial.MaterialState
  ): string {
    switch (state) {
      case uiMaterial.MaterialState.DEFAULT:
        return 'DEFAULT';

      case uiMaterial.MaterialState.ENABLE:
        return 'ENABLE';

      case uiMaterial.MaterialState.DISABLE:
        return 'DISABLE';

      default:
        return `未知状态 ${state}`;
    }
  }

  private getMaterialStateColor(
    state: uiMaterial.MaterialState
  ): ResourceColor {
    switch (state) {
      case uiMaterial.MaterialState.DEFAULT:
        return '#5065E8';

      case uiMaterial.MaterialState.ENABLE:
        return '#1A8F5D';

      case uiMaterial.MaterialState.DISABLE:
        return '#C85A3A';

      default:
        return '#68708A';
    }
  }

  @Builder
  private sectionTitle(
    title: string,
    description: string
  ) {
    Column({ space: 4 }) {
      Text(title)
        .fontSize(22)
        .fontWeight(FontWeight.Bold)
        .fontColor('#11182C')
        .width('100%')

      Text(description)
        .fontSize(14)
        .fontColor('#68708A')
        .lineHeight(21)
        .width('100%')
    }
    .alignItems(HorizontalAlign.Start)
    .width('100%')
  }

  @Builder
  private sceneHeader(
    title: string,
    materialLabel: string,
    description: string
  ) {
    Column({ space: 6 }) {
      Row({ space: 10 }) {
        Text(title)
          .fontSize(18)
          .fontWeight(FontWeight.Bold)
          .fontColor('#17203A')
          .layoutWeight(1)

        Text(materialLabel)
          .fontSize(11)
          .fontWeight(FontWeight.Medium)
          .fontColor('#5065E8')
          .padding({
            left: 9,
            right: 9,
            top: 4,
            bottom: 4
          })
          .backgroundColor('#EEF1FF')
          .borderRadius(12)
      }
      .width('100%')

      Text(description)
        .fontSize(13)
        .fontColor('#68708A')
        .lineHeight(20)
        .width('100%')
    }
    .width('100%')
  }

  @Builder
  private materialStateCard() {
    Row({ space: 12 }) {
      Text('MaterialState')
        .width('42%')
        .fontSize(14)
        .fontColor('#68708A')

      Text(this.materialStateText)
        .layoutWeight(1)
        .fontSize(14)
        .fontWeight(FontWeight.Medium)
        .fontColor(this.stateColor)
        .textAlign(TextAlign.End)
    }
    .width('100%')
    .padding(16)
    .backgroundColor('#F2FFFFFF')
    .borderRadius(20)
  }

  /**
   * 菜单内容。
   */
  @Builder
  private menuBuilder() {
    Menu() {
      MenuItem({
        content: '复制链接'
      })
        .onClick(() => {
          this.lastActionText = '已选择:复制链接';
        })

      MenuItem({
        content: '加入收藏'
      })
        .onClick(() => {
          this.lastActionText = '已选择:加入收藏';
        })

      MenuItem({
        content: '稍后处理'
      })
        .onClick(() => {
          this.lastActionText = '已选择:稍后处理';
        })
    }
  }

  /**
   * Sheet 内容。
   */
  @Builder
  private sheetBuilder() {
    Column({ space: 18 }) {
      Text('Sheet 设置面板')
        .fontSize(22)
        .fontWeight(FontWeight.Bold)
        .fontColor('#17203A')
        .width('100%')

      Text(
        '当前面板使用 ULTRA_THICK 材质,'
          + '用于降低底层页面对表单内容的干扰。'
      )
        .fontSize(14)
        .fontColor('#68708A')
        .lineHeight(22)
        .width('100%')

      Column({ space: 12 }) {
        Row({ space: 12 }) {
          Text('接收更新提醒')
            .fontSize(15)
            .fontColor('#17203A')
            .layoutWeight(1)

          Toggle({
            type: ToggleType.Switch,
            isOn: true
          })
        }
        .width('100%')

        Divider()
          .color('#E8EBF2')

        Row({ space: 12 }) {
          Text('保留当前选择')
            .fontSize(15)
            .fontColor('#17203A')
            .layoutWeight(1)

          Toggle({
            type: ToggleType.Switch,
            isOn: false
          })
        }
        .width('100%')
      }
      .width('100%')
      .padding(16)
      .backgroundColor('#66FFFFFF')
      .borderRadius(18)

      Button('完成')
        .width('100%')
        .height(44)
        .fontSize(15)
        .onClick(() => {
          this.lastActionText = '已完成 Sheet 操作';
          this.showSheet = false;
        })
    }
    .width('100%')
    .height('100%')
    .padding({
      left: 24,
      right: 24,
      top: 18,
      bottom: 24
    })
    .alignItems(HorizontalAlign.Start)
  }

  build() {
    Stack() {
      /**
       * 简单分区背景用于观察浮层的通透与层级。
       */
      Row() {
        Column()
          .width('42%')
          .height('100%')
          .backgroundColor('#DCE5FF')

        Column()
          .layoutWeight(1)
          .height('100%')
          .backgroundColor('#F0E4FF')
      }
      .width('100%')
      .height('100%')

      Scroll() {
        Column({ space: 18 }) {
          Column({ space: 6 }) {
            Text('HarmonyOS 7 沉浸光感')
              .fontSize(28)
              .fontWeight(FontWeight.Bold)
              .fontColor('#11182C')
              .width('100%')

            Text('Popup、Menu、Tips 与 Sheet')
              .fontSize(16)
              .fontColor('#68708A')
              .width('100%')
          }
          .alignItems(HorizontalAlign.Start)
          .width('100%')

          this.sectionTitle(
            '当前应用状态',
            'DISABLE 状态会关闭页面中的全部沉浸材质。'
          )

          this.materialStateCard()

          this.sectionTitle(
            '四类浮层入口',
            '点击或悬浮入口,观察不同浮层的材质效果。'
          )

          /**
           * Popup 实验卡片。
           */
          Column({ space: 14 }) {
            this.sceneHeader(
              'Popup',
              'THIN',
              '适合围绕宿主组件展示简短说明。'
            )

            Button(
              this.showPopup
                ? '关闭 Popup'
                : '打开 Popup'
            )
              .width('100%')
              .height(42)
              .onClick(() => {
                this.showPopup = !this.showPopup;
              })
              .bindPopup(this.showPopup, {
                message: '这是一条带有 THIN 材质的 Popup',
                placement: Placement.Bottom,
                systemMaterial: this.thinMaterial,
                onStateChange: (event) => {
                  this.showPopup = event.isVisible;
                  this.lastActionText =
                    event.isVisible
                      ? 'Popup 已打开'
                      : 'Popup 已关闭';
                }
              })
          }
          .width('100%')
          .padding(16)
          .backgroundColor('#EFFFFFFF')
          .borderRadius(22)

          /**
           * Menu 实验卡片。
           */
          Column({ space: 14 }) {
            this.sceneHeader(
              'Menu',
              'THICK',
              '适合展示一组需要立即选择的操作。'
            )

            Button('打开 Menu')
              .width('100%')
              .height(42)
              .bindMenu(this.menuBuilder, {
                systemMaterial: this.thickMaterial
              })
          }
          .width('100%')
          .padding(16)
          .backgroundColor('#EFFFFFFF')
          .borderRadius(22)

          /**
           * Tips 实验卡片。
           */
          Column({ space: 14 }) {
            this.sceneHeader(
              'Tips',
              'THIN',
              '依赖鼠标或手写笔悬浮事件,'
                + '手机触控环境可能无法触发。'
            )

            Button('鼠标悬浮查看 Tips')
              .width('100%')
              .height(42)
              .bindTips(
                '这是一条带有 THIN 材质的悬浮提示',
                {
                  appearingTime: 300,
                  disappearingTime: 100,
                  enableArrow: true,
                  systemMaterial: this.thinMaterial
                }
              )
          }
          .width('100%')
          .padding(16)
          .backgroundColor('#EFFFFFFF')
          .borderRadius(22)

          /**
           * Sheet 实验卡片。
           */
          Column({ space: 14 }) {
            this.sceneHeader(
              'Sheet',
              'ULTRA_THICK',
              '适合承载表单、设置和相对完整的临时任务。'
            )

            Button('打开 Sheet')
              .width('100%')
              .height(42)
              .onClick(() => {
                this.showSheet = true;
                this.lastActionText = 'Sheet 已打开';
              })
              .bindSheet(
                $$this.showSheet,
                this.sheetBuilder(),
                {
                  height: 380,
                  dragBar: true,
                  showClose: false,
                  backgroundColor: Color.Transparent,
                  systemMaterial: this.ultraThickMaterial,
                  onDisappear: () => {
                    this.lastActionText = 'Sheet 已关闭';
                  }
                }
              )
          }
          .width('100%')
          .padding(16)
          .backgroundColor('#EFFFFFFF')
          .borderRadius(22)

          Column({ space: 6 }) {
            Text('最近一次操作')
              .fontSize(14)
              .fontWeight(FontWeight.Medium)
              .fontColor('#17203A')
              .width('100%')

            Text(this.lastActionText)
              .fontSize(13)
              .fontColor('#68708A')
              .lineHeight(20)
              .width('100%')
          }
          .width('100%')
          .padding(16)
          .backgroundColor('#EFFFFFFF')
          .borderRadius(20)

          Text(
            '模拟器用于核对接口和基础表现,'
              + '浮层材质与动效仍需在真机上复核。'
          )
            .fontSize(13)
            .fontColor('#747C92')
            .lineHeight(20)
            .padding({
              top: 4,
              bottom: 24
            })
            .width('100%')
        }
        .width('100%')
        .padding({
          left: 20,
          right: 20,
          top: 24,
          bottom: 24
        })
      }
      .width('100%')
      .height('100%')
    }
    .width('100%')
    .height('100%')
  }
}
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐