HarmonyOS6 ArkTS Popup 气泡组件指南

文章目录

    • [一、核心 API 速览](#一、核心 API 速览)
      • [1.1 `bindPopup` 方法](#1.1 bindPopup 方法)
      • [1.2 `PopupOptions`(基础文本气泡)](#1.2 PopupOptions(基础文本气泡))
      • [1.3 `CustomPopupOptions`(自定义内容气泡)](#1.3 CustomPopupOptions(自定义内容气泡))
    • 二、完整代码示例与详解
      • 示例详解
        • [1. 基础文本气泡](#1. 基础文本气泡)
        • [2. 自定义样式气泡](#2. 自定义样式气泡)
        • [3. 自定义内容气泡](#3. 自定义内容气泡)
        • [4. 自定义动效气泡](#4. 自定义动效气泡)
        • [5. 退出事件拦截气泡](#5. 退出事件拦截气泡)
        • [6. 渐变描边气泡(API 20+)](#6. 渐变描边气泡(API 20+))
    • 总结

Popup 是 ArkUI 提供的通用属性,用于为组件绑定弹出式气泡,支持文本提示、自定义内容、样式定制、动效配置等能力,从 API version 7 开始支持,是实现用户引导、操作提示、详情展示等场景的核心组件。

核心特性

  • 双模式支持 :基础文本气泡(PopupOptions)与自定义内容气泡(CustomPopupOptions)。
  • 丰富样式定制:支持箭头、圆角、阴影、背景色、描边渐变等全方位样式配置。
  • 交互与动效:支持显隐动效、退出事件拦截、状态监听等交互能力。
  • 版本兼容:高版本 API(如 API 12+ 动效、API 20+ 渐变描边)均有兼容说明。

一、核心 API 速览

1.1 bindPopup 方法

为组件绑定 Popup 气泡,是使用 Popup 的核心入口。

typescript 复制代码
bindPopup(show: boolean, popup: PopupOptions | CustomPopupOptions): T
参数名 类型 必填 说明
show boolean 气泡显隐状态,true 显示,false 隐藏。注意 :不能在页面构建中直接设为 true,需等待页面构建完成。
popup PopupOptions | CustomPopupOptions 气泡配置参数,区分基础文本模式和自定义内容模式。

1.2 PopupOptions(基础文本气泡)

用于配置仅展示文本和按钮的基础气泡,核心参数如下:

参数名 类型 说明 最低 API 版本
message string 气泡文本内容(必填)。 7
placement Placement 气泡显示位置,默认 Placement.Bottom 10
primaryButton {value: string, action: () => void} 主按钮配置。 7
secondaryButton {value: string, action: () => void} 辅助按钮配置。 7
messageOptions PopupMessageOptions 文本样式配置(颜色、字体等)。 10
enableArrow boolean 是否显示箭头,默认 true 10
arrowWidth / arrowHeight Dimension 箭头宽度/高度。 11
popupColor ResourceColor 气泡背景色。 11
radius Dimension 气泡圆角半径。 11
shadow ShadowOptions | ShadowStyle 气泡阴影。 11
transition TransitionEffect 显隐动效配置。 12
onWillDismiss boolean | Callback<DismissPopupAction> 退出事件拦截。 12
outlineLinearGradient / borderLinearGradient PopupBorderLinearGradient 内外描边渐变。 20

1.3 CustomPopupOptions(自定义内容气泡)

用于通过 @Builder 自定义气泡内容,核心参数如下:

参数名 类型 说明 最低 API 版本
builder CustomBuilder 自定义内容构造器(必填),用 @Builder 装饰。 8
placement Placement 气泡显示位置,默认 Placement.Bottom 8
popupColor ResourceColor 气泡背景色。 8
enableArrow boolean 是否显示箭头,默认 true 8
autoCancel boolean 点击外部是否自动关闭,默认 true 8
mask boolean | {color: ResourceColor} 遮罩层配置。 10

二、完整代码示例与详解

以下代码基于官方文档扩展,覆盖 6 大核心场景,可直接复制运行。

typescript 复制代码
@Entry
@Component
struct PopupFullExample {
  // ************************* 气泡显隐状态变量 *************************
  @State basePopupShow: boolean = false; // 基础文本气泡
  @State stylePopupShow: boolean = false; // 自定义样式气泡
  @State customPopupShow: boolean = false; // 自定义内容气泡
  @State transitionPopupShow: boolean = false; // 自定义动效气泡
  @State interceptPopupShow: boolean = false; // 退出事件拦截气泡
  @State gradientPopupShow: boolean = false; // 渐变描边气泡(API20+)

  // ************************* 自定义气泡内容构造器 *************************
  @Builder
  customPopupBuilder() {
    Column({ space: 12 }) {
      Row({ space: 8 }) {
        // 示例图标,使用系统公共图标,也可替换为 $r('app.media.xxx')
        Image($r('sys.media.ohos_ic_public_albums'))
          .width(24)
          .height(24)
          .objectFit(ImageFit.Contain)
        Text('自定义气泡标题')
          .fontSize(16)
          .fontWeight(FontWeight.Medium)
          .fontColor('#181818')
      }
      .width('100%')
      .justifyContent(FlexAlign.Start)

      Text('这是通过CustomPopupOptions实现的自定义内容气泡,支持任意布局组件,可自由定制宽高、样式、交互')
        .fontSize(14)
        .fontColor('#666666')
        .maxLines(2)
        .width('100%')

      Row({ space: 10 }) {
        Button('取消')
          .width(80)
          .height(32)
          .fontSize(14)
          .backgroundColor('#F5F5F5')
          .fontColor('#333333')
          .onClick(() => {
            this.customPopupShow = false;
          })

        Button('确认')
          .width(80)
          .height(32)
          .fontSize(14)
          .backgroundColor('#007DFF')
          .fontColor(Color.White)
          .onClick(() => {
            this.customPopupShow = false;
            console.info('自定义气泡确认按钮点击');
          })
      }
      .width('100%')
      .justifyContent(FlexAlign.End)
    }
    .width(280)
    .padding(16)
  }

  build() {
    Scroll() {
      Column({ space: 20 }) {
        // ************************* 示例1:基础文本气泡 *************************
        Button('基础文本气泡')
          .width('90%')
          .height(48)
          .fontSize(16)
          .onClick(() => {
            this.basePopupShow = !this.basePopupShow;
          })
          .bindPopup(this.basePopupShow, {
            message: '这是基础Popup气泡,支持主副按钮、状态监听、位置定制',
            placement: Placement.Top,
            targetSpace: 12,
            enableArrow: true,
            mask: false,
            autoCancel: true,
            keyboardAvoidMode: KeyboardAvoidMode.DEFAULT,
            primaryButton: {
              value: '确认',
              action: () => {
                this.basePopupShow = false;
              }
            },
            secondaryButton: {
              value: '取消',
              action: () => {
                this.basePopupShow = false;
              }
            },
            onStateChange: (event) => {
              if (!event.isVisible) {
                this.basePopupShow = false;
              }
            }
          })

        // ************************* 示例2:自定义样式气泡 *************************
        Button('自定义样式气泡')
          .width('90%')
          .height(48)
          .fontSize(16)
          .onClick(() => {
            this.stylePopupShow = !this.stylePopupShow;
          })
          .bindPopup(this.stylePopupShow, {
            message: '自定义样式气泡,可定制箭头、圆角、阴影、背景、文本样式',
            placement: Placement.Bottom,
            messageOptions: {
              textColor: Color.White,
              font: {
                size: 14,
                weight: FontWeight.Medium
              }
            },
            enableArrow: true,
            arrowWidth: 20,
            arrowHeight: 10,
            arrowPointPosition: ArrowPointPosition.CENTER,
            width: 260,
            radius: 16,
            popupColor: '#007DFF',
            backgroundBlurStyle: BlurStyle.NONE,
            shadow: ShadowStyle.OUTER_DEFAULT_LG,
            onStateChange: (event) => {
              if (!event.isVisible) {
                this.stylePopupShow = false;
              }
            }
          })

        // ************************* 示例3:自定义内容气泡 *************************
        Button('自定义内容气泡')
          .width('90%')
          .height(48)
          .fontSize(16)
          .onClick(() => {
            this.customPopupShow = !this.customPopupShow;
          })
          .bindPopup(this.customPopupShow, {
            builder: this.customPopupBuilder,
            placement: Placement.Right,
            enableArrow: true,
            mask: { color: '#33000000' },
            popupColor: Color.White,
            autoCancel: false,
            targetSpace: 10,
            onStateChange: (event) => {
              if (!event.isVisible) {
                this.customPopupShow = false;
              }
            }
          })

        // ************************* 示例4:自定义动效气泡 *************************
        Button('自定义动效气泡')
          .width('90%')
          .height(48)
          .fontSize(16)
          .onClick(() => {
            this.transitionPopupShow = !this.transitionPopupShow;
          })
          .bindPopup(this.transitionPopupShow, {
            message: '自定义显隐动效气泡,支持透明度、平移、缩放等组合动效',
            placement: Placement.Top,
            width: 240,
            transition: TransitionEffect.asymmetric(
              TransitionEffect.OPACITY
                .animation({ duration: 600, curve: Curve.EaseInOut })
                .combine(TransitionEffect.translate({ x: 0, y: -20 })),
              TransitionEffect.scale({ x: 0.5, y: 0.5 })
                .animation({ duration: 400, curve: Curve.EaseIn })
                .combine(TransitionEffect.OPACITY)
            ),
            onStateChange: (event) => {
              if (!event.isVisible) {
                this.transitionPopupShow = false;
              }
            }
          })

        // ************************* 示例5:退出事件拦截气泡 *************************
        Button('退出事件拦截气泡')
          .width('90%')
          .height(48)
          .fontSize(16)
          .onClick(() => {
            this.interceptPopupShow = true;
          })
          .bindPopup(this.interceptPopupShow, {
            message: '拦截退出事件气泡,仅允许back键关闭,点击遮罩/外部无法关闭',
            placement: Placement.Bottom,
            width: 260,
            enableArrow: true,
            mask: true,
            onWillDismiss: (dismissPopupAction) => {
              console.info(`气泡关闭原因Code:${dismissPopupAction.reason}`);
              // 0 对应 DismissReason.PRESS_BACK (Back键/侧滑)
              // 1 对应 TOUCH_OUTSIDE (点击遮罩)
              if (dismissPopupAction.reason === 0) {
                dismissPopupAction.dismiss();
                this.interceptPopupShow = false;
              }
            },
            onStateChange: (event) => {
              if (!event.isVisible) {
                this.interceptPopupShow = false;
              }
            }
          })

        // ************************* 示例6:渐变描边气泡 *************************
        Button('渐变描边气泡(API20+)')
          .width('90%')
          .height(48)
          .fontSize(16)
          .onClick(() => {
            this.gradientPopupShow = !this.gradientPopupShow;
          })
          .bindPopup(this.gradientPopupShow, {
            message: 'API20+ 新增特性,气泡内外描边线性渐变效果',
            placement: Placement.Top,
            width: 260,
            radius: 12,
            outlineWidth: 2,
            outlineLinearGradient: {
              direction: GradientDirection.Right,
              colors: [[Color.Yellow, 0.0], [Color.Green, 1.0]]
            },
            borderWidth: 2,
            borderLinearGradient: {
              direction: GradientDirection.Left,
              colors: [[Color.Red, 0.0], [Color.Blue, 1.0]]
            },
            onStateChange: (event) => {
              if (!event.isVisible) {
                this.gradientPopupShow = false;
              }
            }
          })
      }
      .width('100%')
      .padding({ top: 50, bottom: 50 })
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F8F8F8')
  }
}

运行结果如图:

示例详解

1. 基础文本气泡

展示最基础的文本提示气泡,包含主副按钮、位置配置、状态监听。

  • 核心配置message(文本内容)、primaryButton/secondaryButton(按钮)、onStateChange(显隐监听)。
  • 关键逻辑 :通过 onStateChange 同步状态变量,避免变量与气泡显隐不一致。
2. 自定义样式气泡

全方位定制气泡外观,包括文本样式、箭头、圆角、背景色、阴影。

  • 核心配置messageOptions(文本样式)、arrowWidth/arrowHeight(箭头尺寸)、popupColor(背景色)、shadow(阴影)。
  • 适配说明backgroundBlurStyle: BlurStyle.NONE 用于关闭默认模糊背景,突出自定义背景色。
3. 自定义内容气泡

通过 @Builder 构造器完全自定义气泡内容,支持图片、文本、按钮等任意布局。

  • 核心配置builder(自定义构造器)、autoCancel: false(禁止点击外部关闭)。
  • 避坑说明builder 下的第一层容器组件不支持使用 position 属性,否则会导致气泡不显示。
4. 自定义动效气泡

通过 TransitionEffect 定制气泡的显示和退出动效,支持不对称动效。

  • 核心配置transition(动效配置),使用 asymmetric 分别定义显示和退出动效。
  • 动效组合 :通过 combine 组合透明度、平移、缩放等动效,实现丰富的视觉效果。
5. 退出事件拦截气泡

通过 onWillDismiss 拦截气泡退出事件,仅允许特定方式(如 Back 键)关闭气泡。

  • 核心配置onWillDismiss(拦截回调),通过 reason 判断关闭原因(0 为 Back 键,1 为点击遮罩)。
  • 关键逻辑 :仅在 reason === 0 时调用 dismiss(),否则拦截退出。
6. 渐变描边气泡(API 20+)

利用 API 20+ 新特性,为气泡添加内外描边的线性渐变效果。

  • 核心配置outlineWidth/borderWidth(描边宽度)、outlineLinearGradient/borderLinearGradient(渐变配置)。
  • 版本兼容:需在 HarmonyOS 5.0.0.200+ 版本设备上运行,低版本可注释对应代码。

总结

Popup 气泡组件是 HarmonyOS ArkUI 中实现用户交互提示的核心工具,通过 PopupOptionsCustomPopupOptions 可覆盖从简单文本到复杂自定义内容的全场景需求。本文结合官方文档与完整代码,详细讲解了其核心 API、样式定制、动效配置、事件拦截等能力,并提供了实用的避坑指南,帮助开发者快速上手并高效使用 Popup 组件。

如果这篇文章对你有帮助,欢迎点赞、收藏、关注,你的支持是持续创作的动力!

相关推荐
全栈若城6 天前
HarmonyOS6 半年磨一剑 - RcInput 组件核心架构与类型系统设计
架构·harmonyos6·三方库开发实战·rchoui·三方库开发
全栈若城1 个月前
HarmonyOS6 半年磨一剑 - RcInput 组件清空、密码切换与图标交互机制
架构·交互·harmonyos6·三方库开发实战·rchoui·三方库开发
全栈若城1 个月前
HarmonyOS 6 实战:Component3D 与 SURFACE 渲染模式深度解析
3d·架构·harmonyos6
全栈若城1 个月前
HarmonyOS 6 实战:使用 ArkGraphics3D 加载 GLB 模型与 Scene 初始化全流程
3d·华为·架构·harmonyos·harmonyos6
是稻香啊1 个月前
HarmonyOS6 触摸目标 touch-target 属性使用指南
harmonyos6
是稻香啊1 个月前
HarmonyOS6 foregroundBlurStyle 通用属性使用指南
harmonyos6
是稻香啊1 个月前
HarmonyOS6 clickEffect 通用属性使用指南
harmonyos6
是稻香啊1 个月前
HarmonyOS6 filter 通用属性使用指南
harmonyos6
是稻香啊2 个月前
HarmonyOS6 ArkUI 无障碍悬停事件(onAccessibilityHover)全面解析与实战演示
华为·harmonyos·harmonyos6