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 21**Atomic service API**: This API can be used in atomic services since API version 11. 22 23**System capability**: SystemCapability.ArkUI.ArkUI.Full 24 25**Parameters** 26 27| Name| Type| Mandatory| Description| 28| -------- | -------- | -------- | -------- | 29| value | [RefreshOptions](#refreshoptions)| Yes| Parameters of the **Refresh** component.| 30 31## RefreshOptions 32 33**System capability**: SystemCapability.ArkUI.ArkUI.Full 34 35| Name | Type | Mandatory | Description | 36| ---------- | ---------------------------------------- | ---- | ---------------------------------------- | 37| 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 [$$](../../../quick-start/arkts-two-way-sync.md) for two-way binding of variables.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 38| offset<sup>(deprecated)</sup> | number \| string | No | Distance from the pull-down starting point to the top of the component.<br>Default value: **16**, in vp<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.| 39| 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.| 40| 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.| 41| 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.| 42| 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.| 43 44> **Supplementary Notes** 45> - 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. 46> - 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. 47 48## Attributes 49 50In addition to the [universal attributes](ts-component-general-attributes.md), the following attributes are supported. 51 52### refreshOffset<sup>12+</sup> 53 54refreshOffset(value: number) 55 56Sets 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. 57 58**Atomic service API**: This API can be used in atomic services since API version 12. 59 60**System capability**: SystemCapability.ArkUI.ArkUI.Full 61 62**Parameters** 63 64| Name| Type | Mandatory| Description | 65| ------ | ------------------------------------------- | ---- | ---------------------------------------------------------- | 66| 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<br>If the value specified is 0 or less than 0, the default value is used.| 67 68### pullToRefresh<sup>12+</sup> 69 70pullToRefresh(value: boolean) 71 72Sets whether to initiate a refresh when the pull-down distance exceeds the value of [refreshOffset](#refreshoffset12). 73 74**Atomic service API**: This API can be used in atomic services since API version 12. 75 76**System capability**: SystemCapability.ArkUI.ArkUI.Full 77 78**Parameters** 79 80| Name| Type | Mandatory| Description | 81| ------ | ------------------------------------------- | ---- | ---------------------------------------------------------- | 82| 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**| 83 84### pullDownRatio<sup>12+</sup> 85 86pullDownRatio(ratio: [Optional](ts-universal-attributes-custom-property.md#optional12)\<number>) 87 88Sets the pull-down ratio. 89 90**Atomic service API**: This API can be used in atomic services since API version 12. 91 92**System capability**: SystemCapability.ArkUI.ArkUI.Full 93 94**Parameters** 95 96| Name| Type | Mandatory| Description | 97| ------ | ------------------------------------------- | ---- | ---------------------------------------------------------- | 98| 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**. 99 100## Events 101 102In addition to the [universal events](ts-component-general-events.md), the following events are supported. 103 104### onStateChange 105 106onStateChange(callback: (state: RefreshStatus) => void) 107 108Called when the refresh status changes. 109 110**Atomic service API**: This API can be used in atomic services since API version 11. 111 112**System capability**: SystemCapability.ArkUI.ArkUI.Full 113 114**Parameters** 115 116| Name| Type | Mandatory| Description | 117| ------ | --------------------------------------- | ---- | ---------- | 118| state | [RefreshStatus](#refreshstatus) | Yes | Refresh status.| 119 120### onRefreshing 121 122onRefreshing(callback: () => void) 123 124Called when the component starts refreshing. 125 126**Atomic service API**: This API can be used in atomic services since API version 11. 127 128**System capability**: SystemCapability.ArkUI.ArkUI.Full 129 130### onOffsetChange<sup>12+</sup> 131 132onOffsetChange(callback: Callback\<number>) 133 134Called when the pull-down distance changes. 135 136**Atomic service API**: This API can be used in atomic services since API version 12. 137 138**System capability**: SystemCapability.ArkUI.ArkUI.Full 139 140**Parameters** 141 142| Name| Type | Mandatory| Description | 143| ------ | --------------------------------------- | ---- | ---------- | 144| callback | Callback\<number> | Yes | Pull-down distance.<br>Unit: vp| 145 146 147## RefreshStatus 148 149**Atomic service API**: This API can be used in atomic services since API version 11. 150 151**System capability**: SystemCapability.ArkUI.ArkUI.Full 152 153| Name | Value | Description | 154| -------- | -------- | -------------------- | 155| Inactive | 0 | The component is not pulled down. This is the default value. | 156| Drag | 1 | The component is being pulled down, but the pull-down distance is shorter than the minimum length required to trigger the refresh. | 157| OverDrag | 2 | The component is being pulled down, and the pull-down distance exceeds the minimum length required to trigger the refresh. | 158| Refresh | 3 | The pull-down ends, and the component rebounds to the minimum length required to trigger the refresh and enters the refreshing state.| 159| Done | 4 | The refresh is complete, and the component returns to the initial state (at the top). | 160 161 162## Example 163 164### Example 1: Using the Default Refreshing Style 165 166This example implements a **Refresh** component with its refreshing area in the default style. 167 168```ts 169// xxx.ets 170@Entry 171@Component 172struct RefreshExample { 173 @State isRefreshing: boolean = false 174 @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] 175 176 build() { 177 Column() { 178 Refresh({ refreshing: $$this.isRefreshing }) { 179 List() { 180 ForEach(this.arr, (item: string) => { 181 ListItem() { 182 Text('' + item) 183 .width('70%') 184 .height(80) 185 .fontSize(16) 186 .margin(10) 187 .textAlign(TextAlign.Center) 188 .borderRadius(10) 189 .backgroundColor(0xFFFFFF) 190 } 191 }, (item: string) => item) 192 } 193 .onScrollIndex((first: number) => { 194 console.info(first.toString()) 195 }) 196 .width('100%') 197 .height('100%') 198 .alignListItem(ListItemAlign.Center) 199 .scrollBar(BarState.Off) 200 } 201 .onStateChange((refreshStatus: RefreshStatus) => { 202 console.info('Refresh onStatueChange state is ' + refreshStatus) 203 }) 204 .onOffsetChange((value: number) => { 205 console.info('Refresh onOffsetChange offset:' + value) 206 }) 207 .onRefreshing(() => { 208 setTimeout(() => { 209 this.isRefreshing = false 210 }, 2000) 211 console.log('onRefreshing test') 212 }) 213 .backgroundColor(0x89CFF0) 214 .refreshOffset(64) 215 .pullToRefresh(true) 216 } 217 } 218} 219``` 220 221 222 223### Example 2: Setting the Text Displayed in the Refreshing Area 224 225This example shows how to set the text displayed in the refreshing area using the [promptText](#refreshoptions) parameter. 226 227```ts 228// xxx.ets 229@Entry 230@Component 231struct RefreshExample { 232 @State isRefreshing: boolean = false 233 @State promptText: string = "Refreshing..." 234 @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] 235 236 build() { 237 Column() { 238 Refresh({ refreshing: $$this.isRefreshing, promptText: this.promptText }) { 239 List() { 240 ForEach(this.arr, (item: string) => { 241 ListItem() { 242 Text('' + item) 243 .width('70%') 244 .height(80) 245 .fontSize(16) 246 .margin(10) 247 .textAlign(TextAlign.Center) 248 .borderRadius(10) 249 .backgroundColor(0xFFFFFF) 250 } 251 }, (item: string) => item) 252 } 253 .onScrollIndex((first: number) => { 254 console.info(first.toString()) 255 }) 256 .width('100%') 257 .height('100%') 258 .alignListItem(ListItemAlign.Center) 259 .scrollBar(BarState.Off) 260 } 261 .backgroundColor(0x89CFF0) 262 .pullToRefresh(true) 263 .refreshOffset(96) 264 .onStateChange((refreshStatus: RefreshStatus) => { 265 console.info('Refresh onStatueChange state is ' + refreshStatus) 266 }) 267 .onOffsetChange((value: number) => { 268 console.info('Refresh onOffsetChange offset:' + value) 269 }) 270 .onRefreshing(() => { 271 setTimeout(() => { 272 this.isRefreshing = false 273 }, 2000) 274 console.log('onRefreshing test') 275 }) 276 } 277 } 278} 279``` 280 281 282 283### Example 3: Customizing the Refreshing Area Content with builder 284 285This example shows how to customize the content displayed in the refreshing area using the [builder](#refreshoptions) parameter. 286 287```ts 288// xxx.ets 289@Entry 290@Component 291struct RefreshExample { 292 @State isRefreshing: boolean = false 293 @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] 294 295 @Builder 296 customRefreshComponent() { 297 Stack() { 298 Row() { 299 LoadingProgress().height(32) 300 Text("Refreshing...").fontSize(16).margin({ left: 20 }) 301 } 302 .alignItems(VerticalAlign.Center) 303 } 304 .align(Alignment.Center) 305 .clip(true) 306 // 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. 307 .constraintSize({ minHeight: 32 }) 308 .width("100%") 309 } 310 311 build() { 312 Column() { 313 Refresh({ refreshing: $$this.isRefreshing, builder: this.customRefreshComponent() }) { 314 List() { 315 ForEach(this.arr, (item: string) => { 316 ListItem() { 317 Text('' + item) 318 .width('70%') 319 .height(80) 320 .fontSize(16) 321 .margin(10) 322 .textAlign(TextAlign.Center) 323 .borderRadius(10) 324 .backgroundColor(0xFFFFFF) 325 } 326 }, (item: string) => item) 327 } 328 .onScrollIndex((first: number) => { 329 console.info(first.toString()) 330 }) 331 .width('100%') 332 .height('100%') 333 .alignListItem(ListItemAlign.Center) 334 .scrollBar(BarState.Off) 335 } 336 .backgroundColor(0x89CFF0) 337 .pullToRefresh(true) 338 .refreshOffset(64) 339 .onStateChange((refreshStatus: RefreshStatus) => { 340 console.info('Refresh onStatueChange state is ' + refreshStatus) 341 }) 342 .onRefreshing(() => { 343 setTimeout(() => { 344 this.isRefreshing = false 345 }, 2000) 346 console.log('onRefreshing test') 347 }) 348 } 349 } 350} 351``` 352 353 354 355### Example 4: Customizing the Refreshing Area Content with refreshingContent 356 357This example shows how to customize the content displayed in the refreshing area using the [refreshingContent](#refreshoptions) parameter. 358 359```ts 360// xxx.ets 361import { ComponentContent } from '@ohos.arkui.node'; 362 363class Params { 364 refreshStatus: RefreshStatus = RefreshStatus.Inactive 365 366 constructor(refreshStatus: RefreshStatus) { 367 this.refreshStatus = refreshStatus; 368 } 369} 370 371@Builder 372function customRefreshingContent(params: Params) { 373 Stack() { 374 Row() { 375 LoadingProgress().height(32) 376 Text("refreshStatus: " + params.refreshStatus).fontSize(16).margin({ left: 20 }) 377 } 378 .alignItems(VerticalAlign.Center) 379 } 380 .align(Alignment.Center) 381 .clip(true) 382 // 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. 383 .constraintSize({ minHeight: 32 }) 384 .width("100%") 385} 386 387@Entry 388@Component 389struct RefreshExample { 390 @State isRefreshing: boolean = false 391 @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] 392 @State refreshStatus: RefreshStatus = RefreshStatus.Inactive 393 private contentNode?: ComponentContent<Object> = undefined 394 private params: Params = new Params(RefreshStatus.Inactive) 395 396 aboutToAppear(): void { 397 let uiContext = this.getUIContext() 398 this.contentNode = new ComponentContent(uiContext, wrapBuilder(customRefreshingContent), this.params) 399 } 400 401 build() { 402 Column() { 403 Refresh({ refreshing: $$this.isRefreshing, refreshingContent: this.contentNode }) { 404 List() { 405 ForEach(this.arr, (item: string) => { 406 ListItem() { 407 Text('' + item) 408 .width('70%') 409 .height(80) 410 .fontSize(16) 411 .margin(10) 412 .textAlign(TextAlign.Center) 413 .borderRadius(10) 414 .backgroundColor(0xFFFFFF) 415 } 416 }, (item: string) => item) 417 } 418 .onScrollIndex((first: number) => { 419 console.info(first.toString()) 420 }) 421 .width('100%') 422 .height('100%') 423 .alignListItem(ListItemAlign.Center) 424 .scrollBar(BarState.Off) 425 } 426 .backgroundColor(0x89CFF0) 427 .pullToRefresh(true) 428 .refreshOffset(96) 429 .onStateChange((refreshStatus: RefreshStatus) => { 430 this.refreshStatus = refreshStatus 431 this.params.refreshStatus = refreshStatus 432 // Update the content of the custom component. 433 this.contentNode?.update(this.params) 434 console.info('Refresh onStatueChange state is ' + refreshStatus) 435 }) 436 .onRefreshing(() => { 437 setTimeout(() => { 438 this.isRefreshing = false 439 }, 2000) 440 console.log('onRefreshing test') 441 }) 442 } 443 } 444} 445``` 446 447 448### Example 5: Implementing the Maximum Pull-down Distance 449 450This example shows how to use the [pullDownRatio](#pulldownratio12) attribute and the [onOffsetChange](#onoffsetchange12) event to implement the maximum pull-down distance. 451 452```ts 453// xxx.ets 454import { ComponentContent } from '@ohos.arkui.node'; 455 456@Builder 457function customRefreshingContent() { 458 Stack() { 459 Row() { 460 LoadingProgress().height(32) 461 } 462 .alignItems(VerticalAlign.Center) 463 } 464 .align(Alignment.Center) 465 .clip(true) 466 // 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. 467 .constraintSize({ minHeight: 32 }) 468 .width("100%") 469} 470 471@Entry 472@Component 473struct RefreshExample { 474 @State isRefreshing: boolean = false 475 @State arr: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] 476 @State maxRefreshingHeight: number = 100.0 477 @State ratio: number = 1 478 private contentNode?: ComponentContent<Object> = undefined 479 480 aboutToAppear(): void { 481 let uiContext = this.getUIContext(); 482 this.contentNode = new ComponentContent(uiContext, wrapBuilder(customRefreshingContent)) 483 } 484 485 build() { 486 Column() { 487 Refresh({ refreshing: $$this.isRefreshing, refreshingContent: this.contentNode }) { 488 List() { 489 ForEach(this.arr, (item: string) => { 490 ListItem() { 491 Text('' + item) 492 .width('70%') 493 .height(80) 494 .fontSize(16) 495 .margin(10) 496 .textAlign(TextAlign.Center) 497 .borderRadius(10) 498 .backgroundColor(0xFFFFFF) 499 } 500 }, (item: string) => item) 501 } 502 .onScrollIndex((first: number) => { 503 console.info(first.toString()) 504 }) 505 .width('100%') 506 .height('100%') 507 .alignListItem(ListItemAlign.Center) 508 .scrollBar(BarState.Off) 509 } 510 .backgroundColor(0x89CFF0) 511 .pullDownRatio(this.ratio) 512 .pullToRefresh(true) 513 .refreshOffset(64) 514 .onOffsetChange((offset: number) => { 515 // The closer to the maximum distance, the smaller the pull-down ratio. 516 this.ratio = 1 - Math.pow((offset / this.maxRefreshingHeight), 3) 517 }) 518 .onStateChange((refreshStatus: RefreshStatus) => { 519 console.info('Refresh onStatueChange state is ' + refreshStatus) 520 }) 521 .onRefreshing(() => { 522 setTimeout(() => { 523 this.isRefreshing = false 524 }, 2000) 525 console.log('onRefreshing test') 526 }) 527 } 528 } 529} 530``` 531 532 533 534### Example 6: Implementing Pull-Down-to-Refresh and Pull-Up-to-Load-More 535 536This 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. 537 538```ts 539// xxx.ets 540@Entry 541@Component 542struct ListRefreshLoad { 543 @State arr: Array<number> = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 544 @State refreshing: boolean = false; 545 @State refreshOffset: number = 0; 546 @State refreshState: RefreshStatus = RefreshStatus.Inactive; 547 @State isLoading: boolean = false; 548 549 @Builder 550 refreshBuilder() { 551 Stack({ alignContent: Alignment.Bottom }) { 552 //The Progress component can be controlled by the refresh state. 553 // The Progress component is present only when the refresh state is pulling or refreshing. 554 if (this.refreshState != RefreshStatus.Inactive && this.refreshState != RefreshStatus.Done) { 555 Progress({ value: this.refreshOffset, total: 64, type: ProgressType.Ring }) 556 .width(32).height(32) 557 .style({ status: this.refreshing ? ProgressStatus.LOADING : ProgressStatus.PROGRESSING }) 558 .margin(10) 559 } 560 } 561 .clip(true) 562 .height("100%") 563 .width("100%") 564 } 565 566 @Builder 567 footer() { 568 Row() { 569 LoadingProgress().height(32).width(48) 570 Text("Loading") 571 }.width("100%") 572 .height(64) 573 .justifyContent(FlexAlign.Center) 574 // Hide the component when it is not in the loading state. 575 .visibility(this.isLoading ? Visibility.Visible : Visibility.Hidden) 576 } 577 578 build() { 579 Refresh({ refreshing: $$this.refreshing, builder: this.refreshBuilder() }) { 580 List() { 581 ForEach(this.arr, (item: number) => { 582 ListItem() { 583 Text('' + item) 584 .width('100%') 585 .height(80) 586 .fontSize(16) 587 .textAlign(TextAlign.Center) 588 .backgroundColor(0xFFFFFF) 589 }.borderWidth(1) 590 }, (item: string) => item) 591 592 ListItem() { 593 this.footer(); 594 } 595 } 596 .onScrollIndex((start: number, end: number) => { 597 // Trigger new data loading when the end of the list is reached. 598 if (end >= this.arr.length - 1) { 599 this.isLoading = true; 600 // Simulate new data loading. 601 setTimeout(() => { 602 for (let i = 0; i < 10; i++) { 603 this.arr.push(this.arr.length); 604 this.isLoading = false; 605 } 606 }, 700) 607 } 608 }) 609 .scrollBar(BarState.Off) 610 // Enable the effect used when the scroll boundary is reached. 611 .edgeEffect(EdgeEffect.Spring, { alwaysEnabled: true }) 612 } 613 .width('100%') 614 .height('100%') 615 .backgroundColor(0xDCDCDC) 616 .onOffsetChange((offset: number) => { 617 this.refreshOffset = offset; 618 }) 619 .onStateChange((state: RefreshStatus) => { 620 this.refreshState = state; 621 }) 622 .onRefreshing(() => { 623 // Simulate data refreshing. 624 setTimeout(() => { 625 this.refreshing = false; 626 }, 2000) 627 }) 628 } 629} 630``` 631 632 633