往期知识点整理
- 鸿蒙(HarmonyOS)北向开发知识点记录~
- 【鸿蒙实战开发】基于Navigation的路由拦截管理
- 【鸿蒙实战开发】基于组件嵌套的滑动
- 【鸿蒙实战开发】基于Text的自定义字体
- 【鸿蒙实战开发】基于Grid实现混合布局
- 【鸿蒙实战开发】基于ArkUI实现类似Toast弹窗
- 【鸿蒙实战开发】基于短距离通信的BLE蓝牙扫描
- 【鸿蒙实战开发】HiLog日志能力介绍
- 【鸿蒙实战开发】基于HiAppEvent能力的应用崩溃监控上报
- 【鸿蒙实战开发】基于Refresh组件的下拉刷新
- 【鸿蒙实战开发】混合开发-web组件入门和实战
- 【HarmonyOS 鸿蒙实战开发】NavDestination弹窗
- 持续更新中……
介绍
本案例介绍了使用NavDestination组件的Dialog模式实现与前一个页面的联动的评论弹窗。
效果预览图
使用说明
点击案例中的商品介绍页面底部商店信息栏中的评论图标,即可拉起评论区弹窗,同时商品介绍页面自适应缩小。
此时在商品介绍页区域(或者未滑动浏览的评论区)可以通过手势向下滑动,缩小评论区高度的同时,增加商品介绍页面的高度,实现联动效果。
实现思路
- 创建商品介绍页面。
通过Navigation组件作为路由导航根容器,同时也作为本案例的商品介绍页的容器。
具体商品介绍组件内容省略。
build() {
Column() {
this.goodsItem()
}
.width($r('app.string.navdialog_full_size'))
}
@Builder
goodsItem() {
Column() {
// 商品图片
...
// 底部栏
this.shopBar(() => {
// 触发弹窗的回调函数
animateTo({ duration: Consts.COMMENT_DIALOG_TRANS_DURATION, curve: Curve.Ease }, () => {
this.ndDialogHeight = this.ndPageHeight * Consts.COMMENT_DIALOG_SCALE;
})
DynamicsRouter.push(RouterInfo.NAVDESTINATION_COMMENT_DIALOG)
logger.info(TAG, `open dialog`);
})
}
.width($r('app.string.navdialog_full_size'))
}
// 商店信息栏的自定义组件实现
@Builder
shopBar(callback: () => void) {
Row({ space: Consts.SHOP_BAR_SPACE }) {
...
// 评论按钮
Image($r("app.media.nd_comment"))
.width(Consts.SHOP_BAR_ICON_SIZE)
.height(Consts.SHOP_BAR_ICON_SIZE)
.onClick(callback)
...
}
...
}
- 创建评论区组件。
使用NavDestination组件作为评论区子页面的根容器,设置mode属性为NavDestinationMode.DIALOG。
此模式默认透明,进出页面栈不影响下层NavDestination的生命周期,不支持系统转场动画,所以可以实现评论区和商品页面同时展现,同时需要自己定义转场动画。
除了弹窗的转场动画,同时还需要设置商品页面缩小的动画,以实现衔接(此内容在上一步中已经实现),并保持转场动画时长略大于主页缩小动画,避免出现衔接空白。
如果显示评论区时不想显示底部商店信息栏,可以设置弹窗高度直接覆盖,可以简化实现代码。
Column() {
// 评论弹窗上部的蒙版,用于附加手势和确定评论弹窗高度
Column()
.width($r('app.string.navdialog_full_size'))
.height(this.windowHeight - this.dialogHeight - Consts.SHOP_BAR_HEIGHT)
.backgroundColor(Color.Transparent)
Column() {
Comment({
isGesture: this.isGesture,
listScrollAble: this.listScrollAble,
close: () => {
this.closeDialog();
}
})
}
.height(this.dialogHeight + Consts.SHOP_BAR_HEIGHT) // 提高弹窗的高度,用以覆盖底部商店栏
.backgroundColor(Color.White)
.transition(
TransitionEffect
.move(TransitionEdge.BOTTOM)
.animation({ duration: Consts.COMMENT_DIALOG_TRANS_DURATION, curve: Curve.Ease }))
}
.height($r('app.string.navdialog_full_size'))
- 设置手势实现动态联动效果。
主页和弹窗页面的尺寸需要联动修改,通过@LocalStorageLink装饰器配置的状态变量,即可实现二者高度的联动,同时设置手势属性实现实时跟手联动效果。
Column() {
Comment({
isGesture: this.isGesture,
listScrollAble: this.listScrollAble,
close: () => {
this.closeDialog();
}
})
}
.width($r('app.string.navdialog_full_size'))
.height(this.dialogHeight + Consts.SHOP_BAR_HEIGHT) // 提高弹窗的高度,用以覆盖底部商店栏
...
.parallelGesture(PanGesture({ direction: PanDirection.Vertical })
.onActionUpdate((event) => {
if (!this.isGesture || this.dialogHeight <= 0) {
return;
}
// 计算当前弹窗的高度
const curDialogHeight = this.initDialogHeight - event.offsetY;
if (curDialogHeight < 0) {
this.dialogHeight = 0;
} else if (curDialogHeight <= this.initDialogHeight) {
this.dialogHeight = curDialogHeight;
}
})
.onActionEnd(() => {
if (!this.isGesture && this.dialogHeight === this.initDialogHeight) {
return;
}
if (this.dialogHeight < Consts.COMMENT_DIALOG_MIN_HEIGHT) {
this.closeDialog();
} else {
this.recoveryDialog();
}
// 手势结束后,重新允许列表滚动
this.listScrollAble = true;
}), GestureMask.Normal)
通过onActionUpdate实时修改弹窗的高度,在抬手时通过onActionEnd回调实现关闭弹窗或者恢复弹窗以及相应的动画效果。
此处有一个注意点是同步评论区List组件的滑动手势和前面手动设置的自定义滑动手势。首先需要监听评论区的滑动位置,只有用户不在浏览状态(也就是List偏移不为0)
时才可以触发自定义手势。其次绑定自定义手势使用parallelGesture,使系统的List滑动手势和自定义绑定的手势都能够触发,避免滑动冒泡事件被阻塞。
// commets list
List({ space: Consts.COMMENT_SPACE, scroller: this.scroller }) {
// TODO: 高性能知识点: LazyForEach按需加载,提高加载性能。
LazyForEach(this.data, (item: number, index: number) => {
ListItem() {
CommentItem({ index: index + 1 }) // index from 1
}
}, (item: number) => item.toString())
}
// TODO: 高性能知识点: 使用了cachedCount设置预加载的评论,提高快速滑动时的性能。
.cachedCount(Consts.COMMENTS_LIST_CACHE)
.edgeEffect(EdgeEffect.Spring)
.onScroll(() => {
const offsetY = this.scroller.currentOffset().yOffset;
if (offsetY <= 0) {
this.isGesture = true;
this.scroller.scrollTo({ xOffset: 0, yOffset: 0 });
} else {
this.isGesture = false;
}
})
.layoutWeight(1) // 自适应布局
高性能知识点
- 本案例在滚动容器List中使用了 LazyForEach ,框架会根据滚动容器可视区域按需创建组件,当组件滑出可视区域外时,框架会进行组件销毁回收以降低内存占用。为了更好的列表滚动体验,减少列表滑动时出现白块,使用了List组件的cachedCount参数用于设置列表项缓存数,只在懒加载LazyForEach中生效。
- 本案例使用了系统高频回调 onScroll 与onActionUpdate ,为提高性能应注意避免在其中使用冗余和耗时的操作。
工程结构&模块类型
navdestinationdialog // HAR类型
├─common
| ├─Constants.ets // 项目中的常量
| └─Utils.ets // 通用的工具函数
├─mainpage
| └─MainPage.ets // 入口主页
├─model
| └─NavgationModel.ets // 数据模型
└─viewmodel
├─CommentDialog.ets // 评论弹窗视图
└─Comment.ets // 评论列表视图
总是有很多小伙伴反馈说:鸿蒙开发不知道学习哪些技术?不知道需要重点掌握哪些鸿蒙开发知识点? 为了解决大家这些学习烦恼。在这准备了一份很实用的鸿蒙全栈开发学习路线与学习文档给大家用来跟着学习。
针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植……等)技术知识点。
《鸿蒙 (Harmony OS)开发学习手册》(共计892页):https://gitcode.com/HarmonyOS_MN/733GH/overview
如何快速入门?
1.基本概念
2.构建第一个ArkTS应用
3.……
开发基础知识:
1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……
基于ArkTS 开发
1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……
鸿蒙开发面试真题(含参考答案):https://gitcode.com/HarmonyOS_MN/733GH/overview
OpenHarmony 开发环境搭建
《OpenHarmony源码解析》:https://gitcode.com/HarmonyOS_MN/733GH/overview
- 搭建开发环境
- Windows 开发环境的搭建
- Ubuntu 开发环境搭建
- Linux 与 Windows 之间的文件共享
- ……
- 系统架构分析
- 构建子系统
- 启动流程
- 子系统
- 分布式任务调度子系统
- 分布式通信子系统
- 驱动子系统
- ……