前言

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

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

我刚开始整理这几类组件时,也容易把注意力全部放在材质样式上。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.systemMaterial THIN 简短说明、状态提示
Menu 点击或长按打开 MenuOptions.systemMaterial THICK 一组操作选项
Tips 鼠标或手写笔悬浮 TipsOptions.systemMaterial THIN 控件名称、补充说明
Sheet 状态绑定后展开 SheetOptions.systemMaterial ULTRA_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 还要关注面板高度、拖拽条和关闭入口。半模态页面保留了底层环境,但复杂或冗长的流程仍然更适合进入独立页面。

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

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

场景 更合适的入口 材质起点
点击后显示一句说明 Popup THIN
鼠标经过图标显示名称 Tips THIN
展示三到六个操作项 Menu THICK
填写表单或选择多个设置 Sheet ULTRA_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、测试、元服务和应用上架分发等。

更多推荐