1# Swiper 2 3 滑块视图容器,提供子组件滑动轮播显示的能力。 4 5> **说明:** 6> 7> 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 8 9 10## 子组件 11 12可以包含子组件。 13 14> **说明:** 15> 16> 子组件类型:系统组件和自定义组件,支持渲染控制类型([if/else](../../quick-start/arkts-rendering-control-ifelse.md)、[ForEach](../../quick-start/arkts-rendering-control-foreach.md)和[LazyForEach](../../quick-start/arkts-rendering-control-lazyforeach.md))。 17> 18> Swiper子组件的visibility属性设置为None,Swiper的displayMode属性设置为SwiperDisplayMode.AutoLinear或displayCount属性设置为'auto'时,对应子组件在视窗内不占位,但不影响导航点个数。 19> 20> Swiper子组件的visibility属性设置为None,或者visibility属性设置为Hidden时,对应子组件不显示,但依然会在视窗内占位。 21> 22> 当Swiper子组件个数小于等于Swiper组件内容区内显示的节点总个数(totalDisplayCount = DisplayCount + prevMargin? (1 : 0 ) + nextMargin? (1 : 0 ))时,按照非循环模式布局处理,此时,前后边距对应子组件不显示,但依然会在视窗内占位。Swiper组件按照totalDisplayCount个数判断测算规格。 23 24 25## 接口 26 27Swiper(controller?: SwiperController) 28 29**参数:** 30 31| 参数名 | 参数类型 | 必填 | 参数描述 | 32| ---------- | ------------------------------------- | ---- | -------------------- | 33| controller | [SwiperController](#swipercontroller) | 否 | 给组件绑定一个控制器,用来控制组件翻页。 | 34 35 36## 属性 37 38除支持[通用属性](ts-universal-attributes-size.md)外,还支持以下属性,不支持[Menu控制](ts-universal-attributes-menu.md)。 39 40| 名称 | 参数类型 | 描述 | 41| ------------------------------------- | ---------------------------------------- | ---------------------------------------- | 42| index | number | 设置当前在容器中显示的子组件的索引值。<br/>默认值:0<br/>**说明:** <br/>设置小于0或大于等于子组件数量时,按照默认值0处理。<br />从API version 10开始,该属性支持[$$](../../quick-start/arkts-two-way-sync.md)双向绑定变量。 | 43| autoPlay | boolean | 子组件是否自动播放。<br/>默认值:false<br/>**说明:** <br/>loop为false时,自动轮播到最后一页时停止轮播。手势切换后不是最后一页时继续播放。 | 44| interval | number | 使用自动播放时播放的时间间隔,单位为毫秒。<br/>默认值:3000 | 45| indicator<sup>10+</sup> | [DotIndicator](#dotindicator10) \| [DigitIndicator](#digitindicator10) \| boolean | 设置可选导航点指示器样式。<br/> \- DotIndicator:圆点指示器样式。<br/> \- DigitIndicator:数字指示器样式。<br/> \- boolean:是否启用导航点指示器。<br/> 默认值:true<br/> 默认类型:DotIndicator | 46| loop | boolean | 是否开启循环。<br>设置为true时表示开启循环,在LazyForEach懒循环加载模式下,加载的组件数量建议大于5个。<br/>默认值:true | 47| duration | number | 子组件切换的动画时长,单位为毫秒。<br/>默认值:400 | 48| vertical | boolean | 是否为纵向滑动。<br/>默认值:false | 49| itemSpace | number \| string | 设置子组件与子组件之间间隙。<br/>默认值:0<br/>**说明:** <br/>不支持设置百分比。 | 50| displayMode | SwiperDisplayMode | 主轴方向上元素排列的模式,优先以displayCount设置的个数显示,displayCount未设置时本属性生效。<br/>默认值:SwiperDisplayMode.Stretch | 51| cachedCount<sup>8+</sup> | number | 设置预加载子组件个数。<br/>默认值:1 | 52| disableSwipe<sup>8+</sup> | boolean | 禁用组件滑动切换功能。<br/>默认值:false | 53| curve<sup>8+</sup> | [Curve](ts-appendix-enums.md#curve) \| string | 设置Swiper的动画曲线,默认为淡入淡出曲线,常用曲线参考[Curve枚举说明](ts-appendix-enums.md#curve),也可以通过[插值计算](../apis/js-apis-curve.md)模块提供的接口创建自定义的插值曲线对象。<br/>默认值:Curve.Linear | 54| indicatorStyle<sup>(deprecated)</sup> | {<br/>left?: [Length](ts-types.md#length),<br/>top?: [Length](ts-types.md#length),<br/>right?: [Length](ts-types.md#length),<br/>bottom?: [Length](ts-types.md#length),<br/>size?: [Length](ts-types.md#length),<br/>mask?: boolean,<br/>color?: [ResourceColor](ts-types.md),<br/>selectedColor?: [ResourceColor](ts-types.md)<br/>} | 设置导航点样式:<br/>\- left: 设置导航点距离Swiper组件左边的距离。<br/>\- top: 设置导航点距离Swiper组件顶部的距离。<br/>\- right: 设置导航点距离Swiper组件右边的距离。<br/>\- bottom: 设置导航点距离Swiper组件底部的距离。<br/>\- size: 设置导航点的直径,不支持设置百分比。默认值:6vp。<br/>\- mask: 设置是否显示导航点蒙层样式。<br/>\- color: 设置导航点的颜色。<br/>\- selectedColor: 设置选中的导航点的颜色。 <br/>从API version 8开始支持,从API version 10开始不再维护,建议使用[indicator](#indicator10对象说明)代替。 | 55| displayCount<sup>8+</sup> | number \| string \| <br />[SwiperAutoFill](#swiperautofill10)<sup>10+</sup> | 设置一页内元素显示个数。<br/>默认值:1<br/>**说明:** <br/>字符串类型仅支持设置为'auto',显示效果同SwiperDisplayMode.AutoLinear。<br/>使用number类型且设置小于等于0时,按默认值1显示。<br/>使用number类型时,子组件按照主轴均分Swiper宽度(减去displayCount-1个itemSpace)的方式进行主轴拉伸(收缩)布局。<br/> 使用SwiperAutoFill类型时,通过设置一个子组件最小宽度值minSize,会根据Swiper当前宽度和minSize值自动计算并更改一页内元素显示个数。当minSize为空或者小于等于0时,Swiper显示1列。 | 56| effectMode<sup>8+</sup> | [EdgeEffect](ts-appendix-enums.md#edgeeffect) | 边缘滑动效果,loop = false时生效。 目前支持的滑动效果参见EdgeEffect的枚举说明。<br/>默认值:EdgeEffect.Spring<br/>**说明:** <br/>控制器接口调用时不生效回弹。 | 57| displayArrow<sup>10+</sup> | value:[ArrowStyle](#arrowstyle10) \| boolean,<br/>isHoverShow?: boolean | 设置导航点箭头样式。<br/>-value: 支持设置箭头和底板样式,异常场景使用ArrowStyle对象中的默认值。<br/>\-isHoverShow:设置鼠标悬停时是否显示箭头。<br/>默认值:false<br/>**说明:**<br/>isHoverShow为false时,常驻显示箭头,支持点击翻页。<br/>isHoverShow为true时,只有在鼠标悬停时才会显示箭头,并支持点击翻页。 | 58| nextMargin<sup>10+</sup> | <br/>[Length](ts-types.md#length)<br/> | 后边距,用于露出后一项的一小部分。<br/>默认值:0<br/>**说明:** <br/>仅当SwiperDisplayMode为STRETCH模式时生效。<br/>当主轴方向为横向布局时,nextmargin/prevmargin中任意一个大于子组件测算的宽度,nextmargin和prevmargin均不显示。<br/>当主轴方向为纵向布局时,nextmargin/prevmargin中任意一个大于子组件测算的高度,nextmargin和prevmargin均不显示。 | 59| prevMargin<sup>10+</sup> | <br/>[Length](ts-types.md#length)<br/> | 前边距,用于露出前一项的一小部分。<br/>默认值:0<br/>**说明:** <br/>仅当SwiperDisplayMode为STRETCH模式时生效。<br/>当主轴方向为横向布局时,nextmargin/prevmargin中任意一个大于子组件测算的宽度,prevmargin和nextmargin均不显示。<br/>当主轴方向为纵向布局时,nextmargin/prevmargin中任意一个大于子组件测算的高度,nextmargin和prevmargin均不显示。 | 60 61## SwiperDisplayMode枚举说明 62 63| 名称 | 描述 | 64| --------------------------------- | ---------------------------------------- | 65| Stretch<sup>(deprecated)</sup> | Swiper滑动一页的宽度为Swiper组件自身的宽度。<br>从API version 10开始不再维护,建议使用STRETCH代替。 | 66| AutoLinear<sup>(deprecated)</sup> | Swiper滑动一页的宽度为子组件宽度中的最大值。<br>从API version 10开始不再维护,建议使用AUTO_LINEAR代替。 | 67| STRETCH<sup>10+</sup> | Swiper滑动一页的宽度为Swiper组件自身的宽度。 | 68| AUTO_LINEAR<sup>10+</sup> | Swiper滑动一页的宽度为视窗内最左侧子组件的宽度。 | 69 70## SwiperController 71 72Swiper容器组件的控制器,可以将此对象绑定至Swiper组件,然后通过它控制翻页。 73 74### showNext 75 76showNext(): void 77 78翻至下一页。翻页带动效切换过程,时长通过duration指定。 79 80### showPrevious 81 82showPrevious(): void 83 84翻至上一页。翻页带动效切换过程,时长通过duration指定。 85 86### finishAnimation 87 88finishAnimation(callback?: () => void): void 89 90停止播放动画。 91 92**参数:** 93 94| 参数名 | 参数类型 | 必填项 | 参数描述 | 95| -------- | ---------- | ---- | -------- | 96| callback | () => void | 否 | 动画结束的回调。 | 97 98## Indicator<sup>10+</sup> 99 100设置导航点距离Swiper组件距离。 101 102| 参数名 | 参数类型 | 必填项 | 参数描述 | 103| ------ | ---------------------------- | ---- | ---------------------------------------- | 104| left | [Length](ts-types.md#length) | 否 | 设置导航点距离Swiper组件左边的距离。<br/>默认值:0<br/>单位:vp | 105| top | [Length](ts-types.md#length) | 否 | 设置导航点距离Swiper组件顶部的距离。<br/>默认值:0<br/>单位:vp | 106| right | [Length](ts-types.md#length) | 否 | 设置导航点距离Swiper组件右边的距离。<br/>默认值:0<br/>单位:vp | 107| bottom | [Length](ts-types.md#length) | 否 | 设置导航点距离Swiper组件底部的距离。<br/>默认值:0<br/>单位:vp | 108 109## DotIndicator<sup>10+</sup> 110 111圆点指示器属性及功能继承自Indicator。 112 113| 参数名 | 参数类型 | 必填项 | 参数描述 | 114| ------------------ | ---------------------------------------- | ---- | ---------------------------------------- | 115| itemWidth | [Length](ts-types.md#length) | 否 | 设置Swiper组件圆点导航指示器的宽,不支持设置百分比。<br/>默认值:6<br/>单位:vp | 116| itemHeight | [Length](ts-types.md#length) | 否 | 设置Swiper组件圆点导航指示器的高,不支持设置百分比。<br/>默认值:6<br/>单位:vp | 117| selectedItemWidth | [Length](ts-types.md#length) | 否 | 设置选中Swiper组件圆点导航指示器的宽,不支持设置百分比。<br/>默认值:12<br/>单位:vp | 118| selectedItemHeight | [Length](ts-types.md#length) | 否 | 设置选中Swiper组件圆点导航指示器的高,不支持设置百分比。<br/>默认值:6<br/>单位:vp | 119| mask | boolean | 否 | 设置是否显示Swiper组件圆点导航指示器的蒙版样式。<br/>默认值:false | 120| color | [ResourceColor](ts-types.md#resourcecolor) | 否 | 设置Swiper组件圆点导航指示器的颜色。<br/>默认值:'\#182431'(10%透明度) | 121| selectedColor | [ResourceColor](ts-types.md#resourcecolor) | 否 | 设置选中Swiper组件圆点导航指示器的颜色。<br/>默认值:'\#007DFF' | 122 123## DigitIndicator<sup>10+</sup> 124 125数字指示器属性及功能继承自Indicator。 126 127| 参数名 | 参数类型 | 必填项 | 参数描述 | 128| ----------------- | ---------------------------------------- | ---- | ---------------------------------------- | 129| fontColor | [ResourceColor](ts-types.md#resourcecolor) | 否 | 设置Swiper组件数字导航点的字体颜色。<br/>默认值:'\#ff182431' | 130| selectedFontColor | [ResourceColor](ts-types.md#resourcecolor) | 否 | 设置选中Swiper组件数字导航点的字体颜色。<br/>默认值:'\#ff182431' | 131| digitFont | {<br/>size?:[Length](ts-types.md#length)<br/>weight?:number \| [FontWeight](ts-appendix-enums.md#fontweight) \| string<br/>} | 否 | 设置Swiper组件数字导航点的字体样式:<br/>\- size:数字导航点指示器的字体大小,不支持设置百分比。<br/>默认值:14vp<br/>\- weight:数字导航点指示器的字重。 | 132| selectedDigitFont | {<br/>size?:[Length](ts-types.md#length)<br/>weight?:number \| [FontWeight](ts-appendix-enums.md#fontweight) \| string<br/>} | 否 | 设置选中Swiper组件数字导航点的字体样式:<br/>\- size:数字导航点选中指示器的字体大小,不支持设置百分比。<br/>默认值:14vp<br/>\- weight:数字导航点选中指示器的字重。 | 133 134## ArrowStyle<sup>10+</sup> 135左右箭头属性。 136 137| 参数名 | 参数类型 | 必填项 | 参数描述 | 138| ---------------- | ---------------------------------------- | ---- | ---------------------------------------- | 139| showBackground | boolean | 否 | 设置箭头底板是否显示。<br/>默认值:false | 140| isSidebarMiddle | boolean | 否 | 设置箭头显示位置。<br/>默认值:false <br/>默认显示在导航点指示器两侧。 | 141| backgroundSize | [Length](ts-types.md#length) | 否 | 设置底板大小。<br/>在导航点两侧显示:<br/>默认值:24vp<br/>在组件两侧显示:<br/>默认值:32vp<br/>不支持设置百分比。 | 142| backgroundColor | [ResourceColor](ts-types.md#resourcecolor) | 否 | 设置底板颜色。<br/>在导航点两侧显示:<br/>默认值:'\#00000000'<br/>在组件两侧显示:<br/>默认值:'\#19182431' | 143| arrowSize | [Length](ts-types.md#length) | 否 | 设置箭头大小。<br/>在导航点两侧显示时:<br/>默认值:18vp<br/>在组件两侧显示时:<br/>默认值:24vp<br/>**说明:**<br/>showBackground为true时,arrowSize为backgroundSize的3/4。<br/>不支持设置百分比。 | 144| arrowColor | [ResourceColor](ts-types.md#resourcecolor) | 否 | 设置箭头颜色。<br/>默认值:'\#182431' | 145 146## SwiperAutoFill<sup>10+</sup> 147 148自适应属性。 149 150| 参数名 | 参数类型 | 必填项 | 参数描述 | 151| ------- | -------------------- | ------ | ------------------------------------ | 152| minSize | [VP](ts-types.md#VP) | 是 | 设置元素显示最小宽度。<br/>默认值:0 | 153 154## 事件 155 156除支持[通用事件](ts-universal-events-click.md)外,还支持以下事件: 157 158| 名称 | 功能描述 | 159| ---------------------------------------- | ---------------------------------------- | 160| onChange(event: (index: number) => void) | 当前显示的子组件索引变化时触发该事件,返回值为当前显示的子组件的索引值。<br/>- index:当前显示元素的索引。<br/>**说明:** <br>Swiper组件结合LazyForEach使用时,不能在onChange事件里触发子页面UI的刷新。 | 161| onAnimationStart<sup>9+</sup>(event: (index: number, targetIndex<sup>10+</sup>: number, extraInfo<sup>10+</sup>: [SwiperAnimationEvent](ts-types.md#swiperanimationevent)) => void) | 切换动画开始时触发该回调。<br/>- index:当前显示元素的索引。<br/>- targetIndex:切换动画目标元素的索引。<br/>- extraInfo:动画相关信息,包括主轴方向上当前显示元素和目标元素相对Swiper起始位置的位移,以及离手速度。<br/>**说明:** <br/>参数为动画开始前的index值(不是最终结束动画的index值),多列Swiper时,index为最左侧组件的索引。 | 162| onAnimationEnd<sup>9+</sup>(event: (index: number, extraInfo: [SwiperAnimationEvent](ts-types.md#swiperanimationevent)) => void) | 切换动画结束时触发该回调。<br/>- index:当前显示元素的索引。<br/>- extraInfo:动画相关信息,只返回主轴方向上当前显示元素相对于Swiper起始位置的位移。<br/>**说明:** <br/>当Swiper切换动效结束时触发,包括动画过程中手势中断,通过SwiperController调用finishAnimation。参数为动画结束后的index值,多列Swiper时,index为最左侧组件的索引。 | 163| onGestureSwipe<sup>10+</sup>(event: (index: number, extraInfo: [SwiperAnimationEvent](ts-types.md#swiperanimationevent)) => void) | 在页面跟手滑动过程中,逐帧触发该回调。<br/>- index:当前显示元素的索引。<br/>- extraInfo:动画相关信息,只返回主轴方向上当前显示元素相对于Swiper起始位置的位移。<br/>**说明:** <br/>多列Swiper时,index为最左侧组件的索引。 | 164 165## 示例 166 167### 示例1 168```ts 169// xxx.ets 170class MyDataSource implements IDataSource { 171 private list: number[] = [] 172 173 constructor(list: number[]) { 174 this.list = list 175 } 176 177 totalCount(): number { 178 return this.list.length 179 } 180 181 getData(index: number): number { 182 return this.list[index] 183 } 184 185 registerDataChangeListener(listener: DataChangeListener): void { 186 } 187 188 unregisterDataChangeListener() { 189 } 190} 191 192@Entry 193@Component 194struct SwiperExample { 195 private swiperController: SwiperController = new SwiperController() 196 private data: MyDataSource = new MyDataSource([]) 197 198 aboutToAppear(): void { 199 let list: number[] = [] 200 for (let i = 1; i <= 10; i++) { 201 list.push(i); 202 } 203 this.data = new MyDataSource(list) 204 } 205 206 build() { 207 Column({ space: 5 }) { 208 Swiper(this.swiperController) { 209 LazyForEach(this.data, (item: string) => { 210 Text(item.toString()) 211 .width('90%') 212 .height(160) 213 .backgroundColor(0xAFEEEE) 214 .textAlign(TextAlign.Center) 215 .fontSize(30) 216 }, (item: string) => item) 217 } 218 .cachedCount(2) 219 .index(1) 220 .autoPlay(true) 221 .interval(4000) 222 .indicator(true) 223 .loop(true) 224 .duration(1000) 225 .itemSpace(0) 226 .displayArrow({ 227 showBackground: true, 228 isSidebarMiddle: true, 229 backgroundSize: 24, 230 backgroundColor: Color.White, 231 arrowSize: 18, 232 arrowColor: Color.Blue 233 }, false) 234 .curve(Curve.Linear) 235 .onChange((index: number) => { 236 console.info(index.toString()) 237 }) 238 .onGestureSwipe((index: number, extraInfo: SwiperAnimationEvent) => { 239 console.info("index: " + index) 240 console.info("current offset: " + extraInfo.currentOffset) 241 }) 242 .onAnimationStart((index: number, targetIndex: number, extraInfo: SwiperAnimationEvent) => { 243 console.info("index: " + index) 244 console.info("targetIndex: " + targetIndex) 245 console.info("current offset: " + extraInfo.currentOffset) 246 console.info("target offset: " + extraInfo.targetOffset) 247 console.info("velocity: " + extraInfo.velocity) 248 }) 249 .onAnimationEnd((index: number, extraInfo: SwiperAnimationEvent) => { 250 console.info("index: " + index) 251 console.info("current offset: " + extraInfo.currentOffset) 252 }) 253 254 Row({ space: 12 }) { 255 Button('showNext') 256 .onClick(() => { 257 this.swiperController.showNext() 258 }) 259 Button('showPrevious') 260 .onClick(() => { 261 this.swiperController.showPrevious() 262 }) 263 }.margin(5) 264 }.width('100%') 265 .margin({ top: 5 }) 266 } 267} 268``` 269 270 271 272### 示例2 273```ts 274// xxx.ets 275class MyDataSource implements IDataSource { 276 private list: number[] = [] 277 278 constructor(list: number[]) { 279 this.list = list 280 } 281 282 totalCount(): number { 283 return this.list.length 284 } 285 286 getData(index: number): number { 287 return this.list[index] 288 } 289 290 registerDataChangeListener(listener: DataChangeListener): void { 291 } 292 293 unregisterDataChangeListener() { 294 } 295} 296 297@Entry 298@Component 299struct SwiperExample { 300 private swiperController: SwiperController = new SwiperController() 301 private data: MyDataSource = new MyDataSource([]) 302 303 aboutToAppear(): void { 304 let list: number[] = [] 305 for (let i = 1; i <= 10; i++) { 306 list.push(i); 307 } 308 this.data = new MyDataSource(list) 309 } 310 311 build() { 312 Column({ space: 5 }) { 313 Swiper(this.swiperController) { 314 LazyForEach(this.data, (item: string) => { 315 Text(item.toString()) 316 .width('90%') 317 .height(160) 318 .backgroundColor(0xAFEEEE) 319 .textAlign(TextAlign.Center) 320 .fontSize(30) 321 }, (item: string) => item) 322 } 323 .cachedCount(2) 324 .index(1) 325 .autoPlay(true) 326 .interval(4000) 327 .indicator(Indicator.dot() 328 .itemWidth(15) 329 .itemHeight(15) 330 .selectedItemWidth(15) 331 .selectedItemHeight(15) 332 .color(Color.Gray) 333 .selectedColor(Color.Blue)) 334 .loop(true) 335 .duration(1000) 336 .itemSpace(0) 337 .displayArrow(true, true) 338 339 Row({ space: 12 }) { 340 Button('showNext') 341 .onClick(() => { 342 this.swiperController.showNext() 343 }) 344 Button('showPrevious') 345 .onClick(() => { 346 this.swiperController.showPrevious() 347 }) 348 }.margin(5) 349 }.width('100%') 350 .margin({ top: 5 }) 351 } 352} 353``` 354 355 356### 示例3 357```ts 358// xxx.ets 359class MyDataSource implements IDataSource { 360 private list: number[] = [] 361 362 constructor(list: number[]) { 363 this.list = list 364 } 365 366 totalCount(): number { 367 return this.list.length 368 } 369 370 getData(index: number): number { 371 return this.list[index] 372 } 373 374 registerDataChangeListener(listener: DataChangeListener): void { 375 } 376 377 unregisterDataChangeListener() { 378 } 379} 380 381@Entry 382@Component 383struct SwiperExample { 384 private swiperController: SwiperController = new SwiperController() 385 private data: MyDataSource = new MyDataSource([]) 386 387 aboutToAppear(): void { 388 let list: number[] = [] 389 for (let i = 1; i <= 10; i++) { 390 list.push(i); 391 } 392 this.data = new MyDataSource(list) 393 } 394 395 build() { 396 Column({ space: 5 }) { 397 Swiper(this.swiperController) { 398 LazyForEach(this.data, (item: string) => { 399 Text(item.toString()) 400 .width('90%') 401 .height(160) 402 .backgroundColor(0xAFEEEE) 403 .textAlign(TextAlign.Center) 404 .fontSize(30) 405 }, (item: string) => item) 406 } 407 .cachedCount(2) 408 .index(1) 409 .autoPlay(true) 410 .interval(4000) 411 .indicator(Indicator.digit() 412 .right("43%") 413 .top(200) 414 .fontColor(Color.Gray) 415 .selectedFontColor(Color.Gray) 416 .digitFont({ size: 20, weight: FontWeight.Bold }) 417 .selectedDigitFont({ size: 20, weight: FontWeight.Normal })) 418 .loop(true) 419 .duration(1000) 420 .itemSpace(0) 421 .displayArrow(true, false) 422 423 Row({ space: 12 }) { 424 Button('showNext') 425 .onClick(() => { 426 this.swiperController.showNext() 427 }) 428 Button('showPrevious') 429 .onClick(() => { 430 this.swiperController.showPrevious() 431 }) 432 }.margin(5) 433 }.width('100%') 434 .margin({ top: 5 }) 435 } 436} 437``` 438