ArkUI bindSheet:半屏一拉起,任务别变成新页面

举报
蓝瘦的蜕变 发表于 2026/09/12 22:58:34 2026/09/12
【摘要】 今天我们用 bindSheet 做一个半模态任务面板。 半模态适合处理短任务。比如整理草稿、补标签、选择分享范围,这些事不一定值得开一个完整页面,但又比一句提示复杂一点。我们这篇只做一个触发按钮和一个面板,先把最常用的结构跑通。 准备一个显示开关 bindSheet 需要一个布尔值控制显示和隐藏。 按钮点击时把它改成

ArkUI bindSheet:半屏一拉起,任务别变成新页面

今天我们用 bindSheet 做一个半模态任务面板。

半模态适合处理短任务。比如整理草稿、补标签、选择分享范围,这些事不一定值得开一个完整页面,但又比一句提示复杂一点。我们这篇只做一个触发按钮和一个面板,先把最常用的结构跑通。

准备一个显示开关

bindSheet 需要一个布尔值控制显示和隐藏。

@State showSheet: boolean = false

按钮点击时把它改成 true,面板里的“完成并收起”按钮再改回 false。这一步只是控制半模态显隐,不展开状态管理。

还有一个很容易踩的点:用户也可能用半模态自带关闭按钮、拖拽或蒙层关闭面板。面板关了以后,我们也要把 showSheet 同步回 false,否则下次点击还是 true -> true,界面就不会重新拉起。

写面板内容

面板内容放进一个 builder。

@Builder
sheetContent() {
  Column({ space: 18 }) {
    Text('整理这篇草稿')
    Button('完成并收起')
      .onClick(() => {
        this.showSheet = false
      })
  }
}

我们把关闭按钮放在面板内部,是为了让用户看到明确的收尾动作。半模态也支持拖动和关闭入口,但案例里保留一个按钮更直观。

绑定到一个按钮上

真正绑定时,用 bindSheet

Button('打开半模态任务面板')
  .onClick(() => {
    this.showSheet = true
  })
  .bindSheet(this.showSheet, this.sheetContent, {
    height: SheetSize.MEDIUM,
    dragBar: true,
    showClose: true,
    detents: [SheetSize.MEDIUM, SheetSize.LARGE],
    maskColor: '#66000000',
    onDisappear: () => {
      this.showSheet = false
    }
  })

这里故意只给一个按钮绑定一个半模态。一个节点上挂太多面板,后面维护起来很容易乱。

height 决定初始高度,detents 决定可停靠高度。dragBarshowClose 让用户知道这个面板可以被收起。maskColor 给底层页面加一层遮罩,让当前重点更明确。onDisappear 负责把页面里的显隐状态同步回来,避免关闭后再次点击没有反应。

你可以想一下自己的页面:有没有哪个操作只是临时补充几项信息,却被做成了完整页面?这种场景很适合先试试半模态。

完整代码

@Entry
@Component
struct ArkUIBindSheetDemo {
  @State showSheet: 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
  sheetContent() {
    Column({ space: 18 }) {
      Column({ space: 8 }) {
        Text('整理这篇草稿')
          .fontSize(22)
          .fontWeight(FontWeight.Bold)
          .fontColor('#111827')
        Text('半模态适合处理一个临时任务。底层页面还在,用户知道自己从哪里来。')
          .fontSize(14)
          .fontColor('#6B7280')
          .lineHeight(22)
      }
      .width('100%')
      .alignItems(HorizontalAlign.Start)

      Column({ space: 10 }) {
        this.taskRow('检查标题', '标题要让用户知道这次面板在处理什么。', '#2563EB')
        this.taskRow('补充标签', '短任务放在这里,比跳到新页面更轻。', '#0F766E')
        this.taskRow('确认发布前状态', '任务完成后可以直接收起面板。', '#C2410C')
      }
      .width('100%')

      Button('完成并收起')
        .width('100%')
        .height(44)
        .borderRadius(22)
        .fontColor('#FFFFFF')
        .backgroundColor('#111827')
        .onClick(() => {
          this.showSheet = false
        })
    }
    .width('100%')
    .padding({ left: 22, right: 22, top: 18, bottom: 24 })
    .backgroundColor('#FFFFFF')
  }

  @Builder
  taskRow(title: string, desc: string, color: string) {
    Row({ space: 12 }) {
      Text(title.substring(0, 1))
        .fontSize(15)
        .fontWeight(FontWeight.Bold)
        .fontColor('#FFFFFF')
        .textAlign(TextAlign.Center)
        .width(34)
        .height(34)
        .borderRadius(17)
        .backgroundColor(color)

      Column({ space: 4 }) {
        Text(title)
          .fontSize(15)
          .fontWeight(FontWeight.Bold)
          .fontColor('#111827')
        Text(desc)
          .fontSize(12)
          .fontColor('#6B7280')
          .lineHeight(18)
      }
      .layoutWeight(1)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .padding(12)
    .borderRadius(12)
    .backgroundColor('#F8FAFC')
    .border({ width: 1, color: '#E5E7EB' })
  }

  build() {
    Scroll() {
      Column({ space: 22 }) {
        Column({ space: 8 }) {
          Text('ArkUI bindSheet')
            .fontSize(28)
            .fontWeight(FontWeight.Bold)
            .fontColor('#111827')
          Text('半屏一拉起,任务别变成新页面')
            .fontSize(16)
            .fontColor('#4B5563')
          Text('半模态适合处理短任务。它保留底层页面的上下文,比新开一个完整页面更轻。')
            .fontSize(14)
            .fontColor('#6B7280')
            .lineHeight(22)
        }
        .width('100%')
        .alignItems(HorizontalAlign.Start)

        this.sectionTitle('一个按钮绑定一个半模态', '这里故意只放一个触发点,避免同一个节点挂多个面板导致关系混乱。')
        Column({ space: 14 }) {
          Text('点击按钮后,面板以中等高度出现,并提供拖拽条、关闭按钮和两个停靠高度。')
            .fontSize(14)
            .fontColor('#4B5563')
            .lineHeight(22)
            .width('100%')

          Button('打开半模态任务面板')
            .fontSize(14)
            .fontColor('#FFFFFF')
            .backgroundColor('#2563EB')
            .borderRadius(20)
            .height(40)
            .padding({ left: 20, right: 20 })
            .onClick(() => {
              this.showSheet = true
            })
            .bindSheet(this.showSheet, this.sheetContent, {
              height: SheetSize.MEDIUM,
              dragBar: true,
              showClose: true,
              detents: [SheetSize.MEDIUM, SheetSize.LARGE],
              maskColor: '#66000000',
              onDisappear: () => {
                this.showSheet = false
              }
            })
        }
        .width('100%')
        .padding(16)
        .borderRadius(14)
        .backgroundColor('#FFFFFF')
        .border({ width: 1, color: '#E5E7EB' })
        .alignItems(HorizontalAlign.Start)

        this.sectionTitle('几个参数先看懂', 'height 决定初始高度,detents 决定可停靠高度,dragBar 和 showClose 负责基础关闭体验。')
        Column({ space: 10 }) {
          this.taskRow('SheetSize.MEDIUM', '初始展示半屏左右,适合临时任务。', '#2563EB')
          this.taskRow('detents', '允许用户把面板拖到另一个高度。', '#0F766E')
          this.taskRow('maskColor', '给底层页面一层遮罩,提示当前重点在面板里。', '#C2410C')
        }
        .width('100%')
      }
      .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个月内不可修改。