• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Creating an Arc Carousel Component (ArcSwiper) (Recommended for Circular Screens)
2
3
4**ArcSwiper** is an arc carousel component designed specifically for circular screens, allowing you to display content in an arc layout. For details, see [ArcSwiper](../reference/apis-arkui/arkui-ts/ts-container-arcswiper.md).
5
6Before using the **ArcSwiper** component, you need to import the **ArcSwiper** module in your code:
7
8```ts
9import {
10  ArcSwiper,
11  ArcSwiperAttribute,
12  ArcDotIndicator,
13  ArcDirection,
14  ArcSwiperController
15} from '@kit.ArkUI'
16```
17
18## Setting the Navigation Point Indicator Style
19
20**ArcSwiper** provides a default arc-shaped navigation point style, with the navigation points displayed centered below the **ArcSwiper**. You can customize the style of the arc-shaped navigation points using the [indicator](../reference/apis-arkui/arkui-ts/ts-container-arcswiper.md#indicator) attribute.
21
22Using the **indicator** attribute, you can set the direction of the arc-shaped navigation points and customize the colors of the points and the selected point.
23
24- Example of using the navigation point indicator in its default style:
25
26  ```ts
27  ArcSwiper() {
28    Text('0')
29      .width(233)
30      .height(233)
31      .backgroundColor(Color.Gray)
32      .textAlign(TextAlign.Center)
33      .fontSize(30)
34
35    Text('1')
36      .width(233)
37      .height(233)
38      .backgroundColor(Color.Green)
39      .textAlign(TextAlign.Center)
40      .fontSize(30)
41
42    Text('2')
43      .width(233)
44      .height(233)
45      .backgroundColor(Color.Pink)
46      .textAlign(TextAlign.Center)
47      .fontSize(30)
48  }
49  ```
50  ![indicator](figures/arcswiper_indicator.png)
51
52- Example of customizing the style of the navigation point indicator:
53
54  In this example, the navigation dots are positioned at the 6 o'clock direction of the **ArcSwiper** component, with the dot color set to red and the selected point color set to blue.
55
56  ```ts
57  ArcSwiper() {
58    // ...
59  }
60  .indicator(
61    new ArcDotIndicator()
62      .arcDirection(ArcDirection.SIX_CLOCK_DIRECTION) // Set the dots at the 6 o'clock direction.
63      .itemColor (Color.Red) // Set the dot color to red.
64      .selectedItemColor (Color.Blue) // Set the selected dot color to blue.
65  )
66  ```
67  ![indicator2](figures/arcswiper_indicator2.png)
68
69## Controlling Page Switching Modes
70
71The **ArcSwiper** component supports four page switching modes: swiping with fingers, touching navigation points, rotating the digital crown, and using a controller. The following examples demonstrate how to use a controller and the digital crown to switch between pages.
72
73- Using a controller to switch between pages
74
75  ```ts
76  // Import the ArcButton and ArcSwiper modules.
77  import {
78    ArcButton,
79    ArcButtonOptions,
80    ArcButtonStatus,
81    ArcButtonStyleMode,
82    ArcButtonPosition,
83    ArcSwiper,
84    ArcSwiperAttribute,
85    ArcDotIndicator,
86    ArcDirection,
87    ArcSwiperController
88  } from '@kit.ArkUI';
89
90  @Entry
91  @Component
92  struct SwiperCustomAnimationExample {
93    private wearableSwiperController: ArcSwiperController = new ArcSwiperController()
94
95    build() {
96      Column() {
97        Stack() {
98          ArcSwiper(this.wearableSwiperController) {
99            // ...
100          }
101          .vertical(true)
102          .indicator(false)
103
104          Column() {
105            ArcButton({
106              options: new ArcButtonOptions({
107                label: 'previous',
108                position: ArcButtonPosition.TOP_EDGE,
109                styleMode: ArcButtonStyleMode.EMPHASIZED_LIGHT,
110                onClick: () => {
111                  this.wearableSwiperController.showPrevious(); // Switch to the previous page using the controller.
112                }
113              })
114            })
115
116            Blank()
117
118            ArcButton({
119              options: new ArcButtonOptions({
120                label: 'next',
121                position: ArcButtonPosition.BOTTOM_EDGE,
122                styleMode: ArcButtonStyleMode.EMPHASIZED_LIGHT,
123                onClick: () => {
124                  this.wearableSwiperController.showNext(); // Switch to the next page using the controller.
125                }
126              })
127            })
128          }.width('100%').height('100%')
129        }
130      }
131    }
132  }
133  ```
134
135  ![controller](figures/arcswiper_controll.gif)
136
137- Using the digital crown to switch between pages
138
139  When the **ArcSwiper** component is focused, it can respond to digital crown rotations. Users can scroll through the **ArcSwiper** component by rotating the crown to browse content.
140
141  ```ts
142  ArcSwiper() {
143    // ...
144  }
145  .focusable(true)
146  .focusOnTouch(true)
147  .defaultFocus(true)
148  ```
149
150  You can also adjust the sensitivity of the digital crown to events using the [digitalCrownSensitivity](../reference/apis-arkui/arkui-ts/ts-container-arcswiper.md#digitalcrownsensitivity) attribute to adapt to different scales of data. For large datasets, you can increase the sensitivity; for smaller datasets, you can decrease it.
151
152  ```ts
153  ArcSwiper() {
154    // ...
155  }
156  .digitalCrownSensitivity(CrownSensitivity.MEDIUM)
157  ```
158
159## Setting the Swiping Direction
160
161The **ArcSwiper** component supports both horizontal and vertical swiping, controlled primarily by the [vertical](../reference/apis-arkui/arkui-ts/ts-container-arcswiper.md#vertical) attribute.
162
163When **vertical** is set to **true**, swiping occurs in the vertical direction. When **vertical** is set to **false**, swiping occurs in the horizontal direction. The default value is **false**.
164
165- Example of using horizontal swiping:
166
167  ```ts
168  ArcSwiper() {
169    // ...
170  }
171  .indicator(true)
172  .vertical(false)
173  ```
174  ![vertical](figures/arcswiper_indicator.png)
175
176
177- Example of using vertical swiping with dots at the 3 o'clock direction:
178
179  ```ts
180  ArcSwiper() {
181    // ...
182  }
183  .indicator(new ArcDotIndicator()
184      .arcDirection(ArcDirection.THREE_CLOCK_DIRECTION))
185  .vertical(true)
186  ```
187  ![vertical2](figures/arcswiper_vertical.png)
188
189## Customizing the Transition Animation
190
191Use the [customContentTransition](../reference/apis-arkui/arkui-ts/ts-container-arcswiper.md#customcontenttransition) attribute to set a custom transition animation for **ArcSwiper**. Define the animation by adjusting opacity, scale, translation, and rendering layer for all pages within the viewport frame by frame in the callback.
192
193```ts
194import { Decimal } from '@kit.ArkTS'
195
196@Entry
197@Component
198struct SwiperCustomAnimationExample {
199  private MIN_SCALE: number = 0.1
200  @State backgroundColors: Color[] = [Color.Green, Color.Blue, Color.Yellow, Color.Pink, Color.Gray, Color.Orange]
201  @State opacityList: number[] = []
202  @State scaleList: number[] = []
203
204  aboutToAppear(): void {
205    for (let i = 0; i < this.backgroundColors.length; i++) {
206      this.opacityList.push(1.0)
207      this.scaleList.push(1.0)
208    }
209  }
210
211  build() {
212    Column() {
213      ArcSwiper() {
214        ForEach(this.backgroundColors, (backgroundColor: Color, index: number) => {
215          Text(index.toString())
216            .width(233)
217            .height(233)
218            .fontSize(50)
219            .textAlign(TextAlign.Center)
220            .backgroundColor(backgroundColor)
221            .opacity(this.opacityList[index])
222            .scale({ x: this.scaleList[index], y: this.scaleList[index] })
223        })
224      }
225      .customContentTransition({
226        timeout: 1000,
227        transition: (proxy: SwiperContentTransitionProxy) => {
228          if (proxy.position <= -1 || proxy.position >= 1) {
229            // When a group of pages is completely scrolled out of the viewport, reset the attribute values.
230            this.opacityList[proxy.index] = 1.0
231            this.scaleList[proxy.index] = 1.0
232          } else {
233            let position: number = Decimal.abs(proxy.position).toNumber()
234            this.opacityList[proxy.index] = 1 - position
235            this.scaleList[proxy.index] =
236              this.MIN_SCALE + (1 - this.MIN_SCALE) * (1 - position)
237          }
238        }
239      })
240    }.width('100%')
241  }
242}
243```
244
245![customContentTransition](figures/arcswiper_custom_animation.gif)
246
247## Implementing Swipe-to-Return
248
249The swipe gesture of the **ArcSwiper** component may conflict with the swipe-to-return functionality. To resolve this, you can use [gesture judgment](../reference/apis-arkui/arkui-ts/ts-gesture-blocking-enhancement.md#ongesturerecognizerjudgebegin) to determine whether **ArcSwiper** has scrolled to the beginning. This allows you to intercept the swipe gesture and enable the swipe-to-return functionality.
250
251```ts
252@Entry
253@Component
254struct SwiperCustomAnimationExample {
255  @State backgroundColors: Color[] = [Color.Green, Color.Blue, Color.Yellow, Color.Pink, Color.Gray, Color.Orange]
256  innerSelectedIndex: number = 0
257
258  build() {
259    Column() {
260      ArcSwiper() {
261        ForEach(this.backgroundColors, (backgroundColor: Color, index: number) => {
262          Text(index.toString())
263            .width(233)
264            .height(233)
265            .fontSize(50)
266            .textAlign(TextAlign.Center)
267            .backgroundColor(backgroundColor)
268        })
269      }
270      .onAnimationStart((index: number, targetIndex: number) => {
271        this.innerSelectedIndex = targetIndex
272      })
273      .onGestureRecognizerJudgeBegin((event: BaseGestureEvent, current: GestureRecognizer,
274        others: Array<GestureRecognizer>): GestureJudgeResult => { // When the implementation is about to succeed, set the recognizer enabling state based on the current component state.
275        if (current) {
276          let target = current.getEventTargetInfo();
277          if (target && current.isBuiltIn() && current.getType() == GestureControl.GestureType.PAN_GESTURE) {
278            let swiperTaget = target as ScrollableTargetInfo
279            if (swiperTaget instanceof ScrollableTargetInfo &&
280              (swiperTaget.isBegin() || this.innerSelectedIndex === 0)) { // This condition checks whether ArcSwiper has scrolled to the beginning.
281              let panEvent = event as PanGestureEvent;
282              if (panEvent && panEvent.offsetX > 0 && (swiperTaget.isBegin() || this.innerSelectedIndex === 0)) {
283                return GestureJudgeResult.REJECT;
284              }
285            }
286          }
287        }
288        return GestureJudgeResult.CONTINUE;
289      })
290    }.width('100%')
291  }
292}
293```
294<!--no_check-->