• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Scroll
2
3可滚动的容器组件,当子组件的布局尺寸超过父组件的尺寸时,内容可以滚动。
4
5>  **说明:**
6>  - 该组件从API version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
7>  - 该组件嵌套List子组件滚动时,若List不设置宽高,则默认全部加载,在对性能有要求的场景下建议指定List的宽高。
8>  - 该组件滚动的前提是主轴方向大小小于内容大小。
9>  - 该组件回弹的前提是要有滚动。内容小于一屏时,没有回弹效果。
10
11
12## 子组件
13
14支持单个子组件。
15
16
17## 接口
18
19Scroll(scroller?: Scroller)
20
21**参数:**
22
23| 参数名 | 参数类型 | 必填 | 参数描述 |
24| -------- | -------- | -------- | -------- |
25| scroller | [Scroller](#scroller) | 否 | 可滚动组件的控制器。用于与可滚动组件进行绑定。 |
26
27## 属性
28
29除支持[通用属性](ts-universal-attributes-size.md)外,还支持以下属性:
30
31| 名称             | 参数类型                                     | 描述        |
32| -------------- | ---------------------------------------- | --------- |
33| scrollable     | [ScrollDirection](#scrolldirection枚举说明)                        | 设置滚动方向。<br/>默认值:ScrollDirection.Vertical |
34| scrollBar      | [BarState](ts-appendix-enums.md#barstate) | 设置滚动条状态。<br/>默认值:BarState.Auto<br/>**说明:** <br/>如果容器组件无法滚动,则滚动条不显示。如果容器组件的子组件大小为无穷大,则滚动条不支持拖动和伴随滚动。 |
35| scrollBarColor | string&nbsp;\|&nbsp;number&nbsp;\|&nbsp;[Color](ts-appendix-enums.md#color)   | 设置滚动条的颜色。 |
36| scrollBarWidth | string&nbsp;\|&nbsp;number         | 设置滚动条的宽度,不支持百分比设置。<br/>默认值:4<br/>单位:vp<br/>**说明:** <br/>如果滚动条的宽度超过其高度,则滚动条的宽度会变为默认值。 |
37| edgeEffect     | [EdgeEffect](ts-appendix-enums.md#edgeeffect)            | 设置滑动效果,目前支持的滑动效果参见EdgeEffect的枚举说明。<br/>默认值:EdgeEffect.None |
38
39## ScrollDirection枚举说明
40| 名称       | 描述                     |
41| ---------- | ------------------------ |
42| Horizontal | 仅支持水平方向滚动。     |
43| Vertical   | 仅支持竖直方向滚动。     |
44| None       | 不可滚动。               |
45| Free<sup>(deprecated) </sup> | 支持竖直或水平方向滚动<br/> 从API version 9开始废弃|
46
47## 事件
48
49| 名称                                                         | 功能描述                                                     |
50| ------------------------------------------------------------ | ------------------------------------------------------------ |
51| onScrollFrameBegin<sup>9+</sup>(event: (offset: number, state: ScrollState) => { offsetRemain }) | 每帧开始滚动时触发,事件参数传入即将发生的滚动量,事件处理函数中可根据应用场景计算实际需要的滚动量并作为事件处理函数的返回值返回,Scroll将按照返回值的实际滚动量进行滚动。<br/>\- offset:即将发生的滚动量。<br/>\- state:当前滚动状态。<br/>- offsetRemain:实际滚动量。<br/>触发该事件的条件 :<br/>1、滚动组件触发滚动时触发,包括键鼠操作等其他触发滚动的输入设置。<br/>2、调用控制器接口时不触发。<br/>3、越界回弹不触发。<br/>**说明:** <br/>支持offsetRemain为负值。<br/>若通过onScrollFrameBegine事件和scrollBy方法实现容器嵌套滚动,需设置子滚动节点的EdgeEffect为None。如Scroll嵌套List滚动时,List组件的edgeEffect属性需设置为EdgeEffect.None。 |
52| onScroll(event: (xOffset: number, yOffset: number) => void)  | 滚动事件回调,&nbsp;返回滚动时水平、竖直方向偏移量。<br/>触发该事件的条件 :<br/>1、滚动组件触发滚动时触发,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用。<br/>3、越界回弹。 |
53| onScrollEdge(event: (side: Edge) => void)                    | 滚动到边缘事件回调。<br/>触发该事件的条件 :<br/>1、滚动组件滚动到边缘时触发,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用。<br/>3、越界回弹。 |
54| onScrollEnd<sup>(deprecated) </sup>(event: () => void)       | 滚动停止事件回调。<br>该事件从API version 9开始废弃,使用onScrollStop事件替代。<br/>触发该事件的条件 :<br/>1、滚动组件触发滚动后停止,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用后停止,带过渡动效。 |
55| onScrollStart<sup>9+</sup>(event: () => void)                | 滚动开始时触发。手指拖动Scroll或拖动Scroll的滚动条触发的滚动开始时,会触发该事件。使用[Scroller](#scroller)滚动控制器触发的带动画的滚动,动画开始时会触发该事件。<br/>触发该事件的条件 :<br/>1、滚动组件开始滚动时触发,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用后开始,带过渡动效。 |
56| onScrollStop<sup>9+</sup>(event: () => void)                 | 滚动停止时触发。手拖动Scroll或拖动Scroll的滚动条触发的滚动,手离开屏幕并且滚动停止时会触发该事件。使用[Scroller](#scroller)滚动控制器触发的带动画的滚动,动画停止时会触发该事件。<br/>触发该事件的条件 :<br/>1、滚动组件触发滚动后停止,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用后开始,带过渡动效,。 |
57
58>  **说明:**
59>
60>  若通过onScrollFrameBegin事件和scrollBy方法实现容器嵌套滚动,需设置子滚动节点的EdgeEffect为None。如Scroll嵌套List滚动时,List组件的edgeEffect属性需设置为EdgeEffect.None61
62## Scroller
63
64可滚动容器组件的控制器,可以将此组件绑定至容器组件,然后通过它控制容器组件的滚动,同一个控制器不可以控制多个容器组件,目前支持绑定到List、Scroll、ScrollBar、Grid、WaterFlow上。
65
66
67### 导入对象
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
79滑动到指定位置。
80
81**参数:**
82
83| 参数名    | 参数类型                                                     | 必填 | 参数描述                                                     |
84| --------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
85| xOffset   | number&nbsp;\|&nbsp;string                                   | 是   | 水平滑动偏移。<br/>**说明:** <br/>该参数值不支持设置百分比。<br/>仅滚动轴为x轴时生效。 |
86| yOffset   | number&nbsp;\|&nbsp;string                                   | 是   | 垂直滑动偏移。<br/>**说明:** <br/>该参数值不支持设置百分比。<br/>仅滚动轴为y轴时生效。 |
87| animation | {<br/>duration:&nbsp;number,<br/>curve:&nbsp;[Curve](ts-appendix-enums.md#curve)<br/>} | 否   | 动画配置:<br/>-&nbsp;duration:&nbsp;滚动时长设置。<br/>-&nbsp;curve:&nbsp;滚动曲线设置。<br/>默认值: <br/>{<br/>duration:&nbsp;0,<br/>curve:&nbsp;Curve.Ease<br/>}<br/>**说明:** <br/>设置为小于0的值时,按默认值显示。 |
88
89
90### scrollEdge
91
92scrollEdge(value: Edge): void
93
94
95滚动到容器边缘,不区分滚动轴方向,Edge.TopEdge.Start表现相同,Edge.BottomEdge.End表现相同。
96
97**参数:**
98
99| 参数名   | 参数类型 | 必填   | 参数描述      |
100| ----- | ---- | ---- | --------- |
101| value | [Edge](ts-appendix-enums.md#edge) | 是    | 滚动到的边缘位置。 |
102
103
104### scrollPage
105
106scrollPage(value: { next: boolean, direction?: Axis }): void
107
108滚动到下一页或者上一页。
109
110**参数:**
111
112| 参数名       | 参数类型    | 必填   | 参数描述                           |
113| --------- | ------- | ---- | ------------------------------ |
114| next      | boolean | 是    | 是否向下翻页。true表示向下翻页,false表示向上翻页。 |
115| direction<sup>(deprecated) </sup> | [Axis](ts-appendix-enums.md#axis)    | 否    | 设置滚动方向为水平或竖直方向。<br/> 从API version 9开始废弃                |
116
117
118### currentOffset
119
120currentOffset(): { xOffset: number, yOffset: number }
121
122
123返回当前的滚动偏移量。
124
125**返回值**
126
127| 类型                                                       | 描述                                                         |
128| ---------------------------------------------------------- | ------------------------------------------------------------ |
129| {<br/>xOffset:&nbsp;number,<br/>yOffset:&nbsp;number<br/>} | xOffset:&nbsp;水平滑动偏移;<br/>yOffset:&nbsp;竖直滑动偏移。<br/>**说明:** <br/>返回值单位为vp。 |
130
131
132### scrollToIndex
133
134scrollToIndex(value: number): void
135
136
137滑动到指定Index。
138
139
140>  **说明:**
141>
142>  仅支持Grid、List、WaterFlow组件。
143
144**参数:**
145
146| 参数名 | 参数类型 | 必填 | 参数描述                           |
147| ------ | -------- | ---- | ---------------------------------- |
148| value  | number   | 是   | 要滑动到的列表项在列表中的索引值。 |
149
150
151### scrollBy<sup>9+</sup>
152
153scrollBy(dx: Length, dy: Length): void
154
155
156滑动指定距离。
157
158
159>  **说明:**
160>
161>  仅支持Scroll、ScrollBar、Grid、List组件。
162
163**参数:**
164
165| 参数名   | 参数类型   | 必填   | 参数描述              |
166| ----- | ------ | ---- | ----------------- |
167| dx | Length | 是    | 水平方向滚动距离,不支持百分比形式。 |
168| dy | Length | 是    | 竖直方向滚动距离,不支持百分比形式。 |
169
170
171## 示例
172### 示例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)  // 滚动方向纵向
199      .scrollBar(BarState.On)  // 滚动条常驻显示
200      .scrollBarColor(Color.Gray)  // 滚动条颜色
201      .scrollBarWidth(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(() => { // 点击后下滑指定距离150.0vp
216          this.scroller.scrollBy(0,150)
217        })
218        .margin({ top: 10, left: 20 })
219      Button('scroll 100')
220        .height('5%')
221        .onClick(() => { // 点击后滑动到指定位置,即下滑100.0vp的距离
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(() => { // 点击后回到顶部
228          this.scroller.scrollEdge(Edge.Top)
229        })
230        .margin({ top: 110, left: 20 })
231      Button('next page')
232        .height('5%')
233        .onClick(() => { // 点击后滑到下一页
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![zh-cn_image_0000001174104386](figures/zh-cn_image_0000001174104386.gif)
243
244### 示例2
245```ts
246@Entry
247@Component
248struct NestedScroll {
249  @State listPosition: number = 0; // 0代表滚动到List顶部,1代表中间值,2代表滚动到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)