diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ba1ec2..4050fd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # [v1.0.9] 2025.xx.xx > - `RefreshView`参数不包含`onLoadMore`的时候,上划不应该提示`没有更多数据了` +> - `RefreshView`添加一个`controller`,补充跳转到顶部,跳转到底部等方法,具体见文档`4.3`注释 > # [v1.0.8] 2025.03.11 diff --git a/Index.ets b/Index.ets index 9510a5c..954cc51 100644 --- a/Index.ets +++ b/Index.ets @@ -55,7 +55,7 @@ export { WindowHelper } from './src/main/ets/utils/WindowHelper' */ export { LoadingView } from './src/main/ets/view/LoadingView' export { SafeView } from './src/main/ets/view/SafeView' -export { RefreshView } from './src/main/ets/view/RefreshView' +export { RefreshView } from './src/main/ets/view/refresh/RefreshView' /** * 自定义view */ diff --git a/README.md b/README.md index a1a80ee..f1b3342 100644 --- a/README.md +++ b/README.md @@ -466,7 +466,7 @@ build() { } ``` -### 4.3.[RefreshView](./src/main/ets/view/RefreshView.ets) +### 4.3.[RefreshView](src/main/ets/view/refresh/RefreshView.ets) > 下拉刷新,上拉加载更多 @@ -487,18 +487,28 @@ build() { // ...... RefreshView({ isLoading: this.isLoading, - keyGenerator: (item: Item) => { - return item.id + // 是否自动调用`onRefresh`方法,默认为`true`,加载组件会自动调用一次`onRefresh` + init: false, + // 第一次加载完成,是否定位到底部,默认`false`,定位到顶部 + positioningToBottom: true, + // 控制器,提供跳转到顶部、跳转到底部、是否已经在最底部方法 + controller: this.msgController, + // 唯一标识,view的key + keyGenerator: () => { + return ToolsHelper.getUuid().toString() }, + // 每页请求的数据大小,根据这个参数判断是否可以上拉加载更多 pageSize: 10, data: this.list ?? [], // 这里要用箭头函数,否则buildItem里面的this指向不对 - customBuilderParam: (item: Item, index: number) => { - this.buildItem(item, index) + customBuilderParam: (item: ImMessage, index: number) => { + this.buildItem(item, index) }, + // 下拉刷新回调 onRefresh: () => { - this.refresh() + this.getHistory() }, + // 上拉加载更多回调 onLoadMore: (pageNum) => { this.refresh(pageNum) } diff --git a/src/main/ets/view/refresh/RefreshController.ets b/src/main/ets/view/refresh/RefreshController.ets new file mode 100644 index 0000000..9004980 --- /dev/null +++ b/src/main/ets/view/refresh/RefreshController.ets @@ -0,0 +1,5 @@ +export interface RefreshController { + toTop: (smooth?: boolean) => void + toBottom: (smooth?: boolean) => void + isAtEnd: () => boolean +} \ No newline at end of file diff --git a/src/main/ets/view/RefreshView.ets b/src/main/ets/view/refresh/RefreshView.ets similarity index 57% rename from src/main/ets/view/RefreshView.ets rename to src/main/ets/view/refresh/RefreshView.ets index 1ce4e0b..01d21fd 100644 --- a/src/main/ets/view/RefreshView.ets +++ b/src/main/ets/view/refresh/RefreshView.ets @@ -1,24 +1,86 @@ -import { ToolsHelper } from '../utils/ToolsHelper' +import { ToolsHelper } from '../../utils/ToolsHelper' +import { inspector } from '@kit.ArkUI' +import { RefreshController } from './RefreshController' @Component export struct RefreshView { @Link isLoading: boolean - @Prop data: Array + @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 + } + } + }; + private _firstFinish = false + private _isLoad = false + private _toTop = 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.isAtEnd = () => this._scroller.isAtEnd() + } + this._listener.on('draw', this.onDrawComplete) + } + + 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 - 1, smooth, ScrollAlign.END) + } else { + this._toBottom = true + } + } + + aboutToDisappear(): void { + this._listener.off('draw', this.onDrawComplete); } // 使用父组件@Builder装饰的方法初始化子组件@BuilderParam @@ -28,7 +90,9 @@ export struct RefreshView { Refresh({ refreshing: $$this.isLoading }) { if (this.data && this.data.length > 0) { - List() { + List({ + scroller: this._scroller, + }) { ForEach(this.data ?? [], (item: ESObject, index: number) => { ListItem() { this.customBuilderParam(item, index) @@ -63,6 +127,7 @@ export struct RefreshView { .onScrollIndex((first: number, last: number) => { this.lastNum = last + 1 }) + .id('Refresh_View_List') .width('100%') .height('100%') .alignListItem(ListItemAlign.Center)