1# Refresh 2 3 The **Refresh** component is a container that provides the pull-to-refresh feature. 4 5> **NOTE** 6> 7> - This component is supported since API version 8. Updates will be marked with a superscript to indicate their earliest API version. 8> 9> - This component provides linkage with a vertical scrolling **Swiper** and **Web** component since API version 12. The linkage does not work if the **loop** attribute of **Swiper** is set to **true**. 10 11## Child Components 12 13This component supports only one child component. 14 15Since API version 11, this component's child component moves down with the pull-down gesture. 16 17## APIs 18 19Refresh(value: RefreshOptions) 20 21Creates a **Refresh** container. 22 23**Atomic service API**: This API can be used in atomic services since API version 11. 24 25**System capability**: SystemCapability.ArkUI.ArkUI.Full 26 27**Parameters** 28 29| Name| Type| Mandatory| Description| 30| -------- | -------- | -------- | -------- | 31| value | [RefreshOptions](#refreshoptions)| Yes| Parameters of the **Refresh** component.| 32 33## RefreshOptions 34 35Defines the options of the **Refresh** component. 36 37**System capability**: SystemCapability.ArkUI.ArkUI.Full 38 39| Name | Type | Mandatory | Description | 40| ---------- | ---------------------------------------- | ---- | ---------------------------------------- | 41| refreshing | boolean | Yes | Whether the component is being refreshed. The value **true** means that the component is being refreshed, and **false** means the opposite.<br>Default value: **false**<br>This parameter supports two-way binding through [$$](../../../ui/state-management/arkts-two-way-sync.md).<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 42| offset<sup>(deprecated)</sup> | number \| string | No | Distance from the pull-down starting point to the top of the component.<br>Default value: **16**.<br>Unit: vp.<br> If the type is string, the pixel unit must be explicitly specified, for example, **'10px'**; if the unit is not specified, for example, **'10'**, the default unit vp is used.<br>This API is deprecated since API version 11. No substitute API is provided.<br>**NOTE**<br>The value range of **offset** is [0vp, 64vp]. If the value is greater than 64 vp, the value 64 vp will be used. The value cannot be a percentage or a negative number.| 43| friction<sup>(deprecated)</sup> | number \| string | No | Coefficient of friction, which indicates the **<Refresh\>** component's sensitivity to the pull-down gesture. The value ranges from 0 to 100.<br>Default value: **62**<br>- **0** indicates that the **Refresh** component is not responsive to the pull-down gesture.<br>- **100** indicates that the **Refresh** component is highly responsive to the pull-down gesture.<br>- A larger value indicates higher responsiveness of the **Refresh** component to the pull-down gesture.<br>This API is deprecated since API version 11. You can use [pullDownRatio](#pulldownratio12) instead since API version 12.| 44| builder<sup>10+</sup> | [CustomBuilder](ts-types.md#custombuilder8) | No | Custom content in the refreshing area.<br>**NOTE**<br>In API version 10 and earlier versions, there is a height limit of 64 vp on custom components. This restriction is removed since API version 11.<br>When a custom component is set with a fixed height, it will be displayed below the refreshing area at that fixed height; when the custom component does not have a height set, its height will adapt to the height of the refreshing area, which may result in the height of the custom component changing to 0 along with the refreshing area. To maintain the intended layout, configure a minimum height constraint for a custom component, which ensures that the component's height does not fall below a certain threshold. For details about how to apply this constraint, see [Example 3](#example-3-customizing-the-refreshing-area-content-with-builder).<br>Since API version 12, use **refreshingContent** instead of **builder** for customizing the content of the refreshing area, to avoid animation interruptions caused by the destruction and re-creation of the custom component during the refreshing process.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 45| promptText<sup>12+</sup> | [ResourceStr](ts-types.md#resourcestr) | No| Custom text displayed at the bottom of the refreshing area.<br>**NOTE**<br>When setting the text, follow the constraints on the **Text** components. If you are using **builder** or **refreshingContent** to customize the content displayed in the refreshing area, the text set with **promptText** will not be displayed.<br>When **promptText** is set and effective, the [refreshOffset](#refreshoffset12) attribute defaults to 96 vp.<br>The maximum font scale factor for the custom text, as specified by [maxFontScale](ts-basic-components-text.md#maxfontscale12), is 2.<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 46| refreshingContent<sup>12+</sup> | [ComponentContent](../js-apis-arkui-ComponentContent.md) | No | Custom content in the refreshing area.<br>**NOTE**<br>If this parameter and the **builder** parameter are set at the same time, the **builder** parameter does not take effect.<br>When a custom component is set with a fixed height, it will be displayed below the refreshing area at that fixed height; when the custom component does not have a height set, its height will adapt to the height of the refreshing area, which may result in the height of the custom component changing to 0 along with the refreshing area. To maintain the intended layout, configure a minimum height constraint for a custom component, which ensures that the component's height does not fall below a certain threshold. For details about how to apply this constraint, see [Example 4](#example-4-customizing-the-refreshing-area-content-with-refreshingcontent).<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 47 48> **Supplementary Notes** 49> - If neither **builder** nor **refreshingContent** is set, the pull-down displacement effect is implemented by adjusting the [translate](ts-universal-attributes-transformation.md#translate) attribute of the child component. During the pull-down process, the [onAreaChange](ts-universal-component-area-change-event.md#onareachange) event of the child component is not triggered, and any changes made to the [translate](ts-universal-attributes-transformation.md#translate) attribute of the child component do not take effect. 50> - When **builder** or **refreshingContent** is set, the pull-down displacement effect is implemented by adjusting the position of the child component relative to the **Refresh** component. During the pull-down process, the [onAreaChange](ts-universal-component-area-change-event.md#onareachange) event of the child component can be triggered. However, if the [position](ts-universal-attributes-location.md#position) attribute is set for the child component, the position of the child component relative to the **Refresh** component is fixed, preventing the child component from moving down with the pull gesture. 51 52## Attributes 53 54In addition to the [universal attributes](ts-component-general-attributes.md), the following attributes are supported. 55 56### refreshOffset<sup>12+</sup> 57 58refreshOffset(value: number) 59 60Sets the minimum pull-down offset required to trigger a refresh. If the distance pulled down is less than the value specified by this attribute, releasing the gesture does not trigger a refresh. 61 62**Atomic service API**: This API can be used in atomic services since API version 12. 63 64**System capability**: SystemCapability.ArkUI.ArkUI.Full 65 66**Parameters** 67 68| Name| Type | Mandatory| Description | 69| ------ | ------------------------------------------- | ---- | ---------------------------------------------------------- | 70| value | number | Yes| Pull-down offset, in vp.<br>Default value: 96 vp when [promptText](#refreshoptions) is set and 64 vp when [promptText](#refreshoptions) is not set.<br>If the value specified is 0 or less than 0, the default value is used.| 71 72### pullToRefresh<sup>12+</sup> 73 74pullToRefresh(value: boolean) 75 76Sets whether to initiate a refresh when the pull-down distance exceeds the value of [refreshOffset](#refreshoffset12). 77 78**Atomic service API**: This API can be used in atomic services since API version 12. 79 80**System capability**: SystemCapability.ArkUI.ArkUI.Full 81 82**Parameters** 83 84| Name| Type | Mandatory| Description | 85| ------ | ------------------------------------------- | ---- | ---------------------------------------------------------- | 86| value | boolean | Yes| Whether to initiate a refresh when the pull-down distance exceeds the value of [refreshOffset](#refreshoffset12). The value **true** means to initiate a refresh, and **false** means the opposite.<br>Default value: **true**| 87 88### pullDownRatio<sup>12+</sup> 89 90pullDownRatio(ratio: [Optional](ts-universal-attributes-custom-property.md#optional12)\<number>) 91 92Sets the pull-down ratio. 93 94**Atomic service API**: This API can be used in atomic services since API version 12. 95 96**System capability**: SystemCapability.ArkUI.ArkUI.Full 97 98**Parameters** 99 100| Name| Type | Mandatory| Description | 101| ------ | ------------------------------------------- | ---- | ---------------------------------------------------------- | 102| ratio | [Optional](ts-universal-attributes-custom-property.md#optional12)\<number> | Yes| Pull-down ratio. A larger value indicates higher responsiveness to the pull-down gesture. The value **0** indicates that the pull-down does not follow the gesture, and **1** indicates that the pull-down follows the gesture proportionally.<br>If this parameter is not set or is set to **undefined**, a dynamic pull-down ratio is used. That is, the larger the pull-down distance, the smaller the ratio.<br>The value ranges from 0 to 1. A value less than 0 is handled as **0**, and a value greater than 1 is handled as **1**. 103 104### maxPullDownDistance<sup>20+</sup> 105 106maxPullDownDistance(distance: Optional\<number>) 107 108Sets the maximum pull-down distance. 109 110**Atomic service API**: This API can be used in atomic services since API version 20. 111 112**System capability**: SystemCapability.ArkUI.ArkUI.Full 113 114**Parameters** 115 116| Name| Type | Mandatory| Description | 117| ------ | ------------------------------------------- | ---- | ---------------------------------------------------------- | 118| distance | [Optional](ts-universal-attributes-custom-property.md#optional12)\<number> | Yes| Maximum pull-down distance. The minimum value for the maximum pull-down distance is 0. Values less than 0 are treated as **0**. If this value is less than the refresh offset (**refreshOffset**), the refresh action will not be triggered when the pull-down gesture is released.<br>If set to **undefined** or **null**, this parameter is considered not set.<br>Default value: **undefined**. 119 120## Events 121 122In addition to the [universal events](ts-component-general-events.md), the following events are supported. 123 124### onStateChange 125 126onStateChange(callback: (state: RefreshStatus) => void) 127 128Called when the refresh status changes. 129 130**Atomic service API**: This API can be used in atomic services since API version 11. 131 132**System capability**: SystemCapability.ArkUI.ArkUI.Full 133 134**Parameters** 135 136| Name| Type | Mandatory| Description | 137| ------ | --------------------------------------- | ---- | ---------- | 138| state | [RefreshStatus](#refreshstatus) | Yes | Refresh status.| 139 140### onRefreshing 141 142onRefreshing(callback: () => void) 143 144Called when the component starts refreshing. 145 146**Atomic service API**: This API can be used in atomic services since API version 11. 147 148**System capability**: SystemCapability.ArkUI.ArkUI.Full 149 150### onOffsetChange<sup>12+</sup> 151 152onOffsetChange(callback: Callback\<number>) 153 154Called when the pull-down distance changes. 155 156**Atomic service API**: This API can be used in atomic services since API version 12. 157 158**System capability**: SystemCapability.ArkUI.ArkUI.Full 159 160**Parameters** 161 162| Name| Type | Mandatory| Description | 163| ------ | --------------------------------------- | ---- | ---------- | 164| callback | Callback\<number> | Yes | Pull-down distance.<br>Unit: vp| 165 166 167## RefreshStatus 168 169Enumerates the states of a refresh operation. 170 171**Atomic service API**: This API can be used in atomic services since API version 11. 172 173**System capability**: SystemCapability.ArkUI.ArkUI.Full 174 175| Name | Value | Description | 176| -------- | -------- | -------------------- | 177| Inactive | 0 | The component is not pulled down. This is the default value. | 178| Drag | 1 | The component is being pulled down, but the pull-down distance is shorter than the minimum length required to trigger the refresh. | 179| OverDrag | 2 | The component is being pulled down, and the pull-down distance exceeds the minimum length required to trigger the refresh. | 180| Refresh | 3 | The pull-down ends, and the component rebounds to the minimum length required to trigger the refresh and enters the refreshing state.| 181| Done | 4 | The refresh is complete, and the component returns to the initial state (at the top). | 182 183 184## Example 185 186### Example 1: Using the Default Refreshing Style 187 188This example implements a **Refresh** component with its refreshing area in the default style. 189 190```ts 191// xxx.ets 192@Entry 193@Component 194struct RefreshExample { 195 @State isRefreshing: boolean = false; 196 @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']; 197 198 build() { 199 Column() { 200 Refresh({ refreshing: $$this.isRefreshing }) { 201 List() { 202 ForEach(this.arr, (item: string) => { 203 ListItem() { 204 Text('' + item) 205 .width('70%') 206 .height(80) 207 .fontSize(16) 208 .margin(10) 209 .textAlign(TextAlign.Center) 210 .borderRadius(10) 211 .backgroundColor(0xFFFFFF) 212 } 213 }, (item: string) => item) 214 } 215 .onScrollIndex((first: number) => { 216 console.info(first.toString()); 217 }) 218 .width('100%') 219 .height('100%') 220 .alignListItem(ListItemAlign.Center) 221 .scrollBar(BarState.Off) 222 } 223 .onStateChange((refreshStatus: RefreshStatus) => { 224 console.info('Refresh onStatueChange state is ' + refreshStatus); 225 }) 226 .onOffsetChange((value: number) => { 227 console.info('Refresh onOffsetChange offset:' + value); 228 }) 229 .onRefreshing(() => { 230 setTimeout(() => { 231 this.isRefreshing = false; 232 }, 2000) 233 console.log('onRefreshing test'); 234 }) 235 .backgroundColor(0x89CFF0) 236 .refreshOffset(64) 237 .pullToRefresh(true) 238 } 239 } 240} 241``` 242 243 244 245### Example 2: Setting the Text Displayed in the Refreshing Area 246 247This example shows how to set the text displayed in the refreshing area using the [promptText](#refreshoptions) parameter. 248 249```ts 250// xxx.ets 251@Entry 252@Component 253struct RefreshExample { 254 @State isRefreshing: boolean = false; 255 @State promptText: string = "Refreshing..."; 256 @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']; 257 258 build() { 259 Column() { 260 Refresh({ refreshing: $$this.isRefreshing, promptText: this.promptText }) { 261 List() { 262 ForEach(this.arr, (item: string) => { 263 ListItem() { 264 Text('' + item) 265 .width('70%') 266 .height(80) 267 .fontSize(16) 268 .margin(10) 269 .textAlign(TextAlign.Center) 270 .borderRadius(10) 271 .backgroundColor(0xFFFFFF) 272 } 273 }, (item: string) => item) 274 } 275 .onScrollIndex((first: number) => { 276 console.info(first.toString()); 277 }) 278 .width('100%') 279 .height('100%') 280 .alignListItem(ListItemAlign.Center) 281 .scrollBar(BarState.Off) 282 } 283 .backgroundColor(0x89CFF0) 284 .pullToRefresh(true) 285 .refreshOffset(96) 286 .onStateChange((refreshStatus: RefreshStatus) => { 287 console.info('Refresh onStatueChange state is ' + refreshStatus); 288 }) 289 .onOffsetChange((value: number) => { 290 console.info('Refresh onOffsetChange offset:' + value); 291 }) 292 .onRefreshing(() => { 293 setTimeout(() => { 294 this.isRefreshing = false; 295 }, 2000) 296 console.log('onRefreshing test'); 297 }) 298 } 299 } 300} 301``` 302 303 304 305### Example 3: Customizing the Refreshing Area Content with builder 306 307This example shows how to customize the content displayed in the refreshing area using the [builder](#refreshoptions) parameter. 308 309```ts 310// xxx.ets 311@Entry 312@Component 313struct RefreshExample { 314 @State isRefreshing: boolean = false; 315 @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']; 316 317 @Builder 318 customRefreshComponent() { 319 Stack() { 320 Row() { 321 LoadingProgress().height(32) 322 Text("Refreshing...").fontSize(16).margin({ left: 20 }) 323 } 324 .alignItems(VerticalAlign.Center) 325 } 326 .align(Alignment.Center) 327 .clip(true) 328 // Set a minimum height constraint to ensure that the height of the custom component does not fall below the specified minHeight when the height of the refreshing area changes. 329 .constraintSize({ minHeight: 32 }) 330 .width("100%") 331 } 332 333 build() { 334 Column() { 335 Refresh({ refreshing: $$this.isRefreshing, builder: this.customRefreshComponent() }) { 336 List() { 337 ForEach(this.arr, (item: string) => { 338 ListItem() { 339 Text('' + item) 340 .width('70%') 341 .height(80) 342 .fontSize(16) 343 .margin(10) 344 .textAlign(TextAlign.Center) 345 .borderRadius(10) 346 .backgroundColor(0xFFFFFF) 347 } 348 }, (item: string) => item) 349 } 350 .onScrollIndex((first: number) => { 351 console.info(first.toString()); 352 }) 353 .width('100%') 354 .height('100%') 355 .alignListItem(ListItemAlign.Center) 356 .scrollBar(BarState.Off) 357 } 358 .backgroundColor(0x89CFF0) 359 .pullToRefresh(true) 360 .refreshOffset(64) 361 .onStateChange((refreshStatus: RefreshStatus) => { 362 console.info('Refresh onStatueChange state is ' + refreshStatus); 363 }) 364 .onRefreshing(() => { 365 setTimeout(() => { 366 this.isRefreshing = false; 367 }, 2000) 368 console.log('onRefreshing test'); 369 }) 370 } 371 } 372} 373``` 374 375 376 377### Example 4: Customizing the Refreshing Area Content with refreshingContent 378 379This example shows how to customize the content displayed in the refreshing area using the [refreshingContent](#refreshoptions) parameter. 380 381```ts 382// xxx.ets 383import { ComponentContent } from '@ohos.arkui.node'; 384 385class Params { 386 refreshStatus: RefreshStatus = RefreshStatus.Inactive; 387 388 constructor(refreshStatus: RefreshStatus) { 389 this.refreshStatus = refreshStatus; 390 } 391} 392 393@Builder 394function customRefreshingContent(params: Params) { 395 Stack() { 396 Row() { 397 LoadingProgress().height(32) 398 Text("refreshStatus: " + params.refreshStatus).fontSize(16).margin({ left: 20 }) 399 } 400 .alignItems(VerticalAlign.Center) 401 } 402 .align(Alignment.Center) 403 .clip(true) 404 // Set a minimum height constraint to ensure that the height of the custom component does not fall below the specified minHeight when the height of the refreshing area changes. 405 .constraintSize({ minHeight: 32 }) 406 .width("100%") 407} 408 409@Entry 410@Component 411struct RefreshExample { 412 @State isRefreshing: boolean = false; 413 @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']; 414 @State refreshStatus: RefreshStatus = RefreshStatus.Inactive; 415 private contentNode?: ComponentContent<Object> = undefined; 416 private params: Params = new Params(RefreshStatus.Inactive); 417 418 aboutToAppear(): void { 419 let uiContext = this.getUIContext(); 420 this.contentNode = new ComponentContent(uiContext, wrapBuilder(customRefreshingContent), this.params); 421 } 422 423 build() { 424 Column() { 425 Refresh({ refreshing: $$this.isRefreshing, refreshingContent: this.contentNode }) { 426 List() { 427 ForEach(this.arr, (item: string) => { 428 ListItem() { 429 Text('' + item) 430 .width('70%') 431 .height(80) 432 .fontSize(16) 433 .margin(10) 434 .textAlign(TextAlign.Center) 435 .borderRadius(10) 436 .backgroundColor(0xFFFFFF) 437 } 438 }, (item: string) => item) 439 } 440 .onScrollIndex((first: number) => { 441 console.info(first.toString()); 442 }) 443 .width('100%') 444 .height('100%') 445 .alignListItem(ListItemAlign.Center) 446 .scrollBar(BarState.Off) 447 } 448 .backgroundColor(0x89CFF0) 449 .pullToRefresh(true) 450 .refreshOffset(96) 451 .onStateChange((refreshStatus: RefreshStatus) => { 452 this.refreshStatus = refreshStatus; 453 this.params.refreshStatus = refreshStatus; 454 // Update the content of the custom component. 455 this.contentNode?.update(this.params); 456 console.info('Refresh onStatueChange state is ' + refreshStatus); 457 }) 458 .onRefreshing(() => { 459 setTimeout(() => { 460 this.isRefreshing = false; 461 }, 2000) 462 console.log('onRefreshing test'); 463 }) 464 } 465 } 466} 467``` 468 469 470### Example 5: Implementing the Maximum Pull-down Distance 471 472This example shows how to use the [pullDownRatio](#pulldownratio12) attribute and the [onOffsetChange](#onoffsetchange12) event to implement the maximum pull-down distance. 473 474```ts 475// xxx.ets 476import { ComponentContent } from '@ohos.arkui.node'; 477 478@Builder 479function customRefreshingContent() { 480 Stack() { 481 Row() { 482 LoadingProgress().height(32) 483 } 484 .alignItems(VerticalAlign.Center) 485 } 486 .align(Alignment.Center) 487 .clip(true) 488 // Set a minimum height constraint to ensure that the height of the custom component does not fall below the specified minHeight when the height of the refreshing area changes. 489 .constraintSize({ minHeight: 32 }) 490 .width("100%") 491} 492 493@Entry 494@Component 495struct RefreshExample { 496 @State isRefreshing: boolean = false; 497 @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']; 498 @State maxRefreshingHeight: number = 100.0; 499 @State ratio: number = 1; 500 private contentNode?: ComponentContent<Object> = undefined; 501 502 aboutToAppear(): void { 503 let uiContext = this.getUIContext(); 504 this.contentNode = new ComponentContent(uiContext, wrapBuilder(customRefreshingContent)); 505 } 506 507 build() { 508 Column() { 509 Refresh({ refreshing: $$this.isRefreshing, refreshingContent: this.contentNode }) { 510 List() { 511 ForEach(this.arr, (item: string) => { 512 ListItem() { 513 Text('' + item) 514 .width('70%') 515 .height(80) 516 .fontSize(16) 517 .margin(10) 518 .textAlign(TextAlign.Center) 519 .borderRadius(10) 520 .backgroundColor(0xFFFFFF) 521 } 522 }, (item: string) => item) 523 } 524 .onScrollIndex((first: number) => { 525 console.info(first.toString()); 526 }) 527 .width('100%') 528 .height('100%') 529 .alignListItem(ListItemAlign.Center) 530 .scrollBar(BarState.Off) 531 } 532 .backgroundColor(0x89CFF0) 533 .pullDownRatio(this.ratio) 534 .pullToRefresh(true) 535 .refreshOffset(64) 536 .onOffsetChange((offset: number) => { 537 // The closer to the maximum distance, the smaller the pull-down ratio. 538 this.ratio = 1 - Math.pow((offset / this.maxRefreshingHeight), 3); 539 }) 540 .onStateChange((refreshStatus: RefreshStatus) => { 541 console.info('Refresh onStatueChange state is ' + refreshStatus); 542 }) 543 .onRefreshing(() => { 544 setTimeout(() => { 545 this.isRefreshing = false; 546 }, 2000) 547 console.log('onRefreshing test'); 548 }) 549 } 550 } 551} 552``` 553 554 555 556### Example 6: Implementing Pull-Down-to-Refresh and Pull-Up-to-Load-More 557 558This example demonstrates how to combine the [Refresh](#refresh) component with the [List](ts-container-list.md) component to implement pull-down-to-refresh and pull-up-to-load-more features. 559 560```ts 561// xxx.ets 562@Entry 563@Component 564struct ListRefreshLoad { 565 @State arr: Array<number> = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 566 @State refreshing: boolean = false; 567 @State refreshOffset: number = 0; 568 @State refreshState: RefreshStatus = RefreshStatus.Inactive; 569 @State isLoading: boolean = false; 570 571 @Builder 572 refreshBuilder() { 573 Stack({ alignContent: Alignment.Bottom }) { 574 // The Progress component is displayed based on the refresh state. 575 // It is only shown when the refresh state is Drag or Refresh. 576 if (this.refreshState != RefreshStatus.Inactive && this.refreshState != RefreshStatus.Done) { 577 Progress({ value: this.refreshOffset, total: 64, type: ProgressType.Ring }) 578 .width(32).height(32) 579 .style({ status: this.refreshing ? ProgressStatus.LOADING : ProgressStatus.PROGRESSING }) 580 .margin(10) 581 } 582 } 583 .clip(true) 584 .height("100%") 585 .width("100%") 586 } 587 588 @Builder 589 footer() { 590 Row() { 591 LoadingProgress().height(32).width(48) 592 Text("Loading") 593 }.width("100%") 594 .height(64) 595 .justifyContent(FlexAlign.Center) 596 // The component is hidden when not in the loading state. 597 .visibility(this.isLoading ? Visibility.Visible : Visibility.Hidden) 598 } 599 600 build() { 601 Refresh({ refreshing: $$this.refreshing, builder: this.refreshBuilder() }) { 602 List() { 603 ForEach(this.arr, (item: number) => { 604 ListItem() { 605 Text('' + item) 606 .width('100%') 607 .height(80) 608 .fontSize(16) 609 .textAlign(TextAlign.Center) 610 .backgroundColor(0xFFFFFF) 611 }.borderWidth(1) 612 }, (item: string) => item) 613 614 ListItem() { 615 this.footer(); 616 } 617 } 618 .onScrollIndex((start: number, end: number) => { 619 // Trigger new data loading when the end of the list is reached. 620 if (end >= this.arr.length - 1) { 621 this.isLoading = true; 622 // Simulate new data loading. 623 setTimeout(() => { 624 for (let i = 0; i < 10; i++) { 625 this.arr.push(this.arr.length); 626 this.isLoading = false; 627 } 628 }, 700) 629 } 630 }) 631 .scrollBar(BarState.Off) 632 // Enable the effect used when the scroll boundary is reached. 633 .edgeEffect(EdgeEffect.Spring, { alwaysEnabled: true }) 634 } 635 .width('100%') 636 .height('100%') 637 .backgroundColor(0xDCDCDC) 638 .onOffsetChange((offset: number) => { 639 this.refreshOffset = offset; 640 }) 641 .onStateChange((state: RefreshStatus) => { 642 this.refreshState = state; 643 }) 644 .onRefreshing(() => { 645 // Simulate data refreshing. 646 setTimeout(() => { 647 this.refreshing = false; 648 }, 2000) 649 }) 650 } 651} 652``` 653 654 655 656### Example 7: Setting the Maximum Pull-Down Distance 657 658This example demonstrates how to set the maximum pull-down distance using the [maxPullDownDistance](#maxpulldowndistance20) attribute. 659 660```ts 661// xxx.ets 662@Entry 663@Component 664struct RefreshExample { 665 @State isRefreshing: boolean = false 666 @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] 667 668 build() { 669 Column() { 670 Refresh({ refreshing: $$this.isRefreshing }) { 671 List() { 672 ForEach(this.arr, (item: string) => { 673 ListItem() { 674 Text('' + item) 675 .width('70%') 676 .height(80) 677 .fontSize(16) 678 .margin(10) 679 .textAlign(TextAlign.Center) 680 .borderRadius(10) 681 .backgroundColor(0xFFFFFF) 682 } 683 }, (item: string) => item) 684 } 685 .onScrollIndex((first: number) => { 686 console.info(first.toString()) 687 }) 688 .width('100%') 689 .height('100%') 690 .alignListItem(ListItemAlign.Center) 691 .scrollBar(BarState.Off) 692 } 693 .maxPullDownDistance(150) 694 .onStateChange((refreshStatus: RefreshStatus) => { 695 console.info('Refresh onStatueChange state is ' + refreshStatus) 696 }) 697 .onOffsetChange((value: number) => { 698 console.info('Refresh onOffsetChange offset:' + value) 699 }) 700 .onRefreshing(() => { 701 setTimeout(() => { 702 this.isRefreshing = false 703 }, 2000) 704 console.log('onRefreshing test') 705 }) 706 .backgroundColor(0x89CFF0) 707 .refreshOffset(64) 708 .pullToRefresh(true) 709 } 710 } 711} 712 713``` 714 715 716