ts-container-scroll.md 16.4 KB
Newer Older
Z
zengyawen 已提交
1 2
# Scroll

G
gmy 已提交
3 4
可滚动的容器组件,当子组件的布局尺寸超过父组件的尺寸时,内容可以滚动。

H
geshi  
HelloCrease 已提交
5
>  **说明:**
G
gmy 已提交
6 7
>  - 该组件从API version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
>  - 该组件嵌套List子组件滚动时,若List不设置宽高,则默认全部加载,在对性能有要求的场景下建议指定List的宽高。
8
>  - 该组件滚动的前提是主轴方向大小小于内容大小。
G
gmy 已提交
9
>  - 该组件回弹的前提是要有滚动。内容小于一屏时,没有回弹效果。
Z
zengyawen 已提交
10

Z
zengyawen 已提交
11

Z
zengyawen 已提交
12
## 子组件
Z
zengyawen 已提交
13 14 15

支持单个子组件。

Z
zengyawen 已提交
16 17 18 19 20

## 接口

Scroll(scroller?: Scroller)

Y
yeyinglong 已提交
21 22 23 24 25 26
**参数:**

| 参数名 | 参数类型 | 必填 | 参数描述 |
| -------- | -------- | -------- | -------- |
| scroller | [Scroller](#scroller) | 否 | 可滚动组件的控制器。用于与可滚动组件进行绑定。 |

Z
zengyawen 已提交
27 28
## 属性

G
gmy 已提交
29 30 31 32
除支持[通用属性](ts-universal-attributes-size.md)外,还支持以下属性:

| 名称             | 参数类型                                     | 描述        |
| -------------- | ---------------------------------------- | --------- |
S
sienna1128 已提交
33
| scrollable     | [ScrollDirection](#scrolldirection枚举说明)                        | 设置滚动方向。<br/>默认值:ScrollDirection.Vertical |
Z
zhangrongjie 已提交
34
| scrollBar      | [BarState](ts-appendix-enums.md#barstate) | 设置滚动条状态。<br/>默认值:BarState.Auto<br/>**说明:** <br/>如果容器组件无法滚动,则滚动条不显示。如果容器组件的子组件大小为无穷大,则滚动条不支持拖动和伴随滚动。 |
S
sienna1128 已提交
35
| scrollBarColor | string&nbsp;\|&nbsp;number&nbsp;\|&nbsp;[Color](ts-appendix-enums.md#color)   | 设置滚动条的颜色。 |
Z
zhangrongjie 已提交
36
| scrollBarWidth | string&nbsp;\|&nbsp;number         | 设置滚动条的宽度,不支持百分比设置。<br/>默认值:4<br/>单位:vp<br/>**说明:** <br/>如果滚动条的宽度超过其高度,则滚动条的宽度会变为默认值。 |
W
wangshuainan 已提交
37
| edgeEffect     | [EdgeEffect](ts-appendix-enums.md#edgeeffect)            | 设置滑动效果,目前支持的滑动效果参见EdgeEffect的枚举说明。<br/>默认值:EdgeEffect.None |
L
luoying_ace_admin 已提交
38
| enableScrollInteraction<sup>10+</sup>  |  boolean  |   设置是否支持滚动手势,当设置为false时,无法通过手指或者鼠标滚动,但不影响控制器的滚动接口。<br/>默认值:true      |
Z
zengyawen 已提交
39

K
kangchongtao 已提交
40
## ScrollDirection枚举说明
G
gmy 已提交
41 42 43 44 45
| 名称       | 描述                     |
| ---------- | ------------------------ |
| Horizontal | 仅支持水平方向滚动。     |
| Vertical   | 仅支持竖直方向滚动。     |
| None       | 不可滚动。               |
46
| Free<sup>(deprecated) </sup> | 支持竖直或水平方向滚动<br/> 从API version 9开始废弃|
K
kangchongtao 已提交
47

48 49
## 事件

G
gmy 已提交
50 51
| 名称                                                         | 功能描述                                                     |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
Y
yamila 已提交
52 53
| 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。 |
| onScroll(event: (xOffset: number, yOffset: number) => void)  | 滚动事件回调,&nbsp;返回滚动时水平、竖直方向偏移量。<br/>触发该事件的条件 :<br/>1、滚动组件触发滚动时触发,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用。<br/>3、越界回弹。 |
Z
zhangrongjie 已提交
54
| onScrollEdge(event: (side: Edge) => void)                    | 滚动到边缘事件回调。<br/>触发该事件的条件 :<br/>1、滚动组件滚动到边缘时触发,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用。<br/>3、越界回弹。 |
Y
yamila 已提交
55
| onScrollEnd<sup>(deprecated) </sup>(event: () => void)       | 滚动停止事件回调。<br>该事件从API version 9开始废弃,使用onScrollStop事件替代。<br/>触发该事件的条件 :<br/>1、滚动组件触发滚动后停止,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用后停止,带过渡动效。 |
Z
zhangrongjie 已提交
56
| onScrollStart<sup>9+</sup>(event: () => void)                | 滚动开始时触发。手指拖动Scroll或拖动Scroll的滚动条触发的滚动开始时,会触发该事件。使用[Scroller](#scroller)滚动控制器触发的带动画的滚动,动画开始时会触发该事件。<br/>触发该事件的条件 :<br/>1、滚动组件开始滚动时触发,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用后开始,带过渡动效。 |
Y
yamila 已提交
57
| onScrollStop<sup>9+</sup>(event: () => void)                 | 滚动停止时触发。手拖动Scroll或拖动Scroll的滚动条触发的滚动,手离开屏幕并且滚动停止时会触发该事件。使用[Scroller](#scroller)滚动控制器触发的带动画的滚动,动画停止时会触发该事件。<br/>触发该事件的条件 :<br/>1、滚动组件触发滚动后停止,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用后开始,带过渡动效,。 |
Z
zengyawen 已提交
58

C
caocan 已提交
59
>  **说明:**
G
gmy 已提交
60
>
Y
yeyinglong 已提交
61
>  若通过onScrollFrameBegin事件和scrollBy方法实现容器嵌套滚动,需设置子滚动节点的EdgeEffect为None。如Scroll嵌套List滚动时,List组件的edgeEffect属性需设置为EdgeEffect.None。
C
caocan 已提交
62

Z
zengyawen 已提交
63
## Scroller
Z
zengyawen 已提交
64

Z
zhangrongjie 已提交
65
可滚动容器组件的控制器,可以将此组件绑定至容器组件,然后通过它控制容器组件的滚动,同一个控制器不可以控制多个容器组件,目前支持绑定到List、Scroll、ScrollBar、Grid、WaterFlow上。
Z
zengyawen 已提交
66

Z
zengyawen 已提交
67 68

### 导入对象
Z
zengyawen 已提交
69 70 71 72 73 74

```
scroller: Scroller = new Scroller()
```


75
### scrollTo
Z
zengyawen 已提交
76

S
sunjiakun 已提交
77
scrollTo(value: { xOffset: number | string, yOffset: number | string, animation?: { duration?: number, curve?: Curve | ICurve } | boolean }): void
Z
zengyawen 已提交
78

Z
zengyawen 已提交
79 80 81

滑动到指定位置。

G
gmy 已提交
82
**参数:**
Z
zengyawen 已提交
83

G
gmy 已提交
84 85
| 参数名    | 参数类型                                                     | 必填 | 参数描述                                                     |
| --------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
Y
yamila 已提交
86 87
| xOffset   | number&nbsp;\|&nbsp;string                                   | 是   | 水平滑动偏移。<br/>**说明:** <br/>该参数值不支持设置百分比。<br/>仅滚动轴为x轴时生效。 |
| yOffset   | number&nbsp;\|&nbsp;string                                   | 是   | 垂直滑动偏移。<br/>**说明:** <br/>该参数值不支持设置百分比。<br/>仅滚动轴为y轴时生效。 |
L
luoying_ace_admin 已提交
88
| animation | {duration?:&nbsp;number, curve?:&nbsp;[Curve](ts-appendix-enums.md#curve)&nbsp;\|&nbsp;[ICurve](../apis/js-apis-curve.md#icurve)<sup>10+ </sup>}&nbsp;\|&nbsp;boolean<sup>10+ </sup> | 否   | 动画配置:<br/>-&nbsp;duration:&nbsp;滚动时长设置。<br/>-&nbsp;curve:&nbsp;滚动曲线设置。<br/>- boolean:&nbsp;使能默认弹簧动效。<br/>默认值: <br/>{<br/>duration:&nbsp;1000,<br/>curve:&nbsp;Curve.Ease<br/>}<br/>boolean:&nbsp;false<br/>**说明:** <br/>设置为小于0的值时,按默认值显示。<br/>当前List、Scroll、Grid、WaterFlow均支持boolean类型和ICurve曲线。 |
Z
zengyawen 已提交
89 90


91
### scrollEdge
Z
zengyawen 已提交
92 93 94

scrollEdge(value: Edge): void

Z
zengyawen 已提交
95

Z
zhangrongjie 已提交
96
滚动到容器边缘,不区分滚动轴方向,Edge.Top和Edge.Start表现相同,Edge.Bottom和Edge.End表现相同。
Z
zengyawen 已提交
97

G
gmy 已提交
98
**参数:**
Z
zengyawen 已提交
99

G
gmy 已提交
100 101 102
| 参数名   | 参数类型 | 必填   | 参数描述      |
| ----- | ---- | ---- | --------- |
| value | [Edge](ts-appendix-enums.md#edge) | 是    | 滚动到的边缘位置。 |
G
gmy 已提交
103

Z
zengyawen 已提交
104

105
### scrollPage
Z
zengyawen 已提交
106 107

scrollPage(value: { next: boolean, direction?: Axis }): void
Z
zengyawen 已提交
108 109

滚动到下一页或者上一页。
Z
zengyawen 已提交
110

G
gmy 已提交
111 112 113 114 115
**参数:**

| 参数名       | 参数类型    | 必填   | 参数描述                           |
| --------- | ------- | ---- | ------------------------------ |
| next      | boolean | 是    | 是否向下翻页。true表示向下翻页,false表示向上翻页。 |
116
| direction<sup>(deprecated) </sup> | [Axis](ts-appendix-enums.md#axis)    | 否    | 设置滚动方向为水平或竖直方向。<br/> 从API version 9开始废弃                |
Z
zengyawen 已提交
117 118


119
### currentOffset
Z
zengyawen 已提交
120

Y
yeyinglong 已提交
121
currentOffset(): { xOffset: number, yOffset: number }
Z
zengyawen 已提交
122

Z
zengyawen 已提交
123 124 125

返回当前的滚动偏移量。

G
gmy 已提交
126
**返回值**
Z
zengyawen 已提交
127

Y
yamila 已提交
128 129 130
| 类型                                                       | 描述                                                         |
| ---------------------------------------------------------- | ------------------------------------------------------------ |
| {<br/>xOffset:&nbsp;number,<br/>yOffset:&nbsp;number<br/>} | xOffset:&nbsp;水平滑动偏移;<br/>yOffset:&nbsp;竖直滑动偏移。<br/>**说明:** <br/>返回值单位为vp。 |
Z
zengyawen 已提交
131

Z
zengyawen 已提交
132

133
### scrollToIndex
Z
zengyawen 已提交
134

135
scrollToIndex(value: number, smooth?: boolean, align?: ScrollAlign): void
Z
zengyawen 已提交
136 137 138

滑动到指定Index。

L
limeng 已提交
139 140
开启smooth动效时,会对经过的所有item进行加载和布局计算,当大量加载item时会导致性能问题。

Z
zengyawen 已提交
141

H
geshi  
HelloCrease 已提交
142
>  **说明:**
G
gmy 已提交
143
>
Z
zhangrongjie 已提交
144
>  仅支持Grid、List、WaterFlow组件。
Z
zengyawen 已提交
145

G
gmy 已提交
146
**参数:**
Z
zengyawen 已提交
147

L
limeng 已提交
148 149
| 参数名                | 参数类型 | 必填 | 参数描述                                                     |
| --------------------- | -------- | ---- | ------------------------------------------------------------ |
150
| value                 | number   | 是   | 要滑动到的列表项在列表中的索引值。      <br/>**说明:** <br/>value值设置成负值或者大于当前List子组件的最大索引值,视为异常值,本次跳转不生效。                     |
151
| smooth<sup>10+ </sup> | boolean  | 否   | 设置滑动到列表项在列表中的索引值时是否有动效,true表示有动效,false表示没有动效。<br/>默认值:false。<br/>**说明:** <br/>当前仅List组件支持该参数。 |
152
| align<sup>10+ </sup> | [ScrollAlign](#scrollalign枚举说明)  | 否   | 指定滑动到的列表项与List的对齐方式。<br/>默认值:ScrollAlign.START。<br/>**说明:** <br/>当前仅List组件支持该参数。 |
Z
zengyawen 已提交
153

T
tianyu 已提交
154
### scrollBy<sup>9+</sup>
C
caocan 已提交
155 156 157 158 159 160 161 162

scrollBy(dx: Length, dy: Length): void


滑动指定距离。


>  **说明:**
G
gmy 已提交
163
>
Z
zhangrongjie 已提交
164
>  仅支持Scroll、ScrollBar、Grid、List组件。
C
caocan 已提交
165

G
gmy 已提交
166
**参数:**
C
caocan 已提交
167

G
gmy 已提交
168 169
| 参数名   | 参数类型   | 必填   | 参数描述              |
| ----- | ------ | ---- | ----------------- |
170 171
| dx | Length | 是    | 水平方向滚动距离,不支持百分比形式。 |
| dy | Length | 是    | 竖直方向滚动距离,不支持百分比形式。 |
C
caocan 已提交
172

173 174 175 176 177 178 179 180
## ScrollAlign枚举说明<sup>10+ </sup>

| 名称     | 描述                             |
| ------ | ------------------------------ |
| START   | 首部对齐。指定item首部与List首部对齐。  |
| CENTER | 居中对齐。指定item主轴方向居中对齐于List。        |
| END  | 尾部对齐。指定item尾部与List尾部对齐。 |
| AUTO  | 自动对齐。<br/>若指定item完全处于显示区,不做调整。否则依照滑动距离最短的原则,将指定item首部对齐或尾部对齐于List,使指定item完全处于显示区。|
C
caocan 已提交
181

Z
zengyawen 已提交
182
## 示例
S
sienna1128 已提交
183
### 示例1
Z
zengyawen 已提交
184

H
geshi  
HelloCrease 已提交
185 186
```ts
// xxx.ets
L
luoying_ace_admin 已提交
187 188
import Curves from '@ohos.curves'

Z
zengyawen 已提交
189 190 191
@Entry
@Component
struct ScrollExample {
Y
yamila 已提交
192 193
  scroller: Scroller = new Scroller()
  private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Z
zengyawen 已提交
194 195 196 197 198 199 200

  build() {
    Stack({ alignContent: Alignment.TopStart }) {
      Scroll(this.scroller) {
        Column() {
          ForEach(this.arr, (item) => {
            Text(item.toString())
G
gmy 已提交
201 202 203 204 205 206
              .width('90%')
              .height(150)
              .backgroundColor(0xFFFFFF)
              .borderRadius(15)
              .fontSize(16)
              .textAlign(TextAlign.Center)
Z
zengyawen 已提交
207 208 209 210
              .margin({ top: 10 })
          }, item => item)
        }.width('100%')
      }
S
sienna1128 已提交
211 212 213
      .scrollable(ScrollDirection.Vertical)  // 滚动方向纵向
      .scrollBar(BarState.On)  // 滚动条常驻显示
      .scrollBarColor(Color.Gray)  // 滚动条颜色
Y
yamila 已提交
214
      .scrollBarWidth(10) // 滚动条宽度
S
sienna1128 已提交
215
      .edgeEffect(EdgeEffect.None)
Z
zengyawen 已提交
216
      .onScroll((xOffset: number, yOffset: number) => {
Y
yamila 已提交
217
        console.info(xOffset + ' ' + yOffset)
Z
zengyawen 已提交
218 219
      })
      .onScrollEdge((side: Edge) => {
Y
yamila 已提交
220
        console.info('To the edge')
Z
zengyawen 已提交
221 222
      })
      .onScrollEnd(() => {
Y
yamila 已提交
223
        console.info('Scroll Stop')
Z
zengyawen 已提交
224
      })
S
sienna1128 已提交
225

G
gmy 已提交
226
      Button('scroll 150')
Y
yamila 已提交
227
        .height('5%')
G
gmy 已提交
228
        .onClick(() => { // 点击后下滑指定距离150.0vp
L
luoying_ace_admin 已提交
229
          this.scroller.scrollBy(0, 150)
G
gmy 已提交
230 231
        })
        .margin({ top: 10, left: 20 })
Z
zengyawen 已提交
232
      Button('scroll 100')
Y
yamila 已提交
233
        .height('5%')
G
gmy 已提交
234
        .onClick(() => { // 点击后滑动到指定位置,即下滑100.0vp的距离
Y
yamila 已提交
235
          this.scroller.scrollTo({ xOffset: 0, yOffset: this.scroller.currentOffset().yOffset + 100 })
Z
zengyawen 已提交
236
        })
G
gmy 已提交
237
        .margin({ top: 60, left: 20 })
L
luoying_ace_admin 已提交
238 239 240 241 242 243 244
      Button('scroll 100')
        .height('5%')
        .onClick(() => { // 点击后滑动到指定位置,即下滑100.0vp的距离,滑动过程配置有动画
          let curve = Curves.interpolatingSpring(100, 1, 228, 30) //创建一个阶梯曲线
          this.scroller.scrollTo({ xOffset: 0, yOffset: this.scroller.currentOffset().yOffset + 100, animation: { duration: 1000, curve: curve }})
        })
        .margin({ top: 110, left: 20 })
Z
zengyawen 已提交
245
      Button('back top')
Y
yamila 已提交
246
        .height('5%')
Z
zengyawen 已提交
247
        .onClick(() => { // 点击后回到顶部
Y
yamila 已提交
248
          this.scroller.scrollEdge(Edge.Top)
Z
zengyawen 已提交
249
        })
L
luoying_ace_admin 已提交
250
        .margin({ top: 160, left: 20 })
Z
zengyawen 已提交
251
      Button('next page')
Y
yamila 已提交
252
        .height('5%')
G
gmy 已提交
253
        .onClick(() => { // 点击后滑到下一页
Y
yamila 已提交
254
          this.scroller.scrollPage({ next: true })
Z
zengyawen 已提交
255
        })
L
luoying_ace_admin 已提交
256
        .margin({ top: 210, left: 20 })
Z
zengyawen 已提交
257 258 259 260 261
    }.width('100%').height('100%').backgroundColor(0xDCDCDC)
  }
}
```

Z
zengyawen 已提交
262
![zh-cn_image_0000001174104386](figures/zh-cn_image_0000001174104386.gif)
C
caocan 已提交
263

S
sienna1128 已提交
264
### 示例2
C
caocan 已提交
265 266 267 268
```ts
@Entry
@Component
struct NestedScroll {
S
sienna1128 已提交
269
  @State listPosition: number = 0; // 0代表滚动到List顶部,1代表中间值,2代表滚动到List底部。
Y
yamila 已提交
270
  private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Z
zhangrongjie 已提交
271 272
  private scrollerForScroll: Scroller = new Scroller()
  private scrollerForList: Scroller = new Scroller()
C
caocan 已提交
273 274 275

  build() {
    Flex() {
Z
zhangrongjie 已提交
276
      Scroll(this.scrollerForScroll) {
C
caocan 已提交
277 278 279 280
        Column() {
          Text("Scroll Area")
            .width("100%").height("40%").backgroundColor(0X330000FF)
            .fontSize(16).textAlign(TextAlign.Center)
Y
yamila 已提交
281
            .onClick(() => {
Z
zhangrongjie 已提交
282
              this.scrollerForList.scrollToIndex(5)
Y
yamila 已提交
283
            })
C
caocan 已提交
284

Z
zhangrongjie 已提交
285
          List({ space: 20, scroller: this.scrollerForList }) {
C
caocan 已提交
286 287 288 289 290 291 292 293
            ForEach(this.arr, (item) => {
              ListItem() {
                Text("ListItem" + item)
                  .width("100%").height("100%").borderRadius(15)
                  .fontSize(16).textAlign(TextAlign.Center).backgroundColor(Color.White)
              }.width("100%").height(100)
            }, item => item)
          }
Y
yamila 已提交
294 295 296
          .width("100%")
          .height("50%")
          .edgeEffect(EdgeEffect.None)
C
caocan 已提交
297
          .onReachStart(() => {
Y
yamila 已提交
298
            this.listPosition = 0
C
caocan 已提交
299 300
          })
          .onReachEnd(() => {
Y
yamila 已提交
301
            this.listPosition = 2
C
caocan 已提交
302
          })
Y
yeyinglong 已提交
303
          .onScrollFrameBegin((offset: number) => {
304 305
            if ((this.listPosition == 0 && offset <= 0) || (this.listPosition == 2 && offset >= 0)) {
              this.scrollerForScroll.scrollBy(0, offset)
Y
yeyinglong 已提交
306
              return { offsetRemain: 0 }
C
caocan 已提交
307
            }
Y
yamila 已提交
308
            this.listPosition = 1
Y
yeyinglong 已提交
309
            return { offsetRemain: offset };
C
caocan 已提交
310 311 312 313 314 315 316 317 318 319 320 321 322
          })

          Text("Scroll Area")
            .width("100%").height("40%").backgroundColor(0X330000FF)
            .fontSize(16).textAlign(TextAlign.Center)
        }
      }
      .width("100%").height("100%")
    }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20)
  }
}
```

L
luoying_ace_admin 已提交
323
![NestedScroll](figures/NestedScroll.gif)