文章目录前言一、bindSheet 的基本用法二、项目中的 bindSheet 实现三、参数详解3.1 $$this.isShow双向绑定控制显示3.2 detents弹窗高度配置3.3 dragBar拖拽把手3.4 title弹窗标题3.5 blurStyle毛玻璃效果3.6 backgroundColor背景颜色3.7 onWillDismiss关闭前回调四、bindBuilder弹窗内容五、弹窗的完整生命周期六、bindSheet vs 自定义弹窗总结前言附近加油站里有一个很好看的交互进入地图页后底部会滑出一个半透明的面板展示附近的加油站列表。这个效果叫半屏弹窗Bottom Sheet在 HarmonyOS 里用bindSheet实现。bindSheet是 ArkUI 里非常强大的 API参数很多但用对了能做出 iOS 级别的流畅体验。这篇文章把项目里的用法完整讲解让你彻底掌握它。项目预览一、bindSheet 的基本用法bindSheet是任何组件都可以调用的属性方法语法组件.bindSheet($$isShow,// 双向绑定控制弹窗显示/隐藏的状态变量builder(),// 弹窗内容一个 Builder 函数options// 配置项)二、项目中的 bindSheet 实现// GasStationPage.etsStack(){MapComponent({...});this.titleBuilder();}.width(100%).height(100%).bindSheet($$this.isShow,this.bindBuilder(),{// 弹窗高度锚点支持两种高度detents:[Constants.BIND_SHEET_HEIGHT,SheetSize.MEDIUM],// 不显示拖拽把手dragBar:false,// 弹窗标题title:{title:$r(app.string.gas_station)},// 毛玻璃背景效果blurStyle:BlurStyle.COMPONENT_THICK,// 弹窗背景色半透明白色backgroundColor:$r(app.color.bind_sheet_background),// 弹窗关闭前的回调onWillDismiss:((dismissSheetAction:DismissSheetAction){if(this.curMarker){this.imageScale1;mapUtil.imageAnimation(this.curMarker,this.imageScale);// 恢复 Marker 大小}dismissSheetAction.dismiss();// 确认关闭弹窗})});三、参数详解3.1 $$this.isShow双向绑定控制显示StateisShow:booleanfalse;// 使用 $$ 表示双向绑定.bindSheet($$this.isShow,...)$$是 ArkUI 的状态变量双向绑定语法isShow true弹窗显示isShow false弹窗关闭用户下拉关闭弹窗时isShow也会自动变为false// 触发显示弹窗多处调用this.isShowtrue;// 页面进入1秒后自动显示setTimeout((){this.isShowtrue;},Constants.TIME);// 1000ms3.2 detents弹窗高度配置detents:[Constants.BIND_SHEET_HEIGHT,SheetSize.MEDIUM]// [400, SheetSize.MEDIUM]detents是弹窗可以停留的高度锚点数组用户可以拖拽在这些高度之间切换值说明number如 400固定高度pxSheetSize.FIT_CONTENT自适应内容高度SheetSize.MEDIUM屏幕高度的 50%SheetSize.LARGE屏幕高度的 90%项目的效果默认展示高度400px第一个锚点上拉后展开至屏幕 50%SheetSize.MEDIUM用户可以在两个高度之间拖拽切换3.3 dragBar拖拽把手dragBar:false,// 不显示顶部的拖拽指示条默认dragBar: true会在弹窗顶部显示一个灰色横条拖拽指示器。项目里关闭了因为有title标题作为顶部元素视觉上更简洁。3.4 title弹窗标题title:{title:$r(app.string.gas_station)// 显示加油站}在弹窗顶部显示标题文字支持自定义样式title:{title:加油站列表,subtitle:附近4个加油站// 可选副标题}3.5 blurStyle毛玻璃效果blurStyle:BlurStyle.COMPONENT_THICK,BlurStyle给弹窗背景加上毛玻璃模糊效果透过弹窗能隐约看到地图BlurStyle模糊程度适用场景THIN轻度模糊浅色背景REGULAR常规模糊通用THICK重度模糊深色背景COMPONENT_THIN组件级轻度模糊推荐新项目用COMPONENT_THICK组件级重度模糊本项目使用NONE无模糊不需要毛玻璃3.6 backgroundColor背景颜色backgroundColor:$r(app.color.bind_sheet_background),// 白色背景色和blurStyle叠加使用创造半透明毛玻璃效果。3.7 onWillDismiss关闭前回调onWillDismiss:((dismissSheetAction:DismissSheetAction){// 在这里做关闭前的清理工作if(this.curMarker){this.imageScale1;mapUtil.imageAnimation(this.curMarker,this.imageScale);}// 必须调用 dismiss() 确认关闭dismissSheetAction.dismiss();})onWillDismiss在弹窗即将关闭时用户下拉或点击遮罩触发恢复当前选中 Marker 的大小必须调用dismissSheetAction.dismiss()才会真正关闭弹窗否则弹窗不会关闭这个设计允许你在拦截关闭时做一些操作比如弹一个确认对话框onWillDismiss:((action:DismissSheetAction){AlertDialog.show({message:确定关闭吗,confirm:{value:确定,action:(){action.dismiss();}// 用户确认后才关闭}});})四、bindBuilder弹窗内容BuilderbindBuilder(){Column(){Scroll(){if(this.stationInfoListthis.stationInfoList.length0){List(){ForEach(this.stationInfoList,(station:StationData){ListItem(){Row({space:Constants.SPACE_12}){this.stationInfoCard(station);}.width(100%);};},(station:StationData){returnstation.idstation.name;});}.width(100%);}}.backgroundColor($r(app.color.start_window_background)).borderRadius(Constants.BORDER_RADIUS).margin({left:16,right:16}).opacity(Constants.ONE).scrollable(ScrollDirection.Vertical).edgeEffect(EdgeEffect.Fade)// 边缘渐隐效果.layoutWeight(Constants.ONE).align(Alignment.Top).height(Constants.MY_BUILDER_HEIGHT)// 300px.width(100%).scrollBar(BarState.Off);// 隐藏滚动条}.height(Constants.MY_BUILDER_COLUMN_HEIGHT);// 380px}弹窗内容是一个可滚动的加油站列表用Scroll包裹List实现滚动edgeEffect(EdgeEffect.Fade)让列表边缘有渐隐效果。五、弹窗的完整生命周期isShow false弹窗隐藏 ↓ this.isShow true代码触发 弹窗从底部滑入 ↓ 动画完成 弹窗显示默认高度400px ↓ 用户上拉 弹窗扩展高度50% ↓ 用户下拉或点遮罩 onWillDismiss 触发 ├─ 恢复 Marker 大小 └─ dismissSheetAction.dismiss() ↓ 弹窗从底部滑出 ↓ 动画完成 isShow false自动更新六、bindSheet vs 自定义弹窗方式优点缺点bindSheet原生动画流畅、支持拖拽、代码简洁样式自定义有限制自定义Stack动画完全自定义样式代码复杂、动画要自己写Dialog居中弹窗简单不适合底部抽屉样式对于底部抽屉效果强烈推荐用bindSheet原生的手势交互拖拽、弹性效果是自定义组件很难复现的。总结bindSheet的核心配置$$isShow双向绑定的布尔变量控制显示/隐藏detents高度锚点数组定义弹窗可停留的高度blurStyle毛玻璃效果COMPONENT_THICK效果最好onWillDismiss关闭前回调必须调用dismiss()才会真正关闭弹窗内容是Builder函数任何 ArkUI 组件都可以放进去下一篇讲GasStationPage 的完整实现解析——把整个地图页的代码从头到尾串一遍让你看懂每一行的作用。