下拉刷新是一个高频使用的功能,ArkUI 开发框架也提供了下拉刷新组件 Refresh,该组件的使用非常简单,读者可参阅笔者在《ArkUI实战》第六章 第 5 小节 的介绍,本文笔者讲解一下笔者在项目上实现的一个下拉刷新组件 RefreshList,该组件的运行效果如下图所示:
- 布局拆分
下拉刷新组件都是分为上下两部分,上边是刷新头:refreshHead,该刷新头根据手指的下滑距离提示是否达到刷新条件;下边是刷新体:refreshContent,当触发下拉刷新条件后对外回调,从而实现内容更新。笔者实现的 RefreshList 也是按照以上布局实现的,简化图如下所示:
默认情况下 refreshHead 是布局在 RefreshList 可视区域外边,笔者在第三章 第 1 小节 讲解过可以使用 position() 方法实现布局定位,简化代码如下所示:
@Component struct RefreshList {
build() {
Column() {
Row() {
// header布局
}
.id("refresh_header")
.width("100%")
.height(50)
.position({
// 利用该属性,把refresh_header布局在 Column 顶部
x: 0,
y: -50
})
Column() {
// content 布局
}
.id("refresh_content")
.width("100%")
.height("100%")
.position({
// 利用该属性,把refresh_content布局向上做偏移
x: 0,
y: 0
})
}
.id("refresh_list")
.width("100%")
.height("100%")
}
}
- 滑动处理
ArkUI 开发框架对于手势事件的处理遵循 W3C 标准,首先是目标捕获阶段,然后再是事件冒泡阶段,下拉刷新的操作就是在事件冒泡阶段处理的,因此直接实现 refresh_list 的 onTouch() 方法即可,在该方法内根据手指的滑动距离动态实现 refreshHeader 和 refreshContent 的布局定位即可,简化代码如下所示:
@Component struct RefreshList {
private refreshHeaderHeight: number = 50;
private offsetY: number = -this.refreshHeaderHeight;
private lastX: number;
private lastY: number;
private downY: number;
build() {
Column() {
Row()
.id("refresh_header")
.width("100%")
.height(this.refreshHeaderHeight)
.backgroundColor("#bbaacc")
.position({
x: 0,
y: this.offsetY
})
Column() {
}
.id("refresh_content")
.width("100%")
.height("100%")
.backgroundColor("#aabbcc")
.position({
x: 0,
y: this.offsetY + this.refreshHeaderHeight
})
}
.id("refresh_list")
.width("100%")
.height("100%")
.onTouch((event) => {
if (event.type == TouchType.Down) {
// 处理 down 事件
this.onTouchDown(event);
} else if (event.type == TouchType.Move) {
// 处理 move 事件
this.onTouchMove(event);
} else if (event.type == TouchType.Cancel || event.type == TouchType.Up) {
// 处理 up 事件
this.onTouchUp(event);
}
})
}
private onTouchDown(event: TouchEvent) {
this.lastX = event.touches[0].screenX;
this.lastY = event.touches[0].screenY;
this.downY = this.lastY;
}
private onTouchMove(event: TouchEvent) {
let currentX = event.touches[0].screenX;
let currentY = event.touches[0].screenY;
let deltaX = currentX - this.lastX;
let deltaY = currentY - this.lastY;
if (Math.abs(deltaX) < Math.abs(deltaY) && Math.abs(deltaY) > 5) {
// 达到滑动条件
}
}
private onTouchUp(event: TouchEvent) {
}
}