2025-03-13 11:40:07 +08:00
|
|
|
import { ToolsHelper } from '../../utils/ToolsHelper'
|
|
|
|
|
import { inspector } from '@kit.ArkUI'
|
|
|
|
|
import { RefreshController } from './RefreshController'
|
2024-10-22 19:36:59 +08:00
|
|
|
|
|
|
|
|
@Component
|
|
|
|
|
export struct RefreshView {
|
2024-10-23 16:03:00 +08:00
|
|
|
@Link isLoading: boolean
|
2025-03-13 11:40:07 +08:00
|
|
|
@Prop @Watch('change') data: Array<ESObject>
|
2024-10-26 19:35:48 +08:00
|
|
|
@Require keyGenerator?: (item: ESObject, index: number) => string
|
2025-03-13 11:40:07 +08:00
|
|
|
//是否自动调用`onRefresh`方法,默认为`true`,加载组件会自动调用一次`onRefresh`
|
2024-11-28 11:32:38 +08:00
|
|
|
init: boolean = true
|
2025-03-13 11:40:07 +08:00
|
|
|
// 第一次加载完成,是否定位到底部,默认`false`,定位到顶部
|
|
|
|
|
positioningToBottom: boolean = false
|
2024-10-26 19:35:48 +08:00
|
|
|
pageSize: number = 10
|
|
|
|
|
onLoadMore?: (pageNum: number) => void
|
2024-10-23 16:03:00 +08:00
|
|
|
onRefresh?: () => void
|
2025-03-13 11:40:07 +08:00
|
|
|
controller: RefreshController | null = null
|
2024-10-23 16:03:00 +08:00
|
|
|
private startY: number = 0
|
|
|
|
|
private endY: number = 0
|
|
|
|
|
private lastNum: number = 0
|
|
|
|
|
private _openMore: boolean = false
|
2024-11-21 15:22:13 +08:00
|
|
|
private _oTime: number = 0
|
2025-03-13 11:40:07 +08:00
|
|
|
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
|
2025-03-17 16:47:21 +08:00
|
|
|
} else if (this._toIndex) {
|
|
|
|
|
this.toIndex()
|
|
|
|
|
this._toIndex = false
|
2025-03-13 11:40:07 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
private _firstFinish = false
|
|
|
|
|
private _isLoad = false
|
|
|
|
|
private _toTop = false
|
2025-03-17 16:47:21 +08:00
|
|
|
private _toIndex = false
|
2025-03-13 11:40:07 +08:00
|
|
|
private _toBottom = false
|
|
|
|
|
|
|
|
|
|
change() {
|
|
|
|
|
this._isLoad = true
|
|
|
|
|
}
|
2024-10-23 10:25:27 +08:00
|
|
|
|
|
|
|
|
aboutToAppear(): void {
|
2024-11-28 11:32:38 +08:00
|
|
|
if (this.init) {
|
|
|
|
|
this.onRefresh && this.onRefresh()
|
|
|
|
|
}
|
2025-03-13 11:40:07 +08:00
|
|
|
if (this.controller) {
|
|
|
|
|
this.controller.toTop = (smooth?: boolean) => {
|
|
|
|
|
this.toTop(smooth)
|
|
|
|
|
}
|
|
|
|
|
this.controller.toBottom = (smooth?: boolean) => {
|
|
|
|
|
this.toBottom(smooth)
|
|
|
|
|
}
|
2025-03-17 16:47:21 +08:00
|
|
|
this.controller.toIndex = (value: number, smooth?: boolean, align?: ScrollAlign) => {
|
|
|
|
|
this.toIndex(value, smooth, align)
|
|
|
|
|
}
|
2025-03-13 11:40:07 +08:00
|
|
|
this.controller.isAtEnd = () => this._scroller.isAtEnd()
|
|
|
|
|
}
|
|
|
|
|
this._listener.on('draw', this.onDrawComplete)
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-17 16:47:21 +08:00
|
|
|
@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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-13 11:40:07 +08:00
|
|
|
toTop(smooth?: boolean) {
|
|
|
|
|
if (!this._isLoad) {
|
|
|
|
|
this._scroller.scrollToIndex(0, smooth, ScrollAlign.START)
|
|
|
|
|
} else {
|
|
|
|
|
this._toTop = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
toBottom(smooth?: boolean) {
|
|
|
|
|
if (!this._isLoad) {
|
2025-03-17 16:47:21 +08:00
|
|
|
this._scroller.scrollToIndex(this.data.length, smooth, ScrollAlign.END)
|
2025-03-13 11:40:07 +08:00
|
|
|
} else {
|
|
|
|
|
this._toBottom = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aboutToDisappear(): void {
|
|
|
|
|
this._listener.off('draw', this.onDrawComplete);
|
2024-10-23 10:25:27 +08:00
|
|
|
}
|
2024-10-22 19:36:59 +08:00
|
|
|
|
2025-03-17 16:47:21 +08:00
|
|
|
@Builder
|
|
|
|
|
doNothingBuilder() {
|
|
|
|
|
};
|
|
|
|
|
|
2024-10-22 19:36:59 +08:00
|
|
|
// 使用父组件@Builder装饰的方法初始化子组件@BuilderParam
|
2024-10-23 16:03:00 +08:00
|
|
|
@BuilderParam customBuilderParam: (item: ESObject, index: number) => void
|
2025-03-17 16:47:21 +08:00
|
|
|
@BuilderParam headBuilderParam: () => void = this.doNothingBuilder;
|
2024-10-22 19:36:59 +08:00
|
|
|
|
|
|
|
|
build() {
|
|
|
|
|
|
|
|
|
|
Refresh({ refreshing: $$this.isLoading }) {
|
2024-10-23 16:03:00 +08:00
|
|
|
if (this.data && this.data.length > 0) {
|
2025-03-13 11:40:07 +08:00
|
|
|
List({
|
|
|
|
|
scroller: this._scroller,
|
|
|
|
|
}) {
|
2025-03-17 16:47:21 +08:00
|
|
|
ListItem() {
|
|
|
|
|
this.headBuilderParam()
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 16:03:00 +08:00
|
|
|
ForEach(this.data ?? [], (item: ESObject, index: number) => {
|
|
|
|
|
ListItem() {
|
|
|
|
|
this.customBuilderParam(item, index)
|
|
|
|
|
}
|
2024-10-26 19:35:48 +08:00
|
|
|
}, (item: ESObject, index: number) => this.keyGenerator!(item, index))
|
2024-10-23 16:03:00 +08:00
|
|
|
}
|
|
|
|
|
.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) {
|
2024-10-26 19:35:48 +08:00
|
|
|
const v = this.data && (this.data.length % this.pageSize) === 0
|
|
|
|
|
if (v) {
|
2024-11-21 15:22:13 +08:00
|
|
|
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
|
|
|
|
|
}
|
2024-10-26 19:35:48 +08:00
|
|
|
} else {
|
2025-03-12 18:28:54 +08:00
|
|
|
this.onLoadMore && ToolsHelper.showMessage('没有更多数据了')
|
2024-10-26 19:35:48 +08:00
|
|
|
}
|
2024-10-23 16:03:00 +08:00
|
|
|
}
|
|
|
|
|
break
|
2024-10-22 19:36:59 +08:00
|
|
|
}
|
2024-10-23 16:03:00 +08:00
|
|
|
})
|
|
|
|
|
.onScrollIndex((first: number, last: number) => {
|
2024-10-26 19:35:48 +08:00
|
|
|
this.lastNum = last + 1
|
2024-10-23 16:03:00 +08:00
|
|
|
})
|
2025-03-13 11:40:07 +08:00
|
|
|
.id('Refresh_View_List')
|
2024-10-23 16:03:00 +08:00
|
|
|
.width('100%')
|
|
|
|
|
.height('100%')
|
|
|
|
|
.alignListItem(ListItemAlign.Center)
|
|
|
|
|
.scrollBar(BarState.Off)
|
|
|
|
|
} else {
|
|
|
|
|
Text('暂无数据')
|
|
|
|
|
.width('100%')
|
|
|
|
|
.height('100%')
|
|
|
|
|
.textAlign(TextAlign.Center)
|
2024-10-26 19:35:48 +08:00
|
|
|
|
2024-10-22 19:36:59 +08:00
|
|
|
}
|
2024-10-23 16:03:00 +08:00
|
|
|
}
|
|
|
|
|
.width('100%')
|
2024-11-18 16:17:13 +08:00
|
|
|
.layoutWeight(1)
|
2024-10-22 19:36:59 +08:00
|
|
|
.onStateChange((refreshStatus: RefreshStatus) => {
|
2024-10-31 16:48:24 +08:00
|
|
|
// ToolsHelper.log('Refresh onStatueChange state is ' + refreshStatus)
|
2024-10-22 19:36:59 +08:00
|
|
|
})
|
|
|
|
|
.onRefreshing(() => {
|
2024-10-23 16:03:00 +08:00
|
|
|
this.onRefresh && this.onRefresh()
|
2024-10-22 19:36:59 +08:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|