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 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 304