鸿蒙UI开发——实现一个上拉抽屉效果

1、概 述

在项目开发中,我们可能会遇到临时交互的场景(即:弹出一个临时交互框,交互完毕后继续用户的主流程),效果如下:

在ArkUI中,此类弹出窗被称为"半模态页面",ArkUI为我们提供了一套可以快速实现此效果的接口,本文针对此效果的实现做讨论。

2、接口定义

给组件绑定半模态页面,点击后显示模态页面。接口定义如下:

复制代码
bindSheet(isShow: Optional<boolean>, builder: CustomBuilder, options?: SheetOptions)

用法类似如下(第5行代码):

复制代码
build() {  Column() {    Button("点击我弹出上拉抽屉")      // ... 其他属性      .bindSheet($$this.isShow, this.myBuilder(), {        // 三挡高度(默认是中间)        detents: [SheetSize.MEDIUM, SheetSize.LARGE, 200],        blurStyle: BlurStyle.Thick,        showClose: true,        title: { title: "抽屉标题", subtitle: "抽屉副标题" },      })  }  .justifyContent(FlexAlign.Start)  .width('100%')  .height('100%')}

其中:

  • isShow是可以支持双向绑定的显示/隐藏的切换控制;

  • builder是抽屉需要显示的内容,内容构造器;

  • options是配置参数,定义如下:

|-----------------------------|----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 名称 | 类型 | 说明 |
| backgroundColor | ResourceColor | 半模态页面的背板颜色。默认值:Color.White。 |
| onWillAppear | () => void | 半模态页面显示(动画开始前)回调函数。 |
| onAppear | () => void | 半模态页面显示(动画结束后)回调函数。 |
| onWillDisappear | () => void | 半模态页面回退(动画开始前)回调函数。 说明:不允许在onWillDisappear函数中修改状态变量,可能会导致组件行为不稳定。 |
| onDisappear | () => void | 半模态页面回退(动画结束后)回调函数。 |
| height | SheetSize | Length | 半模态高度,默认是LARGE。 说明:API version 12之前,底部弹窗横屏时该属性设置无效,高度为距离屏幕顶部8vp。API version 12开始,底部弹窗横屏时该属性设置生效,最大高度为距离屏幕顶部8vp。底部弹窗时,当设置detents时,该属性设置无效。底部弹窗竖屏时,最大高度为距离信号栏8vp。居中弹窗和跟手弹窗设置类型为SheetSize.LARGE和SheetSize.MEDIUM无效,显示默认高度560vp。居中弹窗和跟手弹窗最小高度为320vp,最大高度为窗口短边的90%。当使用Length设置的高度和使用SheetSize.FIT_CONTENT自适应的高度大于最大高度,则显示最大高度,小于最小高度,则显示最小高度。 |
| detents | [(SheetSize | Length), ( SheetSize | Length)?, (SheetSize | Length)?] | 半模态页面的切换高度档位。 说明:从API version 12开始,底部弹窗横屏时该属性设置生效。底部弹窗竖屏生效,元组中第一个高度为初始高度。面板可跟手滑动切换档位,松手后是否滑动至目标档位有两个判断条件:速度和距离。速度超过阈值,则执行滑动至与手速方向一致的目标档位;速度小于阈值,则引入距离判断条件,当位移距离>当前位置与目标位置的1/2,滑动至与手速方向一致的目标档位,位移距离当前位置与目标位置的1/2,返回至当前档位。速度阈值:1000,距离阈值:50%。 |
| preferType | SheetType | 半模态页面的样式。 说明:半模态在不同窗口所支持的显示类型:1. 宽度 < 600vp:底部。2. 600vp <= 宽度 < 840vp:底部、居中。默认居中样式。3. 宽度 >= 840vp:底部、居中、跟手。默认跟手样式。 |
| showClose | boolean | Resource | 是否显示关闭图标,默认显示。 说明:Resource需要为boolean类型。 |
| dragBar | boolean | 是否显示控制条。 说明:半模态面板的detents属性设置多个不同高度并且设置生效时,默认显示控制条。否则不显示控制条。 |
| blurStyle | BlurStyle | 半模态面板的模糊背景。默认无模糊背景。 |
| maskColor | ResourceColor | 半模态页面的背景蒙层颜色。 |
| title | SheetTitleOptions | CustomBuilder | 半模态面板的标题。 |
| enableOutsideInteractive | boolean | 半模态所在页面是否允许交互。 说明:设置为true时允许交互,不显示蒙层;设置为false时不允许交互,显示蒙层;若不进行设置,默认底部弹窗与居中弹窗不允许交互,跟手弹窗允许交互。当设置为true时,maskColor设置无效。 |
| shouldDismiss | (sheetDismiss: SheetDismiss) => void | 半模态页面交互式关闭回调函数。 说明:当用户执行下拉关闭/back事件/点击蒙层关闭/关闭按钮关闭交互操作时,如果注册该回调函数,则不会立刻关闭。 |
| onWillDismiss | DismissSheetAction | 半模态页面交互式关闭回调函数。说明:当用户执行关闭操作时,如果注册该回调函数,不会立刻关闭, 由开发者控制是否关闭。在回调函数中可以通过reason得到关闭页面的操作类型,从而根据原因选择是否关闭半模态页面。在onWillDismiss回调中,不能再做onWillDismiss拦截。元服务API: 从API version 12开始,该接口支持在元服务中使用。 |
| onWillSpringBackWhenDismiss | SpringBackAction | 半模态页面交互式关闭前控制回弹函数。 说明:当用户执行下拉关闭操作并注册shouldDimiss或onWillDismiss时,如果注册该回调函数,则不会回弹,由开发者控制下滑关闭时是否回弹。在回调函数中可以通过调用springBack来实现回弹效果。 |
| onHeightDidChange | Callback<number> | 半模态页面高度变化回调函数。 说明:底部弹窗时,只有档位变化和拖拽跟手才返回每一帧高度,拉起半模态和避让软键盘只返回最后的高度,其他弹窗只在半模态拉起返回最后高度。返回值为px。 |
| onDetentsDidChange | Callback<number> | 半模态页面档位变化回调函数。 说明:底部弹窗时,档位变化返回最后的高度。返回值为px。 |
| onWidthDidChange | Callback<number> | 半模态页面宽度变化回调函数。 说明:宽度变化时返回最后的宽度。返回值为px。 |
| onTypeDidChange | Callback<SheetType> | 半模态页面形态变化回调函数。 说明:形态变化时返回最后的形态。 |
| borderWidth | Dimension | EdgeWidths | LocalizedEdgeWidths | 设置半模态页面的边框宽度。可分别设置4个边框宽度。默认值:0。百分比参数方式:以父元素半模态页面宽的百分比来设置半模态页面的边框宽度。当半模态页面左边框和右边框大于半模态页面宽度,半模态页面上边框和下边框大于半模态页面高度,显示可能不符合预期。说明:底部弹窗时,底部边框宽度设置无效。 |
| borderColor | ResourceColor | EdgeColors | LocalizedEdgeColors | 设置半模态页面的边框颜色。默认值:Color.Black。如果使用borderColor属性,需要和borderWidth属性一起使用。说明:底部弹窗时,底部边框颜色设置无效。 |
| borderStyle | BorderStyle | EdgeStyles | 设置半模态页面的边框样式。默认值:BorderStyle.Solid。如果使用borderStyle属性,需要和borderWidth属性一起使用。说明:底部弹窗时,底部边框样式设置无效。 |
| width | Dimension | 设置半模态页面的宽度。百分比参数方式:以父元素宽的百分比来设置半模态页面的宽度。 |
| shadow | ShadowOptions | ShadowStyle | 设置半模态页面的阴影。 |
| uiContext | UIContext | 在UIContext实例对应的窗口中显示半模态。说明:使用openBindSheet启动的半模态页面,不支持设置、更新该属性。元服务API: 从API version 12开始,该接口支持在元服务中使用。 |
| mode | SheetMode | 设置半模态页面的显示层级。默认值:SheetMode.OVERLAY。 说明:1. 半模态显示期间mode属性不支持动态切换,两种模式的显示层级完全不同,无法做到显示期间同一个半模态从一个层级变换到另一个层级。建议在使用时明确诉求固定mode值。2. 设置SheetMode.EMBEDDED时不支持设置UIContext属性,两者对应的半模态显示层级效果互相冲突。3. 使用openBindSheet启动半模态页面,若未传入有效的targetId,则不支持设置为SheetMode.EMBEDDED,默认为SheetMode.OVERLAY。元服务API: 从API version 12开始,该接口支持在元服务中使用。 |
| scrollSizeMode | ScrollSizeMode | 设置半模态面板滑动时,内容区域刷新时机。默认值:ScrollSizeMode.FOLLOW_DETENT 。 |

3、案 例

实现一个案例效果如下:

代码如下(24~30行的配置,5~15行的builder):​​​​​​​

复制代码
@Entry@Componentstruct SheetTransitionExample {  @State isShow: boolean = false  @Builder  myBuilder() {    Column() {      Text('欢迎加入【Harmony自习室】')        .fontSize(20)      Button("确认")        .margin(10)        .fontSize(20)    }    .width('100%')  }  build() {    Column() {      Button("点击我弹出上拉抽屉")        .onClick(() => {          this.isShow = true        })        .fontSize(20)        .margin(10)        .bindSheet($$this.isShow, this.myBuilder(), {          // 三挡高度(默认是中间)          detents: [SheetSize.MEDIUM, SheetSize.LARGE, 200],          blurStyle: BlurStyle.Thick,          showClose: true,          title: { title: "抽屉标题", subtitle: "抽屉副标题" },        })    }    .justifyContent(FlexAlign.Start)    .width('100%')    .height('100%')  }}
相关推荐
特立独行的猫a1 小时前
鸿蒙HarmonyOS最新的组件间通信的装饰器与状态组件详解
华为·harmonyos
HarmonyOS_SDK3 小时前
【FAQ】HarmonyOS SDK 闭源开放能力 —Live View Kit (3)
harmonyos
ONETHING_CLOUD_24 小时前
华为鸿蒙电脑发布,折叠屏怎么选?
经验分享·华为·电脑·harmonyos·数码
hashiqimiya6 小时前
当点击button时就会,弹出一段信息,然后就消失的效果
鸿蒙·弹出消失
bao_lanlan6 小时前
兰亭妙微 | 系统界面设计优化:让复杂信息更轻松被看懂
ui·adobe·设计模式·ux
互联网之声7 小时前
广州卓远VR受邀参加2025智能体育典型案例调研活动,并入驻国体华为运动健康联合实验室!
华为·vr
枫叶丹48 小时前
【HarmonyOS Next之旅】DevEco Studio使用指南(二十五) -> 端云一体化开发 -> 业务介绍(二)
华为·harmonyos·deveco studio·harmonyos next
特立独行的猫a10 小时前
鸿蒙HarmonyOS多设备流转:分布式的智能协同技术介绍
分布式·华为·harmonyos·碰一碰·跨设备流转
文火冰糖的硅基工坊14 小时前
[创业之路-369]:企业战略管理案例分析-9-战略制定-差距分析的案例之华为
人工智能·华为·架构·系统架构·跨学科·跨学科融合