HarmonyOSBaseLibs/src/main/ets/view/refresh/RefreshView.ets
2025-03-17 16:47:21 +08:00

185 行
5.5 KiB
Plaintext

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<ESObject>
@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 headBuilderParam: () => void = this.doNothingBuilder;
build() {
Refresh({ refreshing: $$this.isLoading }) {
if (this.data && this.data.length > 0) {
List({
scroller: this._scroller,
}) {
ListItem() {
this.headBuilderParam()
}
ForEach(this.data ?? [], (item: ESObject, index: number) => {
ListItem() {
this.customBuilderParam(item, index)
}
}, (item: ESObject, index: number) => this.keyGenerator!(item, index))
}
.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()
})
}
}