diff --git a/PullToRefresh/src/main/ets/components/PullToRefresh/PullToRefresh.ets b/PullToRefresh/src/main/ets/components/PullToRefresh/PullToRefresh.ets index e085598c90d1ba6659c3a7e29d6542ee5b9b5754..d698d5d023046da27ae3e3a3058dd121105de001 100644 --- a/PullToRefresh/src/main/ets/components/PullToRefresh/PullToRefresh.ets +++ b/PullToRefresh/src/main/ets/components/PullToRefresh/PullToRefresh.ets @@ -25,8 +25,9 @@ const IS_LOADING = 5; @Component export struct PullToRefresh { - @BuilderParam customList: () => void; + @Link data: any; scroller: Scroller; + @BuilderParam customList: () => void; refreshConfigurator?: PullToRefreshConfigurator; mWidth?: Length = undefined; mHeight?: Length = undefined; @@ -84,7 +85,7 @@ export struct PullToRefresh { } } - initCanvas(): void { + private initCanvas(): void { if (this.refreshRingOx == 0) { this.canvasRefresh.strokeStyle = this.refreshConfigurator.getRefreshColor(); this.canvasRefresh.fillStyle = this.refreshConfigurator.getRefreshColor(); @@ -302,10 +303,10 @@ export struct PullToRefresh { if (this.value >= 1) { this.value -= 1; } else { - this.value += 0.01; + this.value += 10 / this.refreshConfigurator.getRefreshAnimDuration(); } - // 保留2位小数 - this.value = Math.round(this.value * 100) / 100; + // 保留3位小数 + this.value = Math.round(this.value * 1000) / 1000; // 刷新中动画采用系统组件,因此不用自己去执行动画 // 如果有刷新中动画回调,就执行刷新中动画回调 if (this.onAnimRefreshing) { @@ -313,14 +314,13 @@ export struct PullToRefresh { } }, 10); this.onRefresh().then((refreshText) => { - this.state = IS_REFRESHED; - clearInterval(this.timer); - if (!this.customRefresh) { - this.refreshText = refreshText; - } if (refreshText.length == 0) { this.closeRefresh(); } else { + this.state = IS_REFRESHED; + if (!this.customRefresh) { + this.refreshText = refreshText; + } setTimeout(() => { this.closeRefresh(); }, 1000); @@ -354,7 +354,6 @@ export struct PullToRefresh { } }, 10); this.onLoadMore().then((loadText) => { - clearInterval(this.timer); this.closeLoad(); }); } @@ -452,14 +451,18 @@ export struct PullToRefresh { } private closeRefresh(): void{ + clearInterval(this.timer); animateTo({ duration: this.refreshConfigurator.getAnimDuration() }, () => { this.trYTop = 0; }); - this.state = IS_FREE; - this.refreshText = ''; + setTimeout(() => { + this.state = IS_FREE; + this.refreshText = ''; + }, this.refreshConfigurator.getAnimDuration()); } private closeLoad(): void{ + clearInterval(this.timer); animateTo({ duration: this.refreshConfigurator.getAnimDuration() }, () => { this.trYBottom = 0; }); diff --git a/PullToRefresh/src/main/ets/components/PullToRefresh/PullToRefreshConfigurator.ets b/PullToRefresh/src/main/ets/components/PullToRefresh/PullToRefreshConfigurator.ets index d0bfdf42389ad64dc01343c7386050c4c3d6e08f..67932be424fa1ce15eb9b85a6d4b8ae7b3bbc106 100644 --- a/PullToRefresh/src/main/ets/components/PullToRefresh/PullToRefreshConfigurator.ets +++ b/PullToRefresh/src/main/ets/components/PullToRefresh/PullToRefreshConfigurator.ets @@ -24,6 +24,7 @@ export class PullToRefreshConfigurator { private refreshBackgroundColor?: ResourceColor = 'rgba(0,0,0,0)'; // 下拉动画区域背景色 private refreshTextColor?: ResourceColor = '#999999'; // 下拉加载完毕后提示文本的字体颜色 private refreshTextSize?: number | string | Resource = 18; // 下拉加载完毕后提示文本的字体大小 + private refreshAnimDuration?:number = 1000; // 下拉动画执行一次的时间 private loadImgHeight?: number = 30; // 上拉图片高度 private loadBackgroundColor?: ResourceColor = 'rgba(0,0,0,0)'; // 上拉动画区域背景色 private loadTextColor?: ResourceColor = '#999999'; // 上拉文本的字体颜色 @@ -135,6 +136,15 @@ export class PullToRefreshConfigurator { return this.refreshTextSize; } + setRefreshAnimDuration(refreshAnimDuration: number) { + this.refreshAnimDuration = refreshAnimDuration; + return this; + } + + getRefreshAnimDuration() { + return this.refreshAnimDuration; + } + setLoadImgHeight(loadImgHeight: number) { this.loadImgHeight = loadImgHeight; return this; diff --git a/entry/src/main/ets/pages/customConfig.ets b/entry/src/main/ets/pages/customConfig.ets index 2c188d78cfa30d0cf59a32418cf45b45122312f5..71b26b383b6c5d5642d07684e0c1151f18cb44c3 100644 --- a/entry/src/main/ets/pages/customConfig.ets +++ b/entry/src/main/ets/pages/customConfig.ets @@ -38,6 +38,7 @@ struct Index { .setRefreshBackgroundColor('#ffbbfaf5') // 下拉动画区域背景色 .setRefreshTextColor('red') // 下拉加载完毕后提示文本的字体颜色 .setRefreshTextSize(25) // 下拉加载完毕后提示文本的字体大小 + .setRefreshAnimDuration(1000) // 下拉动画执行一次的时间 .setLoadImgHeight(50) // 上拉图片高度 .setLoadBackgroundColor('#ffbbfaf5') // 上拉动画区域背景色 .setLoadTextColor('blue') // 上拉文本的字体颜色 @@ -50,12 +51,12 @@ struct Index { build() { Column() { PullToRefresh({ + // 必传项,列表组件所绑定的数据 + data: $data, // 必传项,需绑定传入主体布局内的列表或宫格组件 scroller: this.scroller, // 必传项,自定义主体布局,内部有列表或宫格组件 - customList: () => { - this.getListView(); - }, + customList: this.getListView, // 可选项,组件属性配置,具有默认值 refreshConfigurator: this.refreshConfigurator, // 可选项,容器宽,默认自适应 @@ -82,6 +83,8 @@ struct Index { }, 2000); }); }, + customLoad: null, + customRefresh: null, }) } .width('100%') diff --git a/entry/src/main/ets/pages/customRefreshAnim.ets b/entry/src/main/ets/pages/customRefreshAnim.ets index 75571d7ee984c7268f44cc71a09ff6586eeffac9..8a4afc270782cd7a01da52790ec679c5a9684ccc 100644 --- a/entry/src/main/ets/pages/customRefreshAnim.ets +++ b/entry/src/main/ets/pages/customRefreshAnim.ets @@ -12,7 +12,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { PullToRefresh } from '@ohos/pulltorefresh' +import { PullToRefresh, PullToRefreshConfigurator } from '@ohos/pulltorefresh' + +const pointSpace = 30; +const pointJitterAmplitude = 10; @Entry @Component @@ -21,20 +24,30 @@ struct Index { private dataNumbers: string[] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']; private dataStrings: string[] = ['我的评论', '与我相关', '个人中心1', '个人中心2', '个人中心3', '我的发布', '设置', '退出登录']; @State data: string[] = this.dataStrings; - @State isRefreshing: boolean = true; private scroller: Scroller = new Scroller(); + private refreshConfigurator?: PullToRefreshConfigurator = new PullToRefreshConfigurator(); private canvasSetting?: RenderingContextSettings = new RenderingContextSettings(true); private canvasRefresh?: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.canvasSetting); + private value1: number[] = []; + private value2: number[] = []; + + aboutToAppear() { + // 设置属性 + this.refreshConfigurator + .setRefreshAnimDuration(600) // 下拉动画执行一次的时间 + } build() { Column() { PullToRefresh({ + // 必传项,列表组件所绑定的数据 + data: $data, // 必传项,需绑定传入主体布局内的列表或宫格组件 scroller: this.scroller, // 必传项,自定义主体布局,内部有列表或宫格组件 - customList: () => { - this.getListView(); - }, + customList: this.getListView, + // 可选项,组件属性配置,具有默认值 + refreshConfigurator: this.refreshConfigurator, // 可选项,下拉刷新回调 onRefresh: () => { return new Promise((resolve, reject) => { @@ -61,37 +74,61 @@ struct Index { }, // 可选项,下拉中回调 onAnimPullDown: (value, width, height) => { - this.isRefreshing = false; - this.refreshText = '下拉中:' + value; + this.canvasRefresh.clearRect(0, 0, width, height); + if (value <= 0.33) { + this.drawPoint(width / 2, height / 2); + } else if (value <= 0.75) { + this.drawPoint(width / 2 - (pointSpace / 2 * (value - 0.33) / (0.75 - 0.33)), height / 2); + this.drawPoint(width / 2 + (pointSpace / 2 * (value - 0.33) / (0.75 - 0.33)), height / 2); + } else { + this.drawPoint(width / 2, height / 2); + this.drawPoint(width / 2 - pointSpace / 2 - (pointSpace / 2 * (value - 0.75) / (1 - 0.75)), height / 2); + this.drawPoint(width / 2 + pointSpace / 2 + (pointSpace / 2 * (value - 0.75) / (1 - 0.75)), height / 2); + } }, // 可选项,刷新中回调 onAnimRefreshing: (value, width, height) => { - this.isRefreshing = true; this.canvasRefresh.clearRect(0, 0, width, height); - this.canvasRefresh.fillRect(0, height * 3 / 4 / 2, width * value, height / 4); - } + // 将value值由0到1循环变化变为-1到1反复变化 + value = Math.abs(value * 2 - 1) * 2 - 1; + // 绘制第1个点 + this.drawPoint(width / 2 - pointSpace, height / 2 + pointJitterAmplitude * value); + // 绘制第2个点 + if (this.value1.length == 7) { + this.drawPoint(width / 2, height / 2 + pointJitterAmplitude * this.value1[0]); + this.value1 = this.value1.splice(1, this.value1.length); + } else { + this.drawPoint(width / 2, height / 2 + pointJitterAmplitude); + } + this.value1.push(value); + // 绘制第3个点 + if (this.value2.length == 14) { + this.drawPoint(width / 2 + pointSpace, height / 2 + pointJitterAmplitude * this.value2[0]); + this.value2 = this.value2.splice(1, this.value2.length); + } else { + this.drawPoint(width / 2 + pointSpace, height / 2 + pointJitterAmplitude); + } + this.value2.push(value); + }, + customLoad: null, }) } } + private drawPoint(x: number, y: number): void{ + this.canvasRefresh.beginPath(); + this.canvasRefresh.arc(x, y, 3, 0, Math.PI * 2); + this.canvasRefresh.fill(); + } + @Builder private customRefreshView() { - Stack() { - Text(this.refreshText) - .width('100%') - .height('100%') - .fontSize(16) - .fontColor('red') - .textAlign(TextAlign.Center) - .visibility(this.isRefreshing ? Visibility.Hidden : Visibility.Visible) - Canvas(this.canvasRefresh) - .width('100%') - .height('100%') - .onReady(() => { - this.canvasRefresh.fillStyle = '#7bff80'; - }) - .visibility(this.isRefreshing ? Visibility.Visible : Visibility.Hidden) - } + Canvas(this.canvasRefresh) + .width('100%') + .height('100%') + .onReady(() => { + this.canvasRefresh.fillStyle = 'red'; + }) } @Builder diff --git a/entry/src/main/ets/pages/quickStart.ets b/entry/src/main/ets/pages/quickStart.ets index fdfc52b12ac888f67b991d48a66e3cdfee4c59de..4d2f539e29dceb70dd93137e0548b55902057a13 100644 --- a/entry/src/main/ets/pages/quickStart.ets +++ b/entry/src/main/ets/pages/quickStart.ets @@ -27,13 +27,12 @@ struct Index { build() { Column() { PullToRefresh({ + // 必传项,列表组件所绑定的数据 + data: $data, // 必传项,需绑定传入主体布局内的列表或宫格组件 scroller: this.scroller, // 必传项,自定义主体布局,内部有列表或宫格组件 - customList: () => { - // 一个用@Builder修饰过的UI方法 - this.getListView(); - }, + customList: this.getListView, // 可选项,下拉刷新回调 onRefresh: () => { return new Promise((resolve, reject) => { @@ -54,6 +53,8 @@ struct Index { }, 2000); }); }, + customLoad: null, + customRefresh: null, }) } }