HarmonyOS鸿蒙Next中用bindSheet实现高性能的底部半模态交互抽屉

HarmonyOS鸿蒙Next中用bindSheet实现高性能的底部半模态交互抽屉

如何利用 bindSheet 实现高性能的底部半模态交互抽屉

3 回复

实现效果

cke_724.png

cke_1062.png

实现思路

一、使用 @State 变量来控制抽屉的显示状态(isPresent)以及当前的高度档位。

二、创建一个主页面和一个作为抽屉内容的自定义组件。

三、在主容器组件上使用 .bindSheet() 属性方法。

完整代码

// 定义抽屉内容的自定义组件
@Builder
function BottomSheetContent(closeCallback: () => void) {
  Column() {
    Text("操作面板")
      .fontSize(24)
      .fontWeight(FontWeight.Bold)
      .margin({ top: 20, bottom: 20 })

    // 列表项
    List({ space: 10 }) {
      ForEach(["选项 A: 编辑资料", "选项 B: 分享好友", "选项 C: 删除内容"], (item: string) => {
        ListItem() {
          Row() {
            Text(item)
              .fontSize(16)
              .fontColor("#182431")
            Blank()
            Image($r('sys.symbol.chevron_right'))
              .width(20)
              .height(20)
              .fillColor('#99182431')
          }
          .width('100%')
          .padding(16)
          .backgroundColor('#F1F3F5')
          .borderRadius(12)
          .onClick(() => {
            // 点击选项后的业务逻辑
            console.info(`User clicked: ${item}`);
            closeCallback(); 
          })
        }
      })
    }
    .width('100%')
    .layoutWeight(1)

    // 底部确认按钮区域
    Button("确认提交")
      .width('100%')
      .height(48)
      .fontSize(18)
      .fontWeight(FontWeight.Medium)
      .backgroundColor('#007DFF')
      .margin({ bottom: 20 })
      .onClick(() => {
        console.info("User confirmed action.");
        closeCallback();
      })
  }
  .width('100%')
  .height('100%')
  .padding({ left: 20, right: 20 })
}

@Entry
@Component
struct Index {
  // 控制抽屉显示的状态
  [@State](/user/State) isSheetShow: boolean = false;

  // 当前选中的展示高度模式
  [@State](/user/State) currentSheetSize: SheetSize = SheetSize.MEDIUM;

  build() {
    Column() {
      // 顶部标题区
      Text("BindSheet 演示")
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 100 })

      Text("点击下方按钮唤起底部面板")
        .fontSize(16)
        .fontColor('#666')
        .margin({ top: 10 })

      Blank()

      // 主界面按钮
      Button("打开操作抽屉")
        .fontSize(20)
        .backgroundColor('#0A59F7')
        .onClick(() => {
          this.isSheetShow = true;
        })
    }
    .width('100%')
    .height('100%')
    .padding(20)
    // ==========================================
    // 核心实现:bindSheet
    // ==========================================
    .bindSheet(this.isSheetShow, BottomSheetContent(() => {
      this.isSheetShow = false; // 关闭回调
    }), {
      height: this.currentSheetSize, // 设置高度模式:SMALL, MEDIUM, LARGE
      showClose: false, // 是否显示默认的关闭图标
      shouldDismiss: ((dismiss: SheetDismiss) => {
        // dismiss.dismiss() 表示允许关闭
        dismiss.dismiss();
      }),
      onDisappear: () => {
        console.info("Sheet has disappeared");
      },
      blurStyle: BlurStyle.COMPONENT_ULTRA_THICK,
      enableOutsideInteractive: true,
      preferType: SheetType.BOTTOM,
      detents: [SheetSize.MEDIUM, SheetSize.LARGE]
    })
  }
}

更多关于HarmonyOS鸿蒙Next中用bindSheet实现高性能的底部半模态交互抽屉的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,bindSheet用于实现高性能底部半模态抽屉。它通过声明式UI开发,支持自定义高度、圆角及交互动画。开发者可绑定数据状态,抽屉内容随状态变化自动更新。该组件优化了渲染性能,确保滑动流畅。

在HarmonyOS Next中,bindSheet 是实现高性能底部半模态抽屉(Bottom Sheet)的关键API。它通过声明式UI和状态驱动的方式,能够高效地创建和管理抽屉的显示与交互。

核心实现步骤:

  1. 定义抽屉内容:使用 @Builder 装饰器构建抽屉的UI内容,确保组件可复用且与主页面解耦。
  2. 绑定状态与抽屉:通过 bindSheet 将控制抽屉显示/隐藏的状态变量(例如 isPresent)与抽屉内容绑定。当状态改变时,抽屉会响应式地显示或隐藏。
  3. 配置抽屉参数:可以设置 height(高度模式,如固定值、百分比)、dragBar(是否显示拖拽条)、shouldDismiss(点击遮罩是否关闭)等属性来定制交互行为。
  4. 处理交互与动画bindSheet 内置了平滑的动画(如入场、出场、拖拽跟随)和手势交互(如向下拖拽关闭)。可以通过回调(如 onWillDismiss)在特定时机执行业务逻辑。

性能优势体现:

  • 按需构建:抽屉内容仅在需要显示时才会构建和渲染,减少了初始页面负载。
  • 高效渲染:基于ArkUI的声明式范式与差分更新机制,在状态变化时仅更新必要的UI部分。
  • 原生手势:拖拽交互由系统底层手势处理,动画流畅,性能开销极小。

示例代码片段:

@Entry
@Component
struct Index {
  @State isPresent: boolean = false;

  @Builder
  SheetBuilder() {
    // 抽屉内容
    Column() {
      Text('抽屉内容').fontSize(20)
      // ... 其他组件
    }
  }

  build() {
    Column() {
      Button('显示抽屉')
        .onClick(() => {
          this.isPresent = true; // 状态改变,触发抽屉显示
        })
    }
    .bindSheet(
      this.isPresent, // 绑定状态
      this.SheetBuilder(), // 绑定内容
      {
        height: SheetHeight.MEDIUM, // 中等高度
        dragBar: true, // 显示拖拽条
        shouldDismiss: () => { // 点击遮罩关闭
          this.isPresent = false;
          return true;
        }
      }
    )
  }
}

通过 bindSheet 可以简洁地实现一个性能优异、交互流畅的底部抽屉,其设计符合HarmonyOS Next的高性能UI架构。

回到顶部