RefreshLoadLayout.ets
5.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import lottie, { AnimationItem } from '@ohos/lottie';
import { LoadStatus, RefreshLayoutBean } from './RefreshLayoutBean';
/**
* Custom layout to show refresh or load.
* TODO 待优化
*/
@Component
export default struct CustomLayout {
// 设置刷新view高度
static readonly REFRESH_HEIGHT: number = 90;
@ObjectLink @Watch('onOffsetChange') refreshBean: RefreshLayoutBean;
private mainRenderingSettings: RenderingContextSettings = new RenderingContextSettings(true)
private mainCanvasRenderingContext: CanvasRenderingContext2D =
new CanvasRenderingContext2D(this.mainRenderingSettings)
private mainRenderingSettings2: RenderingContextSettings = new RenderingContextSettings(true)
private mainCanvasRenderingContext2: CanvasRenderingContext2D =
new CanvasRenderingContext2D(this.mainRenderingSettings2)
private animateItem: AnimationItem | null = null;
private animateItem2: AnimationItem | null = null;
private animateName: string = "refresh";
private animateName2: string = "refreshing";
@State private layoutHeight: number = 0;
@State private textVisible: boolean = false
build() {
Stack({ alignContent: Alignment.Center }) {
Canvas(this.mainCanvasRenderingContext)
.width(60)
.height(60)
.backgroundColor(Color.Transparent)
.onReady(() => {
// 可在此生命回调周期中加载动画,可以保证动画尺寸正确
//抗锯齿的设置
this.mainCanvasRenderingContext.imageSmoothingEnabled = true;
this.mainCanvasRenderingContext.imageSmoothingQuality = 'medium'
})
.onDisAppear(() => {
lottie.destroy(this.animateName);
})
.visibility(this.refreshBean.loadStatus === LoadStatus.PRELOAD ? Visibility.Visible : Visibility.Hidden)
Canvas(this.mainCanvasRenderingContext2)
.width(60)
.height(60)
.backgroundColor(Color.Transparent)
.onReady(() => {
// 可在此生命回调周期中加载动画,可以保证动画尺寸正确
//抗锯齿的设置
this.mainCanvasRenderingContext2.imageSmoothingEnabled = true;
this.mainCanvasRenderingContext2.imageSmoothingQuality = 'medium'
})
.onDisAppear(() => {
lottie.destroy(this.animateName2);
})
.visibility(this.refreshBean.loadStatus === LoadStatus.LOADING ? Visibility.Visible : Visibility.Hidden)
Text('已更新至最新')
.fontSize(14)
.textAlign(TextAlign.Center)
.fontColor('#676767')
.backgroundColor('#f6f6f6')
.borderRadius(20)
.padding({
left: 19,
right: 19,
top: 10,
bottom: 10
})
.visibility(this.textVisible ? Visibility.Visible : Visibility.Hidden)
}
.clip(true)
.width('100%')
.height(this.layoutHeight)
}
animate1(offset: number) {
if (this.animateItem == null) {
this.animateItem = lottie.loadAnimation({
container: this.mainCanvasRenderingContext,
renderer: 'canvas', // canvas 渲染模式
loop: 1,
autoplay: true,
name: this.animateName,
path: "lottie/refresh_step1.json", // 路径加载动画只支持entry/src/main/ets 文件夹下的相对路径
})
this.animateItem.goToAndStop(1)
}
let total = CustomLayout.REFRESH_HEIGHT
let progress = offset * 100 / total
this.animateItem?.goToAndStop(this.getFramesByProgress(progress), true);
}
animate2() {
if (this.animateItem2 == null) {
this.animateItem2 = lottie.loadAnimation({
container: this.mainCanvasRenderingContext2,
renderer: 'canvas', // canvas 渲染模式
loop: 10,
autoplay: true,
name: this.animateName2,
path: "lottie/refresh_step2.json", // 路径加载动画只支持entry/src/main/ets 文件夹下的相对路径
})
}
}
getFramesByProgress(progress: number): number {
if (this.animateItem == null) {
return 1;
}
let progressTmp = progress
let total = this.animateItem.totalFrames;
let frame = Math.floor(total * progressTmp / 100);
if (frame >= total - 1) {
frame = total - 1
}
return frame;
}
onOffsetChange() {
if (!this.refreshBean.isVisible) {
return
}
if (this.refreshBean.loadStatus === LoadStatus.PRELOAD) {
// 下拉刷新
this.animate1(this.refreshBean.offset)
} else if (this.refreshBean.loadStatus == LoadStatus.LOADING) {
// 正在刷新
this.animate2()
} else {
// 刷新完成
lottie.destroy()
}
let maxH = CustomLayout.REFRESH_HEIGHT
let tmpHeight = this.refreshBean.offset > maxH ? maxH : this.refreshBean.offset
if (this.refreshBean.loadStatus === LoadStatus.LOADED) {
this.textVisible = true
if (tmpHeight <= 0) {
setTimeout(() => {
// 延时设置0,让“已更新到最新”展示
this.textVisible = false
this.setHeight0WithAnimation()
}, 800)
}
} else {
// 直接设置高度
this.layoutHeight = tmpHeight
}
}
/**
* 下拉刷新UI,高度慢慢变为0
*/
setHeight0WithAnimation() {
// this.layoutHeight = 0
animateTo({
duration: 500, // 动画时长
curve: Curve.Linear, // 动画曲线
iterations: 1, // 播放次数
playMode: PlayMode.Normal, // 动画模式
}, () => {
this.layoutHeight = 0
})
}
}