| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- 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 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()
- })
- }
- }
|