• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![en-us_image_refresh_default](figures/en-us_image_refresh_default.gif)
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![en-us_image_refresh_prompttext](figures/en-us_image_refresh_prompttext.gif)
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![en-us_image_refresh_builder](figures/en-us_image_refresh_builder.gif)
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![en-us_image_refresh_refreshingcontent](figures/en-us_image_refresh_refreshingcontent.gif)
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![en-us_image_refresh_maxrefreshingheight](figures/en-us_image_refresh_maxrefreshingheight.gif)
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![refresh_boundary_resilience](figures/refresh_boundary_resilience.gif)
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![refresh_boundary_resilience](figures/refresh_maxpulldowndistance_demo_7.gif)
716