• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Scroll
2
3The **\<Scroll>** component scrolls the content when the layout size of a component exceeds the size of its parent component.
4
5>  **NOTE**
6>  - This component is supported since API version 7. Updates will be marked with a superscript to indicate their earliest API version.
7>  - When nesting a **\<List>** within this component, specify the width and height for the **\<List>** under scenarios where consistently high performance is required. If the width and height are not specified, this component will load all content of the **\<List>**.
8>  - This component can scroll only when the size on the main axis is less than the content size.
9>  - This component can produce a bounce effect only when there is more than one screen of content.
10
11
12## Child Components
13
14This component supports only one child component.
15
16
17## APIs
18
19Scroll(scroller?: Scroller)
20
21**Parameters**
22
23| Name| Type| Mandatory| Description|
24| -------- | -------- | -------- | -------- |
25| scroller | [Scroller](#scroller) | No| Scroller, which can be bound to scrollable components.|
26
27## Attributes
28
29In addition to the [universal attributes](ts-universal-attributes-size.md), the following attributes are supported.
30
31| Name            | Type                                    | Description       |
32| -------------- | ---------------------------------------- | --------- |
33| scrollable     | [ScrollDirection](#scrolldirection)                        | Scroll direction.<br>Default value: **ScrollDirection.Vertical**|
34| scrollBar      | [BarState](ts-appendix-enums.md#barstate) | Scrollbar status.<br>Default value: **BarState.Auto**<br>**NOTE**<br>If the container component cannot be scrolled, the scrollbar is not displayed. If the size of a child component of a container component is infinite, the scrollbar cannot be dragged or scrolled with the child component.|
35| scrollBarColor | string \| number \| [Color](ts-appendix-enums.md#color)   | Color of the scrollbar.|
36| scrollBarWidth | string \| number         | Width of the scrollbar. This attribute cannot be set in percentage.<br>Default value: **4**<br>Unit: vp<br>**NOTE**<br>If the width of the scrollbar exceeds its height, it will change to the default value.|
37| edgeEffect     | [EdgeEffect](ts-appendix-enums.md#edgeeffect)            | Scroll effect. For details, see **EdgeEffect**.<br>Default value: **EdgeEffect.None**|
38
39## ScrollDirection
40| Name      | Description                    |
41| ---------- | ------------------------ |
42| Horizontal | Only horizontal scrolling is supported.    |
43| Vertical   | Only vertical scrolling is supported.    |
44| None       | Scrolling is disabled.              |
45| Free<sup>(deprecated)</sup> | Vertical or horizontal scrolling is supported.<br>This API is deprecated since API version 9.|
46
47## Events
48
49| Name                                                        | Description                                                    |
50| ------------------------------------------------------------ | ------------------------------------------------------------ |
51| onScrollFrameBegin<sup>9+</sup>(event: (offset: number, state: ScrollState) => { offsetRemain }) | Triggered when each frame scrolling starts. The input parameters indicate the amount by which the **\<Scroll>** component will scroll. The event handler then works out the amount by which the component needs to scroll based on the real-world situation and returns the result.<br>\- **offset**: amount to scroll by.<br>\- **state**: current scrolling status.<br>- **offsetRemain**: actual amount by which the component scrolls.<br>**NOTE**<br>1. This event is triggered when scrolling is started by the **\<Scroll>** component or other input settings, such as keyboard and mouse operations.<br>2. This event is not triggered when the controller API is called.<br>3. No out-of-bounds bounce effect is triggered.<br>**NOTE**<br>The value of **offsetRemain** can be a negative value.<br>If the **onScrollFrameBegine** event and **scrollBy** method are used to implement nested scrolling, set the **edgeEffect** attribute of the scrollable child component to **None**. For example, if a **\<List>** is nested in the **\<Scroll>** component, **edgeEffect** of the **\<List>** must be set to **EdgeEffect.None**.|
52| onScroll(event: (xOffset: number, yOffset: number) => void)  | Triggered to return the horizontal and vertical offsets during scrolling when the specified scroll event occurs.<br>**NOTE**<br>1. This event is triggered when scrolling is started by the **\<Scroll>** component or other input settings, such as keyboard and mouse operations.<br>2. This event is triggered when the controller API is called.<br>3. The out-of-bounds bounce effect is triggered.|
53| onScrollEdge(event: (side: Edge) => void)                    | Triggered when scrolling reaches the edge.<br>**NOTE**<br>1. This event is triggered when scrolling reaches the edge after being started by the **\<Scroll>** component or other input settings, such as keyboard and mouse operations.<br>2. This event is triggered when the controller API is called.<br>3. The out-of-bounds bounce effect is triggered.|
54| onScrollEnd<sup>(deprecated) </sup>(event: () => void)       | Triggered when scrolling stops.<br>This event is deprecated since API version 9. Use the **onScrollStop** event instead.<br>**NOTE**<br>1. This event is triggered when scrolling is stopped by the **\<Scroll>** component or other input settings, such as keyboard and mouse operations.<br>2. This event is triggered when the controller API is called, accompanied by a transition animation.|
55| onScrollStart<sup>9+</sup>(event: () => void)                | Triggered when scrolling starts and is initiated by the user's finger dragging the **\<Scroll>** component or its scrollbar. This event is also triggered when the animation contained in the scrolling triggered by [Scroller](#scroller) starts.<br>**NOTE**<br>1. This event is triggered when scrolling is started by the **\<Scroll>** component or other input settings, such as keyboard and mouse operations.<br>2. This event is triggered when the controller API is called, accompanied by a transition animation.|
56| onScrollStop<sup>9+</sup>(event: () => void)                 | Triggered when scrolling stops after the user's finger leaves the screen. This event is also triggered when the animation contained in the scrolling triggered by [Scroller](#scroller) stops.<br>**NOTE**<br>1. This event is triggered when scrolling is stopped by the **\<Scroll>** component or other input settings, such as keyboard and mouse operations.<br>2. This event is triggered when the controller API is called, accompanied by a transition animation.|
57
58>  **NOTE**
59>
60>  If the **onScrollFrameBegin** event and **scrollBy** method are used to implement nested scrolling, set the **edgeEffect** attribute of the scrollable child component to **None**. For example, if a **\<List>** is nested in the **\<Scroll>** component, **edgeEffect** of the **\<List>** must be set to **EdgeEffect.None**.
61
62## Scroller
63
64Implements a controller for a scrollable container component. You can bind this component to a container component and use it to control the scrolling of that component. One controller can control only one container component. The supported container components are **\<List>**, **\<Scroll>**, **\<ScrollBar>**, **\<Grid>**, and **\<WaterFlow>**.
65
66
67### Objects to Import
68
69```
70scroller: Scroller = new Scroller()
71```
72
73
74### scrollTo
75
76scrollTo(value: { xOffset: number | string, yOffset: number | string, animation?: { duration: number, curve: Curve } }): void
77
78
79Scrolls to the specified position.
80
81**Parameters**
82
83| Name   | Type                                                    | Mandatory| Description                                                    |
84| --------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
85| xOffset   | number \| string                                   | Yes  | Horizontal scrolling offset.<br>**NOTE**<br>This parameter cannot be set in percentage.<br>This parameter is valid only when the scroll axis is the x-axis.|
86| yOffset   | number \| string                                   | Yes  | Vertical scrolling offset.<br>**NOTE**<br>This parameter cannot be set in percentage.<br>This parameter is valid only when the scroll axis is the y-axis.|
87| animation | {<br>duration: number,<br>curve: [Curve](ts-appendix-enums.md#curve)<br>} | No  | Animation configuration, which includes the following:<br>- **duration**: scrolling duration.<br>- **curve**: scrolling curve.<br>Default value:<br>{<br>duration: 0,<br>curve: Curve.Ease<br>}<br>**NOTE**<br>A value less than 0 evaluates to the default value.|
88
89
90### scrollEdge
91
92scrollEdge(value: Edge): void
93
94
95Scrolls to the edge of the container, regardless of the scroll axis direction. **Edge.Top** and **Edge.Start** produce the same effect, and **Edge.Bottom** and **Edge.End** produce the same effect.
96
97**Parameters**
98
99| Name  | Type| Mandatory  | Description     |
100| ----- | ---- | ---- | --------- |
101| value | [Edge](ts-appendix-enums.md#edge) | Yes   | Edge position to scroll to.|
102
103
104### scrollPage
105
106scrollPage(value: { next: boolean, direction?: Axis }): void
107
108Scrolls to the next or previous page.
109
110**Parameters**
111
112| Name      | Type   | Mandatory  | Description                          |
113| --------- | ------- | ---- | ------------------------------ |
114| next      | boolean | Yes   | Whether to turn to the next page. The value **true** means to scroll to the next page, and **false** means to scroll to the previous page.|
115| direction<sup>(deprecated)</sup> | [Axis](ts-appendix-enums.md#axis)    | No   | Scrolling direction: horizontal or vertical.<br>This API is deprecated since API version 9.               |
116
117
118### currentOffset
119
120currentOffset(): { xOffset: number, yOffset: number }
121
122
123Obtains the scrolling offset.
124
125**Return value**
126
127| Type                                                      | Description                                                        |
128| ---------------------------------------------------------- | ------------------------------------------------------------ |
129| {<br>xOffset: number,<br>yOffset: number<br>} | **xOffset**: horizontal scrolling offset.<br>**yOffset**: vertical scrolling offset.<br>**NOTE**<br>The unit of the return value is vp.|
130
131
132### scrollToIndex
133
134scrollToIndex(value: number): void
135
136
137Scrolls to the item with the specified index.
138
139
140>  **NOTE**
141>
142>  Only the **\<Grid>**, **\<List>**, and **\<WaterFlow>** components are supported.
143
144**Parameters**
145
146| Name| Type| Mandatory| Description                          |
147| ------ | -------- | ---- | ---------------------------------- |
148| value  | number   | Yes  | Index of the item to be scrolled to in the list.|
149
150
151### scrollBy<sup>9+</sup>
152
153scrollBy(dx: Length, dy: Length): void
154
155
156Scrolls by the specified amount.
157
158
159>  **NOTE**
160>
161>  Only the **\<Scroll>**, **\<ScrollBar>**, **\<Grid>**, and **\<List>** components are supported.
162
163**Parameters**
164
165| Name  | Type  | Mandatory  | Description             |
166| ----- | ------ | ---- | ----------------- |
167| dx | Length | Yes   | Amount to scroll by in the horizontal direction. The percentage format is not supported.|
168| dy | Length | Yes   | Amount to scroll by in the vertical direction. The percentage format is not supported.|
169
170
171## Example
172### Example 1
173
174```ts
175// xxx.ets
176@Entry
177@Component
178struct ScrollExample {
179  scroller: Scroller = new Scroller()
180  private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
181
182  build() {
183    Stack({ alignContent: Alignment.TopStart }) {
184      Scroll(this.scroller) {
185        Column() {
186          ForEach(this.arr, (item) => {
187            Text(item.toString())
188              .width('90%')
189              .height(150)
190              .backgroundColor(0xFFFFFF)
191              .borderRadius(15)
192              .fontSize(16)
193              .textAlign(TextAlign.Center)
194              .margin({ top: 10 })
195          }, item => item)
196        }.width('100%')
197      }
198      .scrollable(ScrollDirection.Vertical)  // The scrollbar scrolls in the vertical direction.
199      .scrollBar(BarState.On)  // The scrollbar is always displayed.
200      .scrollBarColor(Color.Gray)  // Color of the scrollbar.
201      .scrollBarWidth(10) // The scrollbar width is 10.
202      .edgeEffect(EdgeEffect.None)
203      .onScroll((xOffset: number, yOffset: number) => {
204        console.info(xOffset + ' ' + yOffset)
205      })
206      .onScrollEdge((side: Edge) => {
207        console.info('To the edge')
208      })
209      .onScrollEnd(() => {
210        console.info('Scroll Stop')
211      })
212
213      Button('scroll 150')
214        .height('5%')
215        .onClick(() => { // Click to scroll down to 150.0 vp.
216          this.scroller.scrollBy(0,150)
217        })
218        .margin({ top: 10, left: 20 })
219      Button('scroll 100')
220        .height('5%')
221        .onClick(() => { // Click to scroll down by 100.0 vp.
222          this.scroller.scrollTo({ xOffset: 0, yOffset: this.scroller.currentOffset().yOffset + 100 })
223        })
224        .margin({ top: 60, left: 20 })
225      Button('back top')
226        .height('5%')
227        .onClick(() => { // Click to go back to the top.
228          this.scroller.scrollEdge(Edge.Top)
229        })
230        .margin({ top: 110, left: 20 })
231      Button('next page')
232        .height('5%')
233        .onClick(() => { // Click to go to the next page.
234          this.scroller.scrollPage({ next: true })
235        })
236        .margin({ top: 170, left: 20 })
237    }.width('100%').height('100%').backgroundColor(0xDCDCDC)
238  }
239}
240```
241
242![en-us_image_0000001256978363](figures/en-us_image_0000001256978363.gif)
243
244### Example 2
245```ts
246@Entry
247@Component
248struct NestedScroll {
249  @State listPosition: number = 0; // 0 indicates scrolling to the top of the list, 1 indicates scrolling to the middle of the list, and 2 indicates scrolling to the bottom of the list.
250  private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
251  private scrollerForScroll: Scroller = new Scroller()
252  private scrollerForList: Scroller = new Scroller()
253
254  build() {
255    Flex() {
256      Scroll(this.scrollerForScroll) {
257        Column() {
258          Text("Scroll Area")
259            .width("100%").height("40%").backgroundColor(0X330000FF)
260            .fontSize(16).textAlign(TextAlign.Center)
261            .onClick(() => {
262              this.scrollerForList.scrollToIndex(5)
263            })
264
265          List({ space: 20, scroller: this.scrollerForList }) {
266            ForEach(this.arr, (item) => {
267              ListItem() {
268                Text("ListItem" + item)
269                  .width("100%").height("100%").borderRadius(15)
270                  .fontSize(16).textAlign(TextAlign.Center).backgroundColor(Color.White)
271              }.width("100%").height(100)
272            }, item => item)
273          }
274          .width("100%")
275          .height("50%")
276          .edgeEffect(EdgeEffect.None)
277          .onReachStart(() => {
278            this.listPosition = 0
279          })
280          .onReachEnd(() => {
281            this.listPosition = 2
282          })
283          .onScrollFrameBegin((offset: number) => {
284            if ((this.listPosition == 0 && offset <= 0) || (this.listPosition == 2 && offset >= 0)) {
285              this.scrollerForScroll.scrollBy(0, offset)
286              return { offsetRemain: 0 }
287            }
288            this.listPosition = 1
289            return { offsetRemain: offset };
290          })
291
292          Text("Scroll Area")
293            .width("100%").height("40%").backgroundColor(0X330000FF)
294            .fontSize(16).textAlign(TextAlign.Center)
295        }
296      }
297      .width("100%").height("100%")
298    }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20)
299  }
300}
301```
302
303![NestedScroll](figures/NestedScroll.gif)
304