# Refresh å¯ä»¥è¿›è¡Œé¡µé¢ä¸‹æ‹‰æ“作并显示刷新动效的容器组件。 > **说明:** > > - 该组件从API Version 8开始支æŒã€‚åŽç»ç‰ˆæœ¬å¦‚æœ‰æ–°å¢žå†…å®¹ï¼Œåˆ™é‡‡ç”¨ä¸Šè§’æ ‡å•ç‹¬æ ‡è®°è¯¥å†…容的起始版本。 > > - 该组件从API Version 12开始支æŒä¸Žåž‚直滚动的Swiperå’ŒWebçš„è”动。当Swiper设置loop属性为true时,Refreshæ— æ³•å’ŒSwiper产生è”动。 ## å组件 支æŒå•ä¸ªå组件。 从API version 11开始,Refreshå组件会跟éšæ‰‹åŠ¿ä¸‹æ‹‰è€Œä¸‹ç§»ã€‚ ## æŽ¥å£ Refresh(value: RefreshOptions) **原å化æœåŠ¡API:** 从API version 11开始,该接å£æ”¯æŒåœ¨åŽŸå化æœåŠ¡ä¸ä½¿ç”¨ã€‚ **系统能力:** SystemCapability.ArkUI.ArkUI.Full **å‚数:** | å‚æ•°å | 类型 | å¿…å¡« | 说明 | | -------- | -------- | -------- | -------- | | value | [RefreshOptions](#refreshoptions对象说明)| 是 | 刷新组件å‚数。 | ## RefreshOptions对象说明 **系统能力:** SystemCapability.ArkUI.ArkUI.Full | å称 | 类型 | å¿…å¡« | 说明 | | ---------- | ---------------------------------------- | ---- | ---------------------------------------- | | refreshing | boolean | 是 | 组件当å‰æ˜¯å¦å¤„于刷新ä¸çŠ¶æ€ã€‚true表示处于刷新ä¸çŠ¶æ€ï¼Œfalse表示未处于刷新ä¸çŠ¶æ€ã€‚<br/>默认值:false<br/>该å‚数支æŒ[$$](../../../quick-start/arkts-two-way-sync.md)åŒå‘绑定å˜é‡ã€‚ <br/>**原å化æœåŠ¡API:** 从API version 11开始,该接å£æ”¯æŒåœ¨åŽŸå化æœåŠ¡ä¸ä½¿ç”¨ã€‚| | offset<sup>(deprecated)</sup> | number \| string | å¦ | 下拉起点è·ç¦»ç»„件顶部的è·ç¦»ã€‚<br/>默认值:16,å•ä½vp <br/>从API version 11å¼€å§‹åºŸå¼ƒï¼Œæ— æ›¿ä»£æŽ¥å£<br/>**说明:**<br/>offsetå–值范围[0vp,64vp]。大于64vp按照64vp处ç†ã€‚ä¸æ”¯æŒç™¾åˆ†æ¯”,ä¸æ”¯æŒè´Ÿæ•° 。| | friction<sup>(deprecated)</sup> | number \| string | å¦ | 下拉摩擦系数,å–值范围为0到100。<br/>默认值:62<br/>- 0表示下拉刷新容器ä¸è·Ÿéšæ‰‹åŠ¿ä¸‹æ‹‰è€Œä¸‹æ‹‰ã€‚<br/>- 100表示下拉刷新容器紧紧跟éšæ‰‹åŠ¿ä¸‹æ‹‰è€Œä¸‹æ‹‰ã€‚<br/>- 数值越大,下拉刷新容器跟éšæ‰‹åŠ¿ä¸‹æ‹‰çš„å应越çµæ•ã€‚<br/>从API version 11开始废弃,从API version 12开始,å¯ç”¨[pullDownRatio](#pulldownratio12)属性替代。 | | builder<sup>10+</sup> | [CustomBuilder](ts-types.md#custombuilder8) | å¦ | 自定义刷新区域显示内容。<br/>**说明:**<br/>API version 10åŠä¹‹å‰ç‰ˆæœ¬ï¼Œè‡ªå®šä¹‰ç»„件的高度é™åˆ¶åœ¨64vp之内。API version 11åŠä»¥åŽç‰ˆæœ¬æ²¡æœ‰æ¤é™åˆ¶ã€‚ <br/>自定义组件设置了固定高度时,自定义组件会以固定高度显示在刷新区域下方;自定义组件未设置高度时,自定义组件高度会自适应刷新区域高度,会å‘生自定义组件高度跟éšåˆ·æ–°åŒºåŸŸå˜åŒ–至0的现象。建议对自定义组件设置最å°é«˜åº¦çº¦æŸæ¥é¿å…自定义组件高度å°äºŽé¢„期的情况å‘生,具体å¯å‚ç…§[示例3](#示例3自定义刷新区域显示内容-builder)。 <br/>从API version 12开始,建议使用refreshingContentå‚数替代builderå‚数自定义刷新区域显示内容,以é¿å…刷新过程ä¸å› 自定义组件销æ¯é‡å»ºé€ æˆçš„动画ä¸æ–问题。<br/>**原å化æœåŠ¡API:** 从API version 11开始,该接å£æ”¯æŒåœ¨åŽŸå化æœåŠ¡ä¸ä½¿ç”¨ã€‚| | promptText<sup>12+</sup> | [ResourceStr](ts-types.md#resourcestr) | å¦ | 设置刷新区域底部显示的自定义文本。<br/>**说明:**<br/>输入文本的é™åˆ¶å‚考Text组件,使用builder或refreshingContentå‚数自定义刷新区域显示内容时,promptTextä¸æ˜¾ç¤ºã€‚<br/>promptText设置有效时,[refreshOffset](#refreshoffset12)属性默认值为96vp。<br/>自定义文本最大的å—体缩放å€æ•°[maxFontScale](ts-basic-components-text.md#maxfontscale12)为2。<br/>**原å化æœåŠ¡API:** 从API version 12开始,该接å£æ”¯æŒåœ¨åŽŸå化æœåŠ¡ä¸ä½¿ç”¨ã€‚| | refreshingContent<sup>12+</sup> | [ComponentContent](../js-apis-arkui-ComponentContent.md) | å¦ | 自定义刷新区域显示内容。<br/>**说明:**<br/>与builderå‚æ•°åŒæ—¶è®¾ç½®æ—¶builderå‚æ•°ä¸ç”Ÿæ•ˆã€‚<br/>自定义组件设置了固定高度时,自定义组件会以固定高度显示在刷新区域下方;自定义组件未设置高度时,自定义组件高度会自适应刷新区域高度,会å‘生自定义组件高度跟éšåˆ·æ–°åŒºåŸŸå˜åŒ–至0的现象。建议对自定义组件设置最å°é«˜åº¦çº¦æŸæ¥é¿å…自定义组件高度å°äºŽé¢„期的情况å‘生,具体å¯å‚ç…§[示例4](#示例4自定义刷新区域显示内容-refreshingcontent)。 <br/>**原å化æœåŠ¡API:** 从API version 12开始,该接å£æ”¯æŒåœ¨åŽŸå化æœåŠ¡ä¸ä½¿ç”¨ã€‚| > **补充说明:** > - 当未设置builder或refreshingContent时,是通过更新å组件的[translate](ts-universal-attributes-transformation.md#translate)属性实现的下拉ä½ç§»æ•ˆæžœï¼Œä¸‹æ‹‰ä½ç§»è¿‡ç¨‹ä¸ä¸ä¼šè§¦å‘å组件的[onAreaChange](ts-universal-component-area-change-event.md#onareachange)事件,å组件设置[translate](ts-universal-attributes-transformation.md#translate)属性时ä¸ä¼šç”Ÿæ•ˆã€‚ > - 当设置了builder或refreshingContent时,是通过更新å组件相对于Refresh组件的ä½ç½®å®žçŽ°çš„下拉ä½ç§»æ•ˆæžœï¼Œä¸‹æ‹‰ä½ç§»è¿‡ç¨‹ä¸å¯ä»¥è§¦å‘å组件的[onAreaChange](ts-universal-component-area-change-event.md#onareachange)事件,å组件设置[position](ts-universal-attributes-location.md#position)属性时会固定å组件相对于Refresh组件的ä½ç½®å¯¼è‡´å组件ä¸ä¼šè·Ÿæ‰‹è¿›è¡Œä¸‹æ‹‰ä½ç§»ã€‚ ## 属性 支æŒ[通用属性](ts-universal-attributes-size.md)外,还支æŒä»¥ä¸‹å±žæ€§ï¼š ### refreshOffset<sup>12+</sup> refreshOffset(value: number) 设置触å‘刷新的下拉å移é‡ï¼Œå½“下拉è·ç¦»å°äºŽè¯¥å±žæ€§è®¾ç½®å€¼æ—¶ç¦»æ‰‹ä¸ä¼šè§¦å‘刷新。 **原å化æœåŠ¡API:** 从API version 12开始,该接å£æ”¯æŒåœ¨åŽŸå化æœåŠ¡ä¸ä½¿ç”¨ã€‚ **系统能力:** SystemCapability.ArkUI.ArkUI.Full **å‚数:** | å‚æ•°å | 类型 | å¿…å¡« | 说明 | | ------ | ------------------------------------------- | ---- | ---------------------------------------------------------- | | value | number | 是 | 下拉å移é‡ï¼Œå•ä½vp。<br/>默认值:未设置[promptText](#refreshoptions对象说明)å‚数时为64vp,设置了[promptText](#refreshoptions对象说明)å‚数时为96vp。 <br/>如果å–值为0或负数的时候æ¤æŽ¥å£é‡‡ç”¨é»˜è®¤å€¼ã€‚| ### pullToRefresh<sup>12+</sup> pullToRefresh(value: boolean) 设置当下拉è·ç¦»è¶…过[refreshOffset](#refreshoffset12)时是å¦èƒ½è§¦å‘刷新。 **原å化æœåŠ¡API:** 从API version 12开始,该接å£æ”¯æŒåœ¨åŽŸå化æœåŠ¡ä¸ä½¿ç”¨ã€‚ **系统能力:** SystemCapability.ArkUI.ArkUI.Full **å‚数:** | å‚æ•°å | 类型 | å¿…å¡« | 说明 | | ------ | ------------------------------------------- | ---- | ---------------------------------------------------------- | | value | boolean | 是 | 当下拉è·ç¦»è¶…过[refreshOffset](#refreshoffset12)时是å¦èƒ½è§¦å‘刷新。true表示能触å‘刷新,false表示ä¸èƒ½è§¦å‘刷新。<br/>默认值:true | ### pullDownRatio<sup>12+</sup> pullDownRatio(ratio: [Optional](ts-universal-attributes-custom-property.md#optional12)\<number>) 设置下拉跟手系数。 **原å化æœåŠ¡API:** 从API version 12开始,该接å£æ”¯æŒåœ¨åŽŸå化æœåŠ¡ä¸ä½¿ç”¨ã€‚ **系统能力:** SystemCapability.ArkUI.ArkUI.Full **å‚数:** | å‚æ•°å | 类型 | å¿…å¡« | 说明 | | ------ | ------------------------------------------- | ---- | ---------------------------------------------------------- | | ratio | [Optional](ts-universal-attributes-custom-property.md#optional12)\<number> | 是 | 下拉跟手系数。数值越大,跟éšæ‰‹åŠ¿ä¸‹æ‹‰çš„å应越çµæ•ã€‚0表示ä¸è·Ÿéšæ‰‹åŠ¿ä¸‹æ‹‰ï¼Œ1表示ç‰æ¯”例跟éšæ‰‹åŠ¿ä¸‹æ‹‰ã€‚<br/>没有设置或设置为undefined时,默认使用动æ€ä¸‹æ‹‰è·Ÿæ‰‹ç³»æ•°ï¼Œä¸‹æ‹‰è·ç¦»è¶Šå¤§ï¼Œè·Ÿæ‰‹ç³»æ•°è¶Šå°ã€‚<br/>有效值为0-1之间的值,å°äºŽ0的值会被视为0,大于1的值会被视为1。 ## 事件 除支æŒ[通用事件](ts-universal-events-click.md)外,还支æŒä»¥ä¸‹äº‹ä»¶ï¼š ### onStateChange onStateChange(callback: (state: RefreshStatus) => void) 当å‰åˆ·æ–°çŠ¶æ€å˜æ›´æ—¶ï¼Œè§¦å‘回调。 **原å化æœåŠ¡API:** 从API version 11开始,该接å£æ”¯æŒåœ¨åŽŸå化æœåŠ¡ä¸ä½¿ç”¨ã€‚ **系统能力:** SystemCapability.ArkUI.ArkUI.Full **å‚数:** | å‚æ•°å | 类型 | å¿…å¡« | 说明 | | ------ | --------------------------------------- | ---- | ---------- | | state | [RefreshStatus](#refreshstatus枚举说明) | 是 | 刷新状æ€ã€‚ | ### onRefreshing onRefreshing(callback: () => void) 进入刷新状æ€æ—¶è§¦å‘回调。 **原å化æœåŠ¡API:** 从API version 11开始,该接å£æ”¯æŒåœ¨åŽŸå化æœåŠ¡ä¸ä½¿ç”¨ã€‚ **系统能力:** SystemCapability.ArkUI.ArkUI.Full ### onOffsetChange<sup>12+</sup> onOffsetChange(callback: Callback\<number>) 下拉è·ç¦»å‘生å˜åŒ–时触å‘回调。 **原å化æœåŠ¡API:** 从API version 12开始,该接å£æ”¯æŒåœ¨åŽŸå化æœåŠ¡ä¸ä½¿ç”¨ã€‚ **系统能力:** SystemCapability.ArkUI.ArkUI.Full **å‚数:** | å‚æ•°å | 类型 | å¿…å¡« | 说明 | | ------ | --------------------------------------- | ---- | ---------- | | callback | Callback\<number> | 是 | 下拉è·ç¦»ã€‚<br/>å•ä½ï¼švp | ## RefreshStatus枚举说明 **原å化æœåŠ¡API:** 从API version 11开始,该接å£æ”¯æŒåœ¨åŽŸå化æœåŠ¡ä¸ä½¿ç”¨ã€‚ **系统能力:** SystemCapability.ArkUI.ArkUI.Full | å称 | 值 | 说明 | | -------- | -------- | -------------------- | | Inactive | 0 | 默认未下拉状æ€ã€‚ | | Drag | 1 | 下拉ä¸ï¼Œä¸‹æ‹‰è·ç¦»å°äºŽåˆ·æ–°è·ç¦»ã€‚ | | OverDrag | 2 | 下拉ä¸ï¼Œä¸‹æ‹‰è·ç¦»è¶…过刷新è·ç¦»ã€‚ | | Refresh | 3 | 下拉结æŸï¼Œå›žå¼¹è‡³åˆ·æ–°è·ç¦»ï¼Œè¿›å…¥åˆ·æ–°ä¸çŠ¶æ€ã€‚ | | Done | 4 | 刷新结æŸï¼Œè¿”回åˆå§‹çŠ¶æ€ï¼ˆé¡¶éƒ¨ï¼‰ã€‚ | ## 示例 ### 示例1ï¼ˆé»˜è®¤åˆ·æ–°æ ·å¼ï¼‰ åˆ·æ–°åŒºåŸŸä½¿ç”¨é»˜è®¤åˆ·æ–°æ ·å¼ã€‚ ```ts // xxx.ets @Entry @Component struct RefreshExample { @State isRefreshing: boolean = false @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] build() { Column() { Refresh({ refreshing: $$this.isRefreshing }) { List() { ForEach(this.arr, (item: string) => { ListItem() { Text('' + item) .width('70%') .height(80) .fontSize(16) .margin(10) .textAlign(TextAlign.Center) .borderRadius(10) .backgroundColor(0xFFFFFF) } }, (item: string) => item) } .onScrollIndex((first: number) => { console.info(first.toString()) }) .width('100%') .height('100%') .alignListItem(ListItemAlign.Center) .scrollBar(BarState.Off) } .onStateChange((refreshStatus: RefreshStatus) => { console.info('Refresh onStatueChange state is ' + refreshStatus) }) .onOffsetChange((value: number) => { console.info('Refresh onOffsetChange offset:' + value) }) .onRefreshing(() => { setTimeout(() => { this.isRefreshing = false }, 2000) console.log('onRefreshing test') }) .backgroundColor(0x89CFF0) .refreshOffset(64) .pullToRefresh(true) } } } ```  ### 示例2(设置刷新区域显示文本) 通过[promptText](#refreshoptions对象说明)å‚数设置刷新区域显示文本。 ```ts // xxx.ets @Entry @Component struct RefreshExample { @State isRefreshing: boolean = false @State promptText: string = "Refreshing..." @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] build() { Column() { Refresh({ refreshing: $$this.isRefreshing, promptText: this.promptText }) { List() { ForEach(this.arr, (item: string) => { ListItem() { Text('' + item) .width('70%') .height(80) .fontSize(16) .margin(10) .textAlign(TextAlign.Center) .borderRadius(10) .backgroundColor(0xFFFFFF) } }, (item: string) => item) } .onScrollIndex((first: number) => { console.info(first.toString()) }) .width('100%') .height('100%') .alignListItem(ListItemAlign.Center) .scrollBar(BarState.Off) } .backgroundColor(0x89CFF0) .pullToRefresh(true) .refreshOffset(96) .onStateChange((refreshStatus: RefreshStatus) => { console.info('Refresh onStatueChange state is ' + refreshStatus) }) .onOffsetChange((value: number) => { console.info('Refresh onOffsetChange offset:' + value) }) .onRefreshing(() => { setTimeout(() => { this.isRefreshing = false }, 2000) console.log('onRefreshing test') }) } } } ```  ### 示例3(自定义刷新区域显示内容-builder) 通过[builder](#refreshoptions对象说明)å‚数自定义刷新区域显示内容。 ```ts // xxx.ets @Entry @Component struct RefreshExample { @State isRefreshing: boolean = false @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] @Builder customRefreshComponent() { Stack() { Row() { LoadingProgress().height(32) Text("Refreshing...").fontSize(16).margin({ left: 20 }) } .alignItems(VerticalAlign.Center) } .align(Alignment.Center) .clip(true) // 设置最å°é«˜åº¦çº¦æŸä¿è¯è‡ªå®šä¹‰ç»„件高度éšåˆ·æ–°åŒºåŸŸé«˜åº¦å˜åŒ–时自定义组件高度ä¸ä¼šä½ŽäºŽminHeight .constraintSize({ minHeight: 32 }) .width("100%") } build() { Column() { Refresh({ refreshing: $$this.isRefreshing, builder: this.customRefreshComponent() }) { List() { ForEach(this.arr, (item: string) => { ListItem() { Text('' + item) .width('70%') .height(80) .fontSize(16) .margin(10) .textAlign(TextAlign.Center) .borderRadius(10) .backgroundColor(0xFFFFFF) } }, (item: string) => item) } .onScrollIndex((first: number) => { console.info(first.toString()) }) .width('100%') .height('100%') .alignListItem(ListItemAlign.Center) .scrollBar(BarState.Off) } .backgroundColor(0x89CFF0) .pullToRefresh(true) .refreshOffset(64) .onStateChange((refreshStatus: RefreshStatus) => { console.info('Refresh onStatueChange state is ' + refreshStatus) }) .onRefreshing(() => { setTimeout(() => { this.isRefreshing = false }, 2000) console.log('onRefreshing test') }) } } } ```  ### 示例4(自定义刷新区域显示内容-refreshingContent) 通过[refreshingContent](#refreshoptions对象说明)å‚数自定义刷新区域显示内容。 ```ts // xxx.ets import { ComponentContent } from '@ohos.arkui.node'; class Params { refreshStatus: RefreshStatus = RefreshStatus.Inactive constructor(refreshStatus: RefreshStatus) { this.refreshStatus = refreshStatus; } } @Builder function customRefreshingContent(params: Params) { Stack() { Row() { LoadingProgress().height(32) Text("refreshStatus: " + params.refreshStatus).fontSize(16).margin({ left: 20 }) } .alignItems(VerticalAlign.Center) } .align(Alignment.Center) .clip(true) // 设置最å°é«˜åº¦çº¦æŸä¿è¯è‡ªå®šä¹‰ç»„件高度éšåˆ·æ–°åŒºåŸŸé«˜åº¦å˜åŒ–时自定义组件高度ä¸ä¼šä½ŽäºŽminHeight .constraintSize({ minHeight: 32 }) .width("100%") } @Entry @Component struct RefreshExample { @State isRefreshing: boolean = false @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] @State refreshStatus: RefreshStatus = RefreshStatus.Inactive private contentNode?: ComponentContent<Object> = undefined private params: Params = new Params(RefreshStatus.Inactive) aboutToAppear(): void { let uiContext = this.getUIContext() this.contentNode = new ComponentContent(uiContext, wrapBuilder(customRefreshingContent), this.params) } build() { Column() { Refresh({ refreshing: $$this.isRefreshing, refreshingContent: this.contentNode }) { List() { ForEach(this.arr, (item: string) => { ListItem() { Text('' + item) .width('70%') .height(80) .fontSize(16) .margin(10) .textAlign(TextAlign.Center) .borderRadius(10) .backgroundColor(0xFFFFFF) } }, (item: string) => item) } .onScrollIndex((first: number) => { console.info(first.toString()) }) .width('100%') .height('100%') .alignListItem(ListItemAlign.Center) .scrollBar(BarState.Off) } .backgroundColor(0x89CFF0) .pullToRefresh(true) .refreshOffset(96) .onStateChange((refreshStatus: RefreshStatus) => { this.refreshStatus = refreshStatus this.params.refreshStatus = refreshStatus // 更新自定义组件内容 this.contentNode?.update(this.params) console.info('Refresh onStatueChange state is ' + refreshStatus) }) .onRefreshing(() => { setTimeout(() => { this.isRefreshing = false }, 2000) console.log('onRefreshing test') }) } } } ```  ### 示例5(实现最大下拉è·ç¦»ï¼‰ 通过[pullDownRatio](#pulldownratio12)属性和[onOffsetChange](#onoffsetchange12)事件实现最大下拉è·ç¦»ã€‚ ```ts // xxx.ets import { ComponentContent } from '@ohos.arkui.node'; @Builder function customRefreshingContent() { Stack() { Row() { LoadingProgress().height(32) } .alignItems(VerticalAlign.Center) } .align(Alignment.Center) .clip(true) // 设置最å°é«˜åº¦çº¦æŸä¿è¯è‡ªå®šä¹‰ç»„件高度éšåˆ·æ–°åŒºåŸŸé«˜åº¦å˜åŒ–时自定义组件高度ä¸ä¼šä½ŽäºŽminHeight .constraintSize({ minHeight: 32 }) .width("100%") } @Entry @Component struct RefreshExample { @State isRefreshing: boolean = false @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] @State maxRefreshingHeight: number = 100.0 @State ratio: number = 1 private contentNode?: ComponentContent<Object> = undefined aboutToAppear(): void { let uiContext = this.getUIContext(); this.contentNode = new ComponentContent(uiContext, wrapBuilder(customRefreshingContent)) } build() { Column() { Refresh({ refreshing: $$this.isRefreshing, refreshingContent: this.contentNode }) { List() { ForEach(this.arr, (item: string) => { ListItem() { Text('' + item) .width('70%') .height(80) .fontSize(16) .margin(10) .textAlign(TextAlign.Center) .borderRadius(10) .backgroundColor(0xFFFFFF) } }, (item: string) => item) } .onScrollIndex((first: number) => { console.info(first.toString()) }) .width('100%') .height('100%') .alignListItem(ListItemAlign.Center) .scrollBar(BarState.Off) } .backgroundColor(0x89CFF0) .pullDownRatio(this.ratio) .pullToRefresh(true) .refreshOffset(64) .onOffsetChange((offset: number) => { // 越接近最大è·ç¦»ï¼Œä¸‹æ‹‰è·Ÿæ‰‹ç³»æ•°è¶Šå° this.ratio = 1 - Math.pow((offset / this.maxRefreshingHeight), 3) }) .onStateChange((refreshStatus: RefreshStatus) => { console.info('Refresh onStatueChange state is ' + refreshStatus) }) .onRefreshing(() => { setTimeout(() => { this.isRefreshing = false }, 2000) console.log('onRefreshing test') }) } } } ```  ### 示例6ï¼ˆå®žçŽ°ä¸‹æ‹‰åˆ·æ–°ä¸Šæ‹‰åŠ è½½æ›´å¤šï¼‰ [Refresh](#refresh)组件与[List](ts-container-list.md)组件组åˆå®žçŽ°ä¸‹æ‹‰åˆ·æ–°ä¸Šæ‹‰åŠ 载更多效果。 ```ts // xxx.ets @Entry @Component struct ListRefreshLoad { @State arr: Array<number> = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; @State refreshing: boolean = false; @State refreshOffset: number = 0; @State refreshState: RefreshStatus = RefreshStatus.Inactive; @State canLoad: boolean = false; @State isLoading: boolean = false; @Builder refreshBuilder() { Stack({ alignContent: Alignment.Bottom }) { // å¯ä»¥é€šè¿‡åˆ·æ–°çŠ¶æ€æŽ§åˆ¶æ˜¯å¦å˜åœ¨Progress组件 // 当刷新状æ€å¤„于下拉ä¸æˆ–刷新ä¸çŠ¶æ€æ—¶Progress组件æ‰å˜åœ¨ if (this.refreshState != RefreshStatus.Inactive && this.refreshState != RefreshStatus.Done) { Progress({ value: this.refreshOffset, total: 64, type: ProgressType.Ring }) .width(32).height(32) .style({ status: this.refreshing ? ProgressStatus.LOADING : ProgressStatus.PROGRESSING }) .margin(10) } } .clip(true) .height("100%") .width("100%") } @Builder footer() { Row() { LoadingProgress().height(32).width(48) Text("åŠ è½½ä¸") }.width("100%") .height(64) .justifyContent(FlexAlign.Center) // 当ä¸å¤„äºŽåŠ è½½ä¸çŠ¶æ€æ—¶éšè—组件 .visibility(this.isLoading ? Visibility.Visible : Visibility.Hidden) } build() { Refresh({ refreshing: $$this.refreshing, builder: this.refreshBuilder() }) { List() { ForEach(this.arr, (item: number) => { ListItem() { Text('' + item) .width('100%') .height(80) .fontSize(16) .textAlign(TextAlign.Center) .backgroundColor(0xFFFFFF) }.borderWidth(1) }, (item: string) => item) ListItem() { this.footer(); } } .onScrollIndex((start: number, end: number) => { // 当达到列表末尾时,触å‘æ–°æ•°æ®åŠ è½½ if (this.canLoad && end >= this.arr.length - 1) { this.canLoad = false; this.isLoading = true; // 模拟新数æ®åŠ è½½ setTimeout(() => { for (let i = 0; i < 10; i++) { this.arr.push(this.arr.length); this.isLoading = false; } }, 700) } }) .onScrollFrameBegin((offset: number, state: ScrollState) => { // åªæœ‰å½“å‘上滑动时触å‘æ–°æ•°æ®åŠ è½½ if (offset > 5 && !this.isLoading) { this.canLoad = true; } return { offsetRemain: offset }; }) .scrollBar(BarState.Off) // å¼€å¯è¾¹ç¼˜æ»‘动效果 .edgeEffect(EdgeEffect.Spring, { alwaysEnabled: true }) } .width('100%') .height('100%') .backgroundColor(0xDCDCDC) .onOffsetChange((offset: number) => { this.refreshOffset = offset; }) .onStateChange((state: RefreshStatus) => { this.refreshState = state; }) .onRefreshing(() => { // 模拟数æ®åˆ·æ–° setTimeout(() => { this.refreshing = false; }, 2000) }) } } ``` 