ArkUI Popup:小气泡只讲一句有用的话

举报
蓝瘦的蜕变 发表于 2026/09/11 18:32:39 2026/09/11
【摘要】 今天我们用 Popup 做三种贴着控件出现的小提示:基础文字气泡、顶部气泡、自定义气泡。 Popup 的重点是“贴着某个控件解释一句话”。它不像 AlertDialog 那样打断用户,也不像 ActionSheet 那样让用户选动作。我们只用最小的布尔值控制显示,不展开状态管理。 基础文字气泡 最简单的写法是 bind

ArkUI Popup:小气泡只讲一句有用的话

今天我们用 Popup 做三种贴着控件出现的小提示:基础文字气泡、顶部气泡、自定义气泡。

Popup 的重点是“贴着某个控件解释一句话”。它不像 AlertDialog 那样打断用户,也不像 ActionSheet 那样让用户选动作。我们只用最小的布尔值控制显示,不展开状态管理。

基础文字气泡

最简单的写法是 bindPopup(show, options)

Button('显示基础气泡')
  .onClick(() => {
    this.showBasicPopup = !this.showBasicPopup
  })
  .bindPopup(this.showBasicPopup, {
    message: '昵称会展示给其他用户,建议用容易识别的名字。',
    placement: Placement.Bottom,
    enableArrow: true
  })

message 写提示内容,placement 决定出现位置,enableArrow 让气泡有一个指向控件的小箭头。内容仍然要短,别把帮助文档塞进去。

位置控制

第二组把气泡放到按钮上方。

.bindPopup(this.showTopPopup, {
  message: '这条说明会出现在按钮上方。',
  placement: Placement.Top,
  enableArrow: true
})

当底部空间紧张,或者下面有重要按钮时,把气泡放到上方更稳。一般来说,位置跟着页面空间和阅读方向调,没有绝对答案。

自定义气泡

第三组换成 builder

.bindPopup(this.showCustomPopup, {
  builder: this.customPopupBuilder,
  placement: Placement.Top,
  popupColor: '#FFFFFF',
  enableArrow: true
})

自定义气泡可以放标题和说明,但仍然要克制。这个案例只放了两行文字,没有把表单和复杂操作放进去。

你自己的页面里有没有那种“用户第一次看不懂,但又不值得单独写一页说明”的控件?这类地方就很适合试试 Popup。

完整代码

@Entry
@Component
struct ArkUIPopupDemo {
  @State showBasicPopup: boolean = false
  @State showTopPopup: boolean = false
  @State showCustomPopup: boolean = false

  @Builder
  sectionTitle(title: string, desc: string) {
    Column({ space: 6 }) {
      Text(title)
        .fontSize(19)
        .fontWeight(FontWeight.Bold)
        .fontColor('#111827')
      Text(desc)
        .fontSize(13)
        .fontColor('#6B7280')
        .lineHeight(20)
    }
    .width('100%')
    .alignItems(HorizontalAlign.Start)
  }

  @Builder
  customPopupBuilder() {
    Column({ space: 8 }) {
      Text('提示写在这里')
        .fontSize(15)
        .fontWeight(FontWeight.Bold)
        .fontColor('#111827')
      Text('自定义 Popup 可以放更像卡片的内容,但仍然要克制。')
        .fontSize(12)
        .fontColor('#4B5563')
        .lineHeight(18)
    }
    .width(210)
    .padding(14)
    .borderRadius(12)
    .backgroundColor('#FFFFFF')
  }

  @Builder
  popupCard(title: string, desc: string, content: string) {
    Column({ space: 12 }) {
      Column({ space: 6 }) {
        Text(title)
          .fontSize(17)
          .fontWeight(FontWeight.Bold)
          .fontColor('#111827')
        Text(desc)
          .fontSize(13)
          .fontColor('#6B7280')
          .lineHeight(20)
      }
      .width('100%')
      .alignItems(HorizontalAlign.Start)

      Text(content)
        .fontSize(13)
        .fontColor('#1F2937')
        .lineHeight(20)
        .padding(12)
        .borderRadius(10)
        .backgroundColor('#F8FAFC')
        .border({ width: 1, color: '#E5E7EB' })
        .width('100%')
    }
    .width('100%')
    .padding(16)
    .borderRadius(14)
    .backgroundColor('#FFFFFF')
    .border({ width: 1, color: '#E5E7EB' })
    .alignItems(HorizontalAlign.Start)
  }

  build() {
    Scroll() {
      Column({ space: 22 }) {
        Column({ space: 8 }) {
          Text('ArkUI Popup')
            .fontSize(28)
            .fontWeight(FontWeight.Bold)
            .fontColor('#111827')
          Text('小气泡只讲一句有用的话')
            .fontSize(16)
            .fontColor('#4B5563')
          Text('Popup 适合贴着某个控件解释一句话。它不是流程入口,也不适合放一大段复杂内容。')
            .fontSize(14)
            .fontColor('#6B7280')
            .lineHeight(22)
        }
        .width('100%')
        .alignItems(HorizontalAlign.Start)

        this.sectionTitle('基础文字气泡:解释一个点', 'bindPopup 绑定在触发控件上,show 控制显示与隐藏。')
        Column({ space: 12 }) {
          this.popupCard('为什么需要昵称?', '用户点到按钮时,气泡只补充一条上下文。', '示例使用 message 写一段短说明。')
          Button('显示基础气泡')
            .fontSize(14)
            .fontColor('#FFFFFF')
            .backgroundColor('#2563EB')
            .borderRadius(18)
            .height(38)
            .padding({ left: 18, right: 18 })
            .onClick(() => {
              this.showBasicPopup = !this.showBasicPopup
            })
            .bindPopup(this.showBasicPopup, {
              message: '昵称会展示给其他用户,建议用容易识别的名字。',
              placement: Placement.Bottom,
              enableArrow: true,
              onStateChange: (event) => {
                if (!event.isVisible) {
                  this.showBasicPopup = false
                }
              }
            })
        }
        .width('100%')
        .alignItems(HorizontalAlign.Start)

        this.sectionTitle('位置控制:气泡跟着控件走', 'placement 可以调整气泡出现的位置,常见的是 Top、Bottom、Left、Right。')
        Column({ space: 12 }) {
          this.popupCard('顶部提示', '当底部空间紧张时,可以把气泡放到控件上方。', '示例把 placement 设为 Placement.Top。')
          Button('显示顶部气泡')
            .fontSize(14)
            .fontColor('#FFFFFF')
            .backgroundColor('#0F766E')
            .borderRadius(18)
            .height(38)
            .padding({ left: 18, right: 18 })
            .onClick(() => {
              this.showTopPopup = !this.showTopPopup
            })
            .bindPopup(this.showTopPopup, {
              message: '这条说明会出现在按钮上方。',
              placement: Placement.Top,
              enableArrow: true,
              onStateChange: (event) => {
                if (!event.isVisible) {
                  this.showTopPopup = false
                }
              }
            })
        }
        .width('100%')
        .alignItems(HorizontalAlign.Start)

        this.sectionTitle('自定义气泡:只加必要内容', 'builder 可以定制气泡内部结构,但仍然建议保持轻量。')
        Column({ space: 12 }) {
          this.popupCard('自定义内容', '当纯文字不够表达时,再换成自定义 builder。', '这里放标题和一句说明,没有塞表单或复杂操作。')
          Button('显示自定义气泡')
            .fontSize(14)
            .fontColor('#FFFFFF')
            .backgroundColor('#C2410C')
            .borderRadius(18)
            .height(38)
            .padding({ left: 18, right: 18 })
            .onClick(() => {
              this.showCustomPopup = !this.showCustomPopup
            })
            .bindPopup(this.showCustomPopup, {
              builder: this.customPopupBuilder,
              placement: Placement.Top,
              popupColor: '#FFFFFF',
              enableArrow: true,
              onStateChange: (event) => {
                if (!event.isVisible) {
                  this.showCustomPopup = false
                }
              }
            })
        }
        .width('100%')
        .alignItems(HorizontalAlign.Start)
      }
      .width('100%')
      .padding(24)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F8FAFC')
  }
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。