一、功能简介

本篇实现一个支持上滑展开、下滑关闭底部抽屉弹窗组件,支持拖动范围控制、吸附回弹、滑动关闭等交互体验,常用于选项面板、AI推荐卡片、文件操作框等场景。


二、关键技术点

功能 实现方式
抽屉展开/收起 .translate({ y }) + .animate()
拖动手势 PanGesture() 监听垂直滑动
自动吸附 判断滑动距离自动“展开”或“关闭”
状态管理 @State offsetY + @State isOpen

三、页面结构

entry/src/main/ets/pages/BottomDrawerDemo.ets

四、ArkTS 实战代码(BottomDrawerDemo.ets)

@Entry
@Component
struct BottomDrawerDemo {
  @State isOpen: boolean = false
  @State offsetY: number = 300
  private threshold: number = 150
  private maxHeight: number = 300

  openDrawer() {
    this.offsetY = 0
    this.isOpen = true
  }

  closeDrawer() {
    this.offsetY = this.maxHeight
    this.isOpen = false
  }

  build() {
    Stack() {
      Column() {
        Text('HarmonyOS 5.0.0 或以上')
          .fontSize(20)
          .margin({ bottom: 20 })

        Button('⬆️ 打开底部抽屉')
          .onClick(() => this.openDrawer())
      }
      .align(Alignment.Center)

      // 底部抽屉
      Column() {
        Box()
          .width(36).height(4).borderRadius(2)
          .backgroundColor('#aaa')
          .margin({ top: 12, bottom: 12 })

        Text('这是底部抽屉内容')
          .fontSize(16)
          .margin({ bottom: 20 })

        Button('关闭')
          .onClick(() => this.closeDrawer())
      }
      .width('100%')
      .height(this.maxHeight)
      .padding(20)
      .backgroundColor('#ffffff')
      .borderRadius({ topLeft: 20, topRight: 20 })
      .translate({ y: this.offsetY })
      .gesture(
        PanGesture()
          .onActionUpdate(e => {
            this.offsetY = Math.min(this.maxHeight, Math.max(0, this.offsetY + e.offsetY))
          })
          .onActionEnd(() => {
            if (this.offsetY > this.threshold) {
              this.closeDrawer()
            } else {
              this.openDrawer()
            }
          })
      )
      .animate({ duration: 250, curve: Curve.EaseOutBack })
      .position({ x: 0, y: 0 })
      .align(Alignment.Bottom)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#f7f7f7')
  }
}

五、运行效果说明

  • 初始状态抽屉隐藏在底部(offsetY 为 300);
  • 点击按钮或手动上滑 → 展开抽屉;
  • 下滑超过一定距离 → 自动关闭;
  • 拖动结束时自动吸附至顶部或底部;
  • 整体交互平滑、手感灵敏,模拟系统级弹窗行为。

六、常见问题与优化建议

问题 原因 建议
拖动弹性不够 没有限制最大最小值 使用 Math.min / Math.max 限制 offset 范围
滑动后停在中间 无吸附逻辑 判断拖动结束位置吸附至顶部或底部
动画生硬 无动画修饰 使用 .animate({ duration, curve }) 平滑处理

七、拓展建议

  • 支持抽屉内容滚动、分页;
  • 结合模糊背景、点击外层关闭功能;
  • 可封装为 <BottomDrawer open={true}>...</BottomDrawer>
  • 添加多个高度状态(半展开、全展开);
  • 支持动态高度内容适配、软键盘避让处理。

下一篇为第25篇:

《HarmonyOS 5.0.0 或以上:实现 AI内容生成加载节奏动画与渐显展示》

Logo

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

更多推荐