• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 创建弧形轮播 (ArcSwiper)(圆形屏幕推荐使用)
2
3
4ArcSwiper是弧形轮播组件,用于圆形屏幕使用,提供弧形轮播显示能力。具体用法请参考[ArcSwiper](../reference/apis-arkui/arkui-ts/ts-container-arcswiper.md)。
5
6在使用ArcSwiper组件之前,需要在代码中先导入ArcSwiper模块。
7
8```ts
9import {
10  ArcSwiper,
11  ArcSwiperAttribute,
12  ArcDotIndicator,
13  ArcDirection,
14  ArcSwiperController
15} from '@kit.ArkUI'
16```
17
18## 设置导航点样式
19
20ArcSwiper提供了默认的弧形导航点样式,导航点默认显示在ArcSwiper下方居中位置,开发者也可以通过[indicator](../reference/apis-arkui/arkui-ts/ts-container-arcswiper.md#indicator)属性自定义弧形导航点的样式。
21
22通过indicator属性,开发者可以设置弧形导航点的方向,同时也可以设置导航点和被选中导航点的颜色。
23
24- 导航点使用默认样式
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- 自定义导航点样式
53
54  导航点位于ArcSwiper组件6点钟方向,导航点颜色设为红色,被选中导航点颜色为蓝色。
55
56  ```ts
57  ArcSwiper() {
58    // ...
59  }
60  .indicator(
61    new ArcDotIndicator()
62      .arcDirection(ArcDirection.SIX_CLOCK_DIRECTION) // 设置导航点位于6点钟方向
63      .itemColor(Color.Red) // 设置导航点颜色为红色
64      .selectedItemColor(Color.Blue) // 设置选中导航点颜色为蓝色
65  )
66  ```
67  ![indicator2](figures/arcswiper_indicator2.png)
68
69## 控制页面切换方式
70
71ArcSwiper支持滑动手指、点击导航点、旋转表冠和控制控制器四种方式切换页面。以下示例展示通过控制控制器和旋转表冠翻页的方法。
72
73- 控制控制器翻页。
74
75  ```ts
76  // 导入ArcButton和ArcSwiper模块
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(); // 通过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(); // 通过controller切换到后一页
125                }
126              })
127            })
128          }.width('100%').height('100%')
129        }
130      }
131    }
132  }
133  ```
134
135  ![controller](figures/arcswiper_controll.gif)
136
137- 旋转表冠翻页。
138
139  ArcSwiper在获得焦点时能够响应旋转表冠的操作,用户可以通过旋转表冠来滑动ArcSwiper,从而浏览数据。
140
141  ```ts
142  ArcSwiper() {
143    // ...
144  }
145  .focusable(true)
146  .focusOnTouch(true)
147  .defaultFocus(true)
148  ```
149
150  还可以通过设置[digitalCrownSensitivity](../reference/apis-arkui/arkui-ts/ts-container-arcswiper.md#digitalcrownsensitivity)属性来调整表冠对事件响应的灵敏度,以适应不同规模的数据处理。在处理大量数据时,可以提高响应事件的灵敏度;而在处理少量数据时,则可以降低灵敏度设置。
151
152  ```ts
153  ArcSwiper() {
154    // ...
155  }
156  .digitalCrownSensitivity(CrownSensitivity.MEDIUM)
157  ```
158
159## 设置轮播方向
160
161ArcSwiper支持水平和垂直方向上进行轮播,主要通过[vertical](../reference/apis-arkui/arkui-ts/ts-container-arcswiper.md#vertical)属性控制。
162
163当vertical为true时,表示在垂直方向上进行轮播;为false时,表示在水平方向上进行轮播。vertical默认值为false。
164
165- 设置水平方向上轮播。
166
167  ```ts
168  ArcSwiper() {
169    // ...
170  }
171  .indicator(true)
172  .vertical(false)
173  ```
174  ![vertical](figures/arcswiper_indicator.png)
175
176
177- 设置垂直方向轮播,导航点设为3点钟方向。
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## 自定义切换动画
190
191ArcSwiper支持通过[customContentTransition](../reference/apis-arkui/arkui-ts/ts-container-arcswiper.md#customcontenttransition)设置自定义切换动画,可以在回调中对视窗内所有页面逐帧设置透明度、缩放比例、位移、渲染层级等属性,从而实现自定义切换动画效果。
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            // 页面完全滑出视窗外时,重置属性值
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## 实现侧滑返回
248
249ArcSwiper的滑动事件会与侧滑返回冲突,可以通过[手势拦截](../reference/apis-arkui/arkui-ts/ts-gesture-blocking-enhancement.md#ongesturerecognizerjudgebegin)去判断ArcSwiper是否滑动到开头去拦截ArcSwiper的滑动手势,实现再次左滑返回上一页的功能。
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 => { // 在识别器即将要成功时,根据当前组件状态,设置识别器使能状态
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)) { // 此处判断swiperTaget.isBegin()或innerSelectedIndex === 0,表明ArcSwiper滑动到开头
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