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![loop_true](figures/loop_true.gif)
49
50- Example of setting **loop** to **false**:
51
52```ts
53Swiper() {
54  // ...
55}
56.loop(false)
57```
58
59![loop_false](figures/loop_false.gif)
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![autoPlay](figures/autoPlay.gif)
78
79
80## Navigation Point Indicator
81
82The **Swiper** component comes with default navigation point and arrow styles, with navigation dots centered at the bottom and arrows hidden.
83
84With the **indicator** attribute, you can set the position of the navigation point indicator relative to the edges of the **Swiper** component, in addition to the size, color, and mask of each navigation point as well as the color of the selected navigation point.
85
86- Example of using the navigation point 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![indicator](figures/indicator.PNG)
114
115- Example of customizing the style of the navigation dots 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![ind](figures/ind.PNG)
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![arrow1](figures/arrow1.gif)
149
150- Example of customizing the style of navigation point arrows as follows:
151
15218 vp size, blue color, on both sides of the component
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![arrow2](figures/arrow2.gif)
169
170## Page Switching Mode
171
172The **Swiper** component supports three page switching modes: using the swipe gesture, using the navigation dots indicator, and using the controller. The following example shows how to switch pages using the controller.
173
174```ts
175@Entry
176@Component
177struct SwiperDemo {
178  private swiperController: SwiperController = new SwiperController();
179
180  build() {
181    Column({ space: 5 }) {
182      Swiper(this.swiperController) {
183        Text('0')
184          .width(250)
185          .height(250)
186          .backgroundColor(Color.Gray)
187          .textAlign(TextAlign.Center)
188          .fontSize(30)
189        Text('1')
190          .width(250)
191          .height(250)
192          .backgroundColor(Color.Green)
193          .textAlign(TextAlign.Center)
194          .fontSize(30)
195        Text('2')
196          .width(250)
197          .height(250)
198          .backgroundColor(Color.Pink)
199          .textAlign(TextAlign.Center)
200          .fontSize(30)
201      }
202      .indicator(true)
203
204      Row({ space: 12 }) {
205        Button('showNext')
206          .onClick(() => {
207            this.swiperController.showNext(); // Switch to the next page through the controller.
208          })
209        Button('showPrevious')
210          .onClick(() => {
211            this.swiperController.showPrevious(); // Switch to the previous page through the controller.
212          })
213      }.margin(5)
214    }.width('100%')
215    .margin({ top: 5 })
216  }
217}
218```
219
220![controll](figures/controll.gif)
221
222
223## Playback Direction
224
225You can set the playback direction for the Swiper component through its **vertical** attribute.
226
227When **vertical** is set to **true**, vertical swiping is used. The default value of **vertical** is **false**.
228
229
230- Example of using horizontal swiping:
231
232```ts
233Swiper() {
234  // ...
235}
236.indicator(true)
237.vertical(false)
238```
239
240
241![horizontal-swiping](figures/horizontal-swiping.PNG)
242
243
244- Example of using vertical swiping:
245
246```ts
247Swiper() {
248  // ...
249}
250.indicator(true)
251.vertical(true)
252```
253
254
255![vertical-swiping](figures/vertical-swiping.PNG)
256
257
258## Child Components Per Page
259
260You 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#attributes) attribute.
261
262```ts
263Swiper() {
264  Text('0')
265    .width(250)
266    .height(250)
267    .backgroundColor(Color.Gray)
268    .textAlign(TextAlign.Center)
269    .fontSize(30)
270  Text('1')
271    .width(250)
272    .height(250)
273    .backgroundColor(Color.Green)
274    .textAlign(TextAlign.Center)
275    .fontSize(30)
276  Text('2')
277    .width(250)
278    .height(250)
279    .backgroundColor(Color.Pink)
280    .textAlign(TextAlign.Center)
281    .fontSize(30)
282  Text('3')
283    .width(250)
284    .height(250)
285    .backgroundColor(Color.Blue)
286    .textAlign(TextAlign.Center)
287    .fontSize(30)
288}
289.indicator(true)
290.displayCount(2)
291```
292
293![two](figures/two.PNG)
294
295## Customizing Transition Animation
296
297Use 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.
298
299```ts
300@Entry
301@Component
302struct SwiperCustomAnimationExample {
303  private DISPLAY_COUNT: number = 2
304  private MIN_SCALE: number = 0.75
305
306  @State backgroundColors: Color[] = [Color.Green, Color.Blue, Color.Yellow, Color.Pink, Color.Gray, Color.Orange]
307  @State opacityList: number[] = []
308  @State scaleList: number[] = []
309  @State translateList: number[] = []
310  @State zIndexList: number[] = []
311
312  aboutToAppear(): void {
313    for (let i = 0; i < this.backgroundColors.length; i++) {
314      this.opacityList.push(1.0)
315      this.scaleList.push(1.0)
316      this.translateList.push(0.0)
317      this.zIndexList.push(0)
318    }
319  }
320
321  build() {
322    Column() {
323      Swiper() {
324        ForEach(this.backgroundColors, (backgroundColor: Color, index: number) => {
325          Text(index.toString()).width('100%').height('100%').fontSize(50).textAlign(TextAlign.Center)
326            .backgroundColor(backgroundColor)
327            .opacity(this.opacityList[index])
328            .scale({ x: this.scaleList[index], y: this.scaleList[index] })
329            .translate({ x: this.translateList[index] })
330            .zIndex(this.zIndexList[index])
331        })
332      }
333      .height(300)
334      .indicator(false)
335      .displayCount(this.DISPLAY_COUNT, true)
336      .customContentTransition({
337        timeout: 1000,
338        transition: (proxy: SwiperContentTransitionProxy) => {
339          if (proxy.position <= proxy.index % this.DISPLAY_COUNT || proxy.position >= this.DISPLAY_COUNT + proxy.index % this.DISPLAY_COUNT) {
340            // When a group of pages is completely scrolled out of the viewport, reset the attribute values.
341            this.opacityList[proxy.index] = 1.0
342            this.scaleList[proxy.index] = 1.0
343            this.translateList[proxy.index] = 0.0
344            this.zIndexList[proxy.index] = 0
345          } else {
346            // 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.
347            if (proxy.index % this.DISPLAY_COUNT === 0) {
348              this.opacityList[proxy.index] = 1 - proxy.position / this.DISPLAY_COUNT
349              this.scaleList[proxy.index] = this.MIN_SCALE + (1 - this.MIN_SCALE) * (1 - proxy.position / this.DISPLAY_COUNT)
350              this.translateList[proxy.index] = - proxy.position * proxy.mainAxisLength + (1 - this.scaleList[proxy.index]) * proxy.mainAxisLength / 2.0
351            } else {
352              this.opacityList[proxy.index] = 1 - (proxy.position - 1) / this.DISPLAY_COUNT
353              this.scaleList[proxy.index] = this.MIN_SCALE + (1 - this.MIN_SCALE) * (1 - (proxy.position - 1) / this.DISPLAY_COUNT)
354              this.translateList[proxy.index] = - (proxy.position - 1) * proxy.mainAxisLength - (1 - this.scaleList[proxy.index]) * proxy.mainAxisLength / 2.0
355            }
356            this.zIndexList[proxy.index] = -1
357          }
358        }
359      })
360    }.width('100%')
361  }
362}
363```
364
365![customAnimation](figures/swiper-custom-animation.gif)
366
367