import { ToolsHelper } from '../../utils/ToolsHelper' import { inspector } from '@kit.ArkUI' import { RefreshController } from './RefreshController' @Component export struct RefreshView { @Link isLoading: boolean @Prop @Watch('change') data: Array @Require keyGenerator?: (item: ESObject, index: number) => string //是否自动调用`onRefresh`方法,默认为`true`,加载组件会自动调用一次`onRefresh` init: boolean = true // 第一次加载完成,是否定位到底部,默认`false`,定位到顶部 positioningToBottom: boolean = false pageSize: number = 10 onLoadMore?: (pageNum: number) => void onRefresh?: () => void controller: RefreshController | null = null private startY: number = 0 private endY: number = 0 private lastNum: number = 0 private _openMore: boolean = false private _oTime: number = 0 private _listener: inspector.ComponentObserver = inspector.createComponentObserver('Refresh_View_List'); private _scroller: Scroller = new Scroller() private onDrawComplete = () => { this._isLoad = false this.isLoading = false if (!this._firstFinish && this.positioningToBottom) { this._firstFinish = true this.toBottom() } else { if (this._toTop) { this.toTop() this._toTop = false } else if (this._toBottom) { this.toBottom() this._toBottom = false } else if (this._toIndex) { this.toIndex() this._toIndex = false } } }; private _firstFinish = false private _isLoad = false private _toTop = false private _toIndex = false private _toBottom = false change() { this._isLoad = true } aboutToAppear(): void { if (this.init) { this.onRefresh && this.onRefresh() } if (this.controller) { this.controller.toTop = (smooth?: boolean) => { this.toTop(smooth) } this.controller.toBottom = (smooth?: boolean) => { this.toBottom(smooth) } this.controller.toIndex = (value: number, smooth?: boolean, align?: ScrollAlign) => { this.toIndex(value, smooth, align) } this.controller.isAtEnd = () => this._scroller.isAtEnd() } this._listener.on('draw', this.onDrawComplete) } @State value: number = -1 @State smooth?: boolean = false @State aligns?: ScrollAlign = undefined toIndex(value?: number, smooth?: boolean, align?: ScrollAlign) { if (!this._isLoad) { if (value || this.value != -1 || value === 0) { this._scroller.scrollToIndex(value ?? this.value, smooth, align) } } else { this.value = value ?? this.value this.smooth = smooth this.aligns = align this._toIndex = true } } toTop(smooth?: boolean) { if (!this._isLoad) { this._scroller.scrollToIndex(0, smooth, ScrollAlign.START) } else { this._toTop = true } } toBottom(smooth?: boolean) { if (!this._isLoad) { this._scroller.scrollToIndex(this.data.length, smooth, ScrollAlign.END) } else { this._toBottom = true } } aboutToDisappear(): void { this._listener.off('draw', this.onDrawComplete); } @Builder doNothingBuilder() { }; // 使用父组件@Builder装饰的方法初始化子组件@BuilderParam @BuilderParam customBuilderParam: (item: ESObject, index: number) => void @BuilderParam headerBuilderParam: () => void = this.doNothingBuilder; @BuilderParam footerBuilderParam: () => void = this.doNothingBuilder; build() { Refresh({ refreshing: $$this.isLoading }) { if (this.data && this.data.length > 0) { List({ scroller: this._scroller, }) { ListItem() { this.headerBuilderParam() } ForEach(this.data ?? [], (item: ESObject, index: number) => { ListItem() { this.customBuilderParam(item, index) } }, (item: ESObject, index: number) => this.keyGenerator!(item, index)) ListItem() { this.footerBuilderParam() } } .onTouch((event: TouchEvent) => { const e1 = event.touches[0] switch (event.type) { case TouchType.Down: this._openMore = this.data && this.lastNum >= this.data.length && !this.isLoading this.startY = e1.y break case TouchType.Up: this.endY = e1.y if (this.endY - this.startY < -100 && this._openMore) { const v = this.data && (this.data.length % this.pageSize) === 0 if (v) { const cTime = new Date().getTime() // 2024.11.21 测试觉得刷新太多了,暂时改为1秒5间隔 if (cTime - this._oTime > 1500) { this.onLoadMore && this.onLoadMore(Math.floor(this.data.length / this.pageSize)) this._oTime = cTime } } else { this.onLoadMore && ToolsHelper.showMessage('没有更多数据了') } } break } }) .onScrollIndex((first: number, last: number) => { this.lastNum = last + 1 }) .id('Refresh_View_List') .width('100%') .height('100%') .alignListItem(ListItemAlign.Center) .scrollBar(BarState.Off) } else { Text('暂无数据') .width('100%') .height('100%') .textAlign(TextAlign.Center) } } .width('100%') .layoutWeight(1) .onStateChange((refreshStatus: RefreshStatus) => { // ToolsHelper.log('Refresh onStatueChange state is ' + refreshStatus) }) .onRefreshing(() => { this.onRefresh && this.onRefresh() }) } }