1# Creating a Swiper (Swiper) 2 3 4The [Swiper](../reference/apis-arkui/arkui-ts/ts-container-swiper.md) component is a container that is able to display child components in looping mode. It is typically used in scenarios such as display of recommended content on the home page. 5 6The **Swiper** component provides a preloading mechanism, which you can use to improve the swipe experience in complex scenarios. This mechanism allows for prebuilding and prerendering components when the main thread is idle. <!--Del-->For details, see [High-Performance Swiper Development](../performance/swiper_optimization.md).<!--DelEnd--> 7 8 9## Layout and Constraints 10 11The **Swiper** component follows its own size settings if they are configured. If the component does not have its own size settings configured, it follows the size of its parent component when the **prevMargin** or **nextMargin** attribute is set, or adapts its size to its child components otherwise. 12 13 14## Loop Playback 15 16The **loop** attribute sets whether to enable loop playback. Its default value is **true**. 17 18When **loop** is set to **true**, the user can switch to the previous or next page when they are on the first or last page. 19 20- Example of setting **loop** to **true**: 21 22```ts 23Swiper() { 24 Text('0') 25 .width('90%') 26 .height('100%') 27 .backgroundColor(Color.Gray) 28 .textAlign(TextAlign.Center) 29 .fontSize(30) 30 31 Text('1') 32 .width('90%') 33 .height('100%') 34 .backgroundColor(Color.Green) 35 .textAlign(TextAlign.Center) 36 .fontSize(30) 37 38 Text('2') 39 .width('90%') 40 .height('100%') 41 .backgroundColor(Color.Pink) 42 .textAlign(TextAlign.Center) 43 .fontSize(30) 44} 45.loop(true) 46``` 47 48 49 50- Example of setting **loop** to **false**: 51 52```ts 53Swiper() { 54 // ... 55} 56.loop(false) 57``` 58 59 60 61 62## Automatic Playback 63 64The **autoPlay** attribute sets whether to enable automatic playback for child component switching. Its default value is **false**. 65 66When **autoPlay** is set to **true**, automatic playback is enabled for child component switching. The playback interval is specified by the **interval** attribute, which is **3000** by default, in milliseconds. 67 68```ts 69Swiper() { 70 // ... 71} 72.loop(true) 73.autoPlay(true) 74.interval(1000) 75``` 76 77 78 79 80## Navigation Indicator 81 82The **Swiper** component comes with default indicator and arrow styles, with the indicators centered at the bottom and arrows hidden. 83 84With the **indicator** attribute, you can set the position of the indicator relative to the edges of the **Swiper** component, in addition to the size, color, and mask of each indicator as well as the color of the selected indicator. 85 86- Example of using the navigation indicator in its default style: 87 88```ts 89Swiper() { 90 Text('0') 91 .width('90%') 92 .height('100%') 93 .backgroundColor(Color.Gray) 94 .textAlign(TextAlign.Center) 95 .fontSize(30) 96 97 Text('1') 98 .width('90%') 99 .height('100%') 100 .backgroundColor(Color.Green) 101 .textAlign(TextAlign.Center) 102 .fontSize(30) 103 104 Text('2') 105 .width('90%') 106 .height('100%') 107 .backgroundColor(Color.Pink) 108 .textAlign(TextAlign.Center) 109 .fontSize(30) 110} 111``` 112 113 114 115- Example of customizing the style of the navigation indicator, with the diameter of 30 vp, left margin of 0, and color of red: 116 117 118 119```ts 120Swiper() { 121 // ... 122} 123.indicator( 124 Indicator.dot() 125 .left(0) 126 .itemWidth(15) 127 .itemHeight(15) 128 .selectedItemWidth(30) 129 .selectedItemHeight(15) 130 .color(Color.Red) 131 .selectedColor(Color.Blue) 132) 133``` 134 135 136 137You can set the [displayArrow](../reference/apis-arkui/arkui-ts/ts-container-swiper.md#displayarrow10) attribute of **Swiper** to control the size, position, color, and background of navigation point arrows, and whether to display arrows on mouse hover. 138 139- Example of using the navigation point arrows in the default style: 140 141```ts 142Swiper() { 143 // ... 144} 145.displayArrow(true, false) 146``` 147 148 149 150- Example of customizing the style of navigation point arrows: 151 152In this example, the arrows are displayed on both sides of the component, with a size of 18 vp and a color of blue. 153 154```ts 155Swiper() { 156 // ... 157} 158.displayArrow({ 159 showBackground: true, 160 isSidebarMiddle: true, 161 backgroundSize: 24, 162 backgroundColor: Color.White, 163 arrowSize: 18, 164 arrowColor: Color.Blue 165 }, false) 166``` 167 168 169 170## Page Switching Mode 171 172The **Swiper** component supports three page switching modes: swiping with fingers, touching navigation points, and using a controller. The following example shows how to switch between pages using a controller. 173 174```ts 175@Entry 176@Component 177struct SwiperDemo { 178 private swiperBackgroundColors: Color[] = [Color.Blue, Color.Brown, Color.Gray, Color.Green, Color.Orange, 179 Color.Pink, Color.Red, Color.Yellow]; 180 private swiperAnimationMode: (SwiperAnimationMode | boolean | undefined)[] = [undefined, true, false, 181 SwiperAnimationMode.NO_ANIMATION, SwiperAnimationMode.DEFAULT_ANIMATION, SwiperAnimationMode.FAST_ANIMATION]; 182 private swiperController: SwiperController = new SwiperController(); 183 private animationModeIndex: number = 0; 184 private animationMode: (SwiperAnimationMode | boolean | undefined) = undefined; 185 @State animationModeStr: string = 'undefined'; 186 @State targetIndex: number = 0; 187 188 aboutToAppear(): void { 189 this.toSwiperAnimationModeStr(); 190 } 191 192 build() { 193 Column({ space: 5 }) { 194 Swiper(this.swiperController) { 195 ForEach(this.swiperBackgroundColors, (backgroundColor: Color, index: number) => { 196 Text(index.toString()) 197 .width(250) 198 .height(250) 199 .backgroundColor(backgroundColor) 200 .textAlign(TextAlign.Center) 201 .fontSize(30) 202 }) 203 } 204 .indicator(true) 205 206 Row({ space: 12 }) { 207 Button('showNext') 208 .onClick(() => { 209 this.swiperController.showNext(); // Switch to the next page using the controller. 210 }) 211 Button('showPrevious') 212 .onClick(() => { 213 this.swiperController.showPrevious(); // Switch to the previous page using the controller. 214 }) 215 }.margin(5) 216 217 Row({ space: 12 }) { 218 Text('Index:') 219 Button(this.targetIndex.toString()) 220 .onClick(() => { 221 this.targetIndex = (this.targetIndex + 1) % this.swiperBackgroundColors.length; 222 }) 223 }.margin(5) 224 Row({ space: 12 }) { 225 Text('AnimationMode:') 226 Button(this.animationModeStr) 227 .onClick(() => { 228 this.animationModeIndex = (this.animationModeIndex + 1) % this.swiperAnimationMode.length; 229 this.toSwiperAnimationModeStr(); 230 }) 231 }.margin(5) 232 233 Row({ space: 12 }) { 234 Button('changeIndex(' + this.targetIndex + ', ' + this.animationModeStr + ')') 235 .onClick(() => { 236 this.swiperController.changeIndex(this.targetIndex, this.animationMode); // Switch to the specified page using the controller. 237 }) 238 }.margin(5) 239 }.width('100%') 240 .margin({ top: 5 }) 241 } 242 243 private toSwiperAnimationModeStr() { 244 this.animationMode = this.swiperAnimationMode[this.animationModeIndex]; 245 if ((this.animationMode === true) || (this.animationMode === false)) { 246 this.animationModeStr = '' + this.animationMode; 247 } else if ((this.animationMode === SwiperAnimationMode.NO_ANIMATION) || 248 (this.animationMode === SwiperAnimationMode.DEFAULT_ANIMATION) || 249 (this.animationMode === SwiperAnimationMode.FAST_ANIMATION)) { 250 this.animationModeStr = SwiperAnimationMode[this.animationMode]; 251 } else { 252 this.animationModeStr = 'undefined'; 253 } 254 } 255} 256``` 257 258 259 260 261## Playback Direction 262 263You can set the playback direction for the Swiper component through its **vertical** attribute. 264 265When **vertical** is set to **true**, vertical swiping is used. The default value of **vertical** is **false**. 266 267 268- Example of using horizontal swiping: 269 270```ts 271Swiper() { 272 // ... 273} 274.indicator(true) 275.vertical(false) 276``` 277 278 279 280 281 282- Example of using vertical swiping: 283 284```ts 285Swiper() { 286 // ... 287} 288.indicator(true) 289.vertical(true) 290``` 291 292 293 294 295 296## Child Components Per Page 297 298You can set the number of child components per page for the **Swiper** component through its [displayCount](../reference/apis-arkui/arkui-ts/ts-container-swiper.md#displaycount8) attribute. 299 300```ts 301Swiper() { 302 Text('0') 303 .width(250) 304 .height(250) 305 .backgroundColor(Color.Gray) 306 .textAlign(TextAlign.Center) 307 .fontSize(30) 308 Text('1') 309 .width(250) 310 .height(250) 311 .backgroundColor(Color.Green) 312 .textAlign(TextAlign.Center) 313 .fontSize(30) 314 Text('2') 315 .width(250) 316 .height(250) 317 .backgroundColor(Color.Pink) 318 .textAlign(TextAlign.Center) 319 .fontSize(30) 320 Text('3') 321 .width(250) 322 .height(250) 323 .backgroundColor(Color.Blue) 324 .textAlign(TextAlign.Center) 325 .fontSize(30) 326} 327.indicator(true) 328.displayCount(2) 329``` 330 331 332 333## Customizing Transition Animation 334 335Use the [customContentTransition](../reference/apis-arkui/arkui-ts/ts-container-swiper.md#customcontenttransition12) attribute to set a custom transition animation for **Swiper**. Define the animation by adjusting opacity, scale, translation, and rendering layer for all pages within the viewport frame by frame in the callback. 336 337```ts 338@Entry 339@Component 340struct SwiperCustomAnimationExample { 341 private DISPLAY_COUNT: number = 2 342 private MIN_SCALE: number = 0.75 343 344 @State backgroundColors: Color[] = [Color.Green, Color.Blue, Color.Yellow, Color.Pink, Color.Gray, Color.Orange] 345 @State opacityList: number[] = [] 346 @State scaleList: number[] = [] 347 @State translateList: number[] = [] 348 @State zIndexList: number[] = [] 349 350 aboutToAppear(): void { 351 for (let i = 0; i < this.backgroundColors.length; i++) { 352 this.opacityList.push(1.0) 353 this.scaleList.push(1.0) 354 this.translateList.push(0.0) 355 this.zIndexList.push(0) 356 } 357 } 358 359 build() { 360 Column() { 361 Swiper() { 362 ForEach(this.backgroundColors, (backgroundColor: Color, index: number) => { 363 Text(index.toString()).width('100%').height('100%').fontSize(50).textAlign(TextAlign.Center) 364 .backgroundColor(backgroundColor) 365 .opacity(this.opacityList[index]) 366 .scale({ x: this.scaleList[index], y: this.scaleList[index] }) 367 .translate({ x: this.translateList[index] }) 368 .zIndex(this.zIndexList[index]) 369 }) 370 } 371 .height(300) 372 .indicator(false) 373 .displayCount(this.DISPLAY_COUNT, true) 374 .customContentTransition({ 375 timeout: 1000, 376 transition: (proxy: SwiperContentTransitionProxy) => { 377 if (proxy.position <= proxy.index % this.DISPLAY_COUNT || proxy.position >= this.DISPLAY_COUNT + proxy.index % this.DISPLAY_COUNT) { 378 // When a group of pages is completely scrolled out of the viewport, reset the attribute values. 379 this.opacityList[proxy.index] = 1.0 380 this.scaleList[proxy.index] = 1.0 381 this.translateList[proxy.index] = 0.0 382 this.zIndexList[proxy.index] = 0 383 } else { 384 // When a group of pages is not scrolled out of the viewport, adjust the attribute values frame by frame for the left and right pages in the group based on the position. 385 if (proxy.index % this.DISPLAY_COUNT === 0) { 386 this.opacityList[proxy.index] = 1 - proxy.position / this.DISPLAY_COUNT 387 this.scaleList[proxy.index] = this.MIN_SCALE + (1 - this.MIN_SCALE) * (1 - proxy.position / this.DISPLAY_COUNT) 388 this.translateList[proxy.index] = - proxy.position * proxy.mainAxisLength + (1 - this.scaleList[proxy.index]) * proxy.mainAxisLength / 2.0 389 } else { 390 this.opacityList[proxy.index] = 1 - (proxy.position - 1) / this.DISPLAY_COUNT 391 this.scaleList[proxy.index] = this.MIN_SCALE + (1 - this.MIN_SCALE) * (1 - (proxy.position - 1) / this.DISPLAY_COUNT) 392 this.translateList[proxy.index] = - (proxy.position - 1) * proxy.mainAxisLength - (1 - this.scaleList[proxy.index]) * proxy.mainAxisLength / 2.0 393 } 394 this.zIndexList[proxy.index] = -1 395 } 396 } 397 }) 398 }.width('100%') 399 } 400} 401``` 402 403 404