1e41f4b71Sopenharmony_ci# Component Animation
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ciIn addition to universal property animation and transition animation APIs, ArkUI provides default animation effects for certain components, for example, the swipe effect for the [List](../reference/apis-arkui/arkui-ts/ts-container-list.md) component and the click effect of the [Button](../reference/apis-arkui/arkui-ts/ts-basic-components-button.md) component. Based on these default animation effects, you can apply custom animations to the child components through the property animation and transition animation APIs.
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ci## Using Default Component Animation
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ciThe default animation of a component exhibits the following features:
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci- Indicate the current state of the component. For example, after the user clicks a **Button** component, the component turns gray, indicating that it is selected.
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ci- Make UI interactions more intuitive and pleasurable.
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci- Reduce development workload, as the APIs are readily available.
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ciFor more effects, see [Component Overview](../reference/apis-arkui/arkui-ts/ts-container-flex.md).
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ciBelow is the sample code and effect:
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci
22e41f4b71Sopenharmony_ci```ts
23e41f4b71Sopenharmony_ci@Entry
24e41f4b71Sopenharmony_ci@Component
25e41f4b71Sopenharmony_cistruct ComponentDemo {
26e41f4b71Sopenharmony_ci  build() {
27e41f4b71Sopenharmony_ci    Row() {
28e41f4b71Sopenharmony_ci      Checkbox({ name: 'checkbox1', group: 'checkboxGroup' })
29e41f4b71Sopenharmony_ci        .select(true)
30e41f4b71Sopenharmony_ci        .shape(CheckBoxShape.CIRCLE)
31e41f4b71Sopenharmony_ci        .size({ width: 50, height: 50 })
32e41f4b71Sopenharmony_ci    }
33e41f4b71Sopenharmony_ci    .width('100%')
34e41f4b71Sopenharmony_ci    .height('100%')
35e41f4b71Sopenharmony_ci    .justifyContent(FlexAlign.Center)
36e41f4b71Sopenharmony_ci  }
37e41f4b71Sopenharmony_ci}
38e41f4b71Sopenharmony_ci```
39e41f4b71Sopenharmony_ci
40e41f4b71Sopenharmony_ci![en-us_image_0000001649338585](figures/en-us_image_0000001649338585.gif)
41e41f4b71Sopenharmony_ci
42e41f4b71Sopenharmony_ci
43e41f4b71Sopenharmony_ci
44e41f4b71Sopenharmony_ci## Customizing Component Animation
45e41f4b71Sopenharmony_ci
46e41f4b71Sopenharmony_ciSome components allow for animation customization for their child components through the [property animation](arkts-attribute-animation-overview.md) and [transition animation](arkts-transition-overview.md) APIs. For example, you can customize the swipe animation for child components of [Scroll](../reference/apis-arkui/arkui-ts/ts-container-scroll.md).
47e41f4b71Sopenharmony_ci
48e41f4b71Sopenharmony_ci- For a scroll or click gesture, you can implement various effects by changing affine properties of the child component.
49e41f4b71Sopenharmony_ci
50e41f4b71Sopenharmony_ci- To customize the animation for a scroll , you can add a listener to listen for scroll distance in the **onScroll** callback and calculate the affine property of each component. You can also define gestures, monitor positions through the gestures, and manually call **ScrollTo** to change the scrolled-to position.
51e41f4b71Sopenharmony_ci
52e41f4b71Sopenharmony_ci- Fine-tune the final scrolled-to position in the **onScrollStop** callback or gesture end callback.
53e41f4b71Sopenharmony_ci
54e41f4b71Sopenharmony_ciThe following is an example of customizing the swipe animation for the **Scroll** component:
55e41f4b71Sopenharmony_ci
56e41f4b71Sopenharmony_ci
57e41f4b71Sopenharmony_ci```ts
58e41f4b71Sopenharmony_ciimport { curves, window, display, mediaquery } from '@kit.ArkUI';
59e41f4b71Sopenharmony_ciimport { UIAbility } from '@kit.AbilityKit';
60e41f4b71Sopenharmony_ci
61e41f4b71Sopenharmony_ciexport default class GlobalContext extends AppStorage{
62e41f4b71Sopenharmony_ci  static mainWin: window.Window|undefined = undefined;
63e41f4b71Sopenharmony_ci  static mainWindowSize:window.Size|undefined = undefined;
64e41f4b71Sopenharmony_ci}
65e41f4b71Sopenharmony_ci/**
66e41f4b71Sopenharmony_ci * Encapsulates the WindowManager class.
67e41f4b71Sopenharmony_ci */
68e41f4b71Sopenharmony_ciexport class WindowManager {
69e41f4b71Sopenharmony_ci  private static instance: WindowManager|null = null;
70e41f4b71Sopenharmony_ci  private displayInfo: display.Display|null = null;
71e41f4b71Sopenharmony_ci  private orientationListener = mediaquery.matchMediaSync('(orientation: landscape)');
72e41f4b71Sopenharmony_ci
73e41f4b71Sopenharmony_ci  constructor() {
74e41f4b71Sopenharmony_ci    this.orientationListener.on('change', (mediaQueryResult: mediaquery.MediaQueryResult) => { this.onPortrait(mediaQueryResult) })
75e41f4b71Sopenharmony_ci    this.loadDisplayInfo()
76e41f4b71Sopenharmony_ci  }
77e41f4b71Sopenharmony_ci
78e41f4b71Sopenharmony_ci  /**
79e41f4b71Sopenharmony_ci   * Sets the main window.
80e41f4b71Sopenharmony_ci   * @param win Indicates the current application window.
81e41f4b71Sopenharmony_ci   */
82e41f4b71Sopenharmony_ci  setMainWin(win: window.Window) {
83e41f4b71Sopenharmony_ci    if (win == null) {
84e41f4b71Sopenharmony_ci      return
85e41f4b71Sopenharmony_ci    }
86e41f4b71Sopenharmony_ci    GlobalContext.mainWin = win;
87e41f4b71Sopenharmony_ci    win.on("windowSizeChange", (data: window.Size) => {
88e41f4b71Sopenharmony_ci      if (GlobalContext.mainWindowSize == undefined || GlobalContext.mainWindowSize == null) {
89e41f4b71Sopenharmony_ci        GlobalContext.mainWindowSize = data;
90e41f4b71Sopenharmony_ci      } else {
91e41f4b71Sopenharmony_ci        if (GlobalContext.mainWindowSize.width == data.width && GlobalContext.mainWindowSize.height == data.height) {
92e41f4b71Sopenharmony_ci          return
93e41f4b71Sopenharmony_ci        }
94e41f4b71Sopenharmony_ci        GlobalContext.mainWindowSize = data;
95e41f4b71Sopenharmony_ci      }
96e41f4b71Sopenharmony_ci
97e41f4b71Sopenharmony_ci      let winWidth = this.getMainWindowWidth();
98e41f4b71Sopenharmony_ci      AppStorage.setOrCreate<number>('mainWinWidth', winWidth)
99e41f4b71Sopenharmony_ci      let winHeight = this.getMainWindowHeight();
100e41f4b71Sopenharmony_ci      AppStorage.setOrCreate<number>('mainWinHeight', winHeight)
101e41f4b71Sopenharmony_ci      let context:UIAbility = new UIAbility()
102e41f4b71Sopenharmony_ci      context.context.eventHub.emit("windowSizeChange", winWidth, winHeight)
103e41f4b71Sopenharmony_ci    })
104e41f4b71Sopenharmony_ci  }
105e41f4b71Sopenharmony_ci
106e41f4b71Sopenharmony_ci  static getInstance(): WindowManager {
107e41f4b71Sopenharmony_ci    if (WindowManager.instance == null) {
108e41f4b71Sopenharmony_ci      WindowManager.instance = new WindowManager();
109e41f4b71Sopenharmony_ci    }
110e41f4b71Sopenharmony_ci    return WindowManager.instance
111e41f4b71Sopenharmony_ci  }
112e41f4b71Sopenharmony_ci
113e41f4b71Sopenharmony_ci  private onPortrait(mediaQueryResult: mediaquery.MediaQueryResult) {
114e41f4b71Sopenharmony_ci    if (mediaQueryResult.matches == AppStorage.get<boolean>('isLandscape')) {
115e41f4b71Sopenharmony_ci      return
116e41f4b71Sopenharmony_ci    }
117e41f4b71Sopenharmony_ci    AppStorage.setOrCreate<boolean>('isLandscape', mediaQueryResult.matches)
118e41f4b71Sopenharmony_ci    this.loadDisplayInfo()
119e41f4b71Sopenharmony_ci  }
120e41f4b71Sopenharmony_ci
121e41f4b71Sopenharmony_ci  /**
122e41f4b71Sopenharmony_ci   * Changes the screen orientation.
123e41f4b71Sopenharmony_ci   * @param ori Indicates the orientation.
124e41f4b71Sopenharmony_ci   */
125e41f4b71Sopenharmony_ci  changeOrientation(ori: window.Orientation) {
126e41f4b71Sopenharmony_ci    if (GlobalContext.mainWin != null) {
127e41f4b71Sopenharmony_ci      GlobalContext.mainWin.setPreferredOrientation(ori)
128e41f4b71Sopenharmony_ci    }
129e41f4b71Sopenharmony_ci  }
130e41f4b71Sopenharmony_ci
131e41f4b71Sopenharmony_ci  private loadDisplayInfo() {
132e41f4b71Sopenharmony_ci    this.displayInfo = display.getDefaultDisplaySync()
133e41f4b71Sopenharmony_ci    AppStorage.setOrCreate<number>('displayWidth', this.getDisplayWidth())
134e41f4b71Sopenharmony_ci    AppStorage.setOrCreate<number>('displayHeight', this.getDisplayHeight())
135e41f4b71Sopenharmony_ci  }
136e41f4b71Sopenharmony_ci
137e41f4b71Sopenharmony_ci  /**
138e41f4b71Sopenharmony_ci   * Obtains the width of the main window, in vp.
139e41f4b71Sopenharmony_ci   */
140e41f4b71Sopenharmony_ci  getMainWindowWidth(): number {
141e41f4b71Sopenharmony_ci    return GlobalContext.mainWindowSize != null ? px2vp(GlobalContext.mainWindowSize.width) : 0
142e41f4b71Sopenharmony_ci  }
143e41f4b71Sopenharmony_ci
144e41f4b71Sopenharmony_ci  /**
145e41f4b71Sopenharmony_ci   * Obtains the height of the main window, in vp.
146e41f4b71Sopenharmony_ci   */
147e41f4b71Sopenharmony_ci  getMainWindowHeight(): number {
148e41f4b71Sopenharmony_ci    return GlobalContext.mainWindowSize != null ? px2vp(GlobalContext.mainWindowSize.height) : 0
149e41f4b71Sopenharmony_ci  }
150e41f4b71Sopenharmony_ci
151e41f4b71Sopenharmony_ci  /**
152e41f4b71Sopenharmony_ci   * Obtains the screen width, in vp.
153e41f4b71Sopenharmony_ci   */
154e41f4b71Sopenharmony_ci  getDisplayWidth(): number {
155e41f4b71Sopenharmony_ci    return this.displayInfo != null ? px2vp(this.displayInfo.width) : 0
156e41f4b71Sopenharmony_ci  }
157e41f4b71Sopenharmony_ci
158e41f4b71Sopenharmony_ci  /**
159e41f4b71Sopenharmony_ci   * Obtains the screen height, in vp.
160e41f4b71Sopenharmony_ci   */
161e41f4b71Sopenharmony_ci  getDisplayHeight(): number {
162e41f4b71Sopenharmony_ci    return this.displayInfo != null ? px2vp(this.displayInfo.height) : 0
163e41f4b71Sopenharmony_ci  }
164e41f4b71Sopenharmony_ci
165e41f4b71Sopenharmony_ci  /**
166e41f4b71Sopenharmony_ci   * Releases resources.
167e41f4b71Sopenharmony_ci   */
168e41f4b71Sopenharmony_ci  release() {
169e41f4b71Sopenharmony_ci    if (this.orientationListener) {
170e41f4b71Sopenharmony_ci      this.orientationListener.off('change', (mediaQueryResult: mediaquery.MediaQueryResult) => { this.onPortrait(mediaQueryResult)})
171e41f4b71Sopenharmony_ci    }
172e41f4b71Sopenharmony_ci    if (GlobalContext.mainWin != null) {
173e41f4b71Sopenharmony_ci      GlobalContext.mainWin.off('windowSizeChange')
174e41f4b71Sopenharmony_ci    }
175e41f4b71Sopenharmony_ci    WindowManager.instance = null;
176e41f4b71Sopenharmony_ci  }
177e41f4b71Sopenharmony_ci}
178e41f4b71Sopenharmony_ci
179e41f4b71Sopenharmony_ci/**
180e41f4b71Sopenharmony_ci * Encapsulates the TaskData class.
181e41f4b71Sopenharmony_ci */
182e41f4b71Sopenharmony_ciexport class TaskData {
183e41f4b71Sopenharmony_ci  bgColor: Color | string | Resource = Color.White;
184e41f4b71Sopenharmony_ci  index: number = 0;
185e41f4b71Sopenharmony_ci  taskInfo: string = 'music';
186e41f4b71Sopenharmony_ci
187e41f4b71Sopenharmony_ci  constructor(bgColor: Color | string | Resource, index: number, taskInfo: string) {
188e41f4b71Sopenharmony_ci    this.bgColor = bgColor;
189e41f4b71Sopenharmony_ci    this.index = index;
190e41f4b71Sopenharmony_ci    this.taskInfo = taskInfo;
191e41f4b71Sopenharmony_ci  }
192e41f4b71Sopenharmony_ci}
193e41f4b71Sopenharmony_ci
194e41f4b71Sopenharmony_ciexport const taskDataArr: Array<TaskData> =
195e41f4b71Sopenharmony_ci  [
196e41f4b71Sopenharmony_ci    new TaskData('#317AF7', 0, 'music'),
197e41f4b71Sopenharmony_ci    new TaskData('#D94838', 1, 'mall'),
198e41f4b71Sopenharmony_ci    new TaskData('#DB6B42 ', 2, 'photos'),
199e41f4b71Sopenharmony_ci    new TaskData('#5BA854', 3, 'setting'),
200e41f4b71Sopenharmony_ci    new TaskData('#317AF7', 4, 'call'),
201e41f4b71Sopenharmony_ci    new TaskData('#D94838', 5, 'music'),
202e41f4b71Sopenharmony_ci    new TaskData('#DB6B42', 6, 'mall'),
203e41f4b71Sopenharmony_ci    new TaskData('#5BA854', 7, 'photos'),
204e41f4b71Sopenharmony_ci    new TaskData('#D94838', 8, 'setting'),
205e41f4b71Sopenharmony_ci    new TaskData('#DB6B42', 9, 'call'),
206e41f4b71Sopenharmony_ci    new TaskData('#5BA854', 10, 'music')
207e41f4b71Sopenharmony_ci
208e41f4b71Sopenharmony_ci  ];
209e41f4b71Sopenharmony_ci
210e41f4b71Sopenharmony_ci@Entry
211e41f4b71Sopenharmony_ci@Component
212e41f4b71Sopenharmony_ciexport struct TaskSwitchMainPage {
213e41f4b71Sopenharmony_ci  displayWidth: number = WindowManager.getInstance().getDisplayWidth();
214e41f4b71Sopenharmony_ci  scroller: Scroller = new Scroller();
215e41f4b71Sopenharmony_ci  cardSpace: number = 0; // Widget spacing
216e41f4b71Sopenharmony_ci  cardWidth: number = this.displayWidth / 2 - this.cardSpace / 2; // Widget width
217e41f4b71Sopenharmony_ci  cardHeight: number = 400; // Widget height
218e41f4b71Sopenharmony_ci  cardPosition: Array<number> = []; // Initial position of the widget
219e41f4b71Sopenharmony_ci  clickIndex: boolean = false;
220e41f4b71Sopenharmony_ci  @State taskViewOffsetX: number = 0;
221e41f4b71Sopenharmony_ci  @State cardOffset: number = this.displayWidth / 4;
222e41f4b71Sopenharmony_ci  lastCardOffset: number = this.cardOffset;
223e41f4b71Sopenharmony_ci  startTime: number|undefined=undefined
224e41f4b71Sopenharmony_ci
225e41f4b71Sopenharmony_ci  // Initial position of each widget
226e41f4b71Sopenharmony_ci  aboutToAppear() {
227e41f4b71Sopenharmony_ci    for (let i = 0; i < taskDataArr.length; i++) {
228e41f4b71Sopenharmony_ci      this.cardPosition[i] = i * (this.cardWidth + this.cardSpace);
229e41f4b71Sopenharmony_ci    }
230e41f4b71Sopenharmony_ci  }
231e41f4b71Sopenharmony_ci
232e41f4b71Sopenharmony_ci  // Position of each widget
233e41f4b71Sopenharmony_ci  getProgress(index: number): number {
234e41f4b71Sopenharmony_ci    let progress = (this.cardOffset + this.cardPosition[index] - this.taskViewOffsetX + this.cardWidth / 2) / this.displayWidth;
235e41f4b71Sopenharmony_ci    return progress
236e41f4b71Sopenharmony_ci  }
237e41f4b71Sopenharmony_ci
238e41f4b71Sopenharmony_ci  build() {
239e41f4b71Sopenharmony_ci    Stack({ alignContent: Alignment.Bottom }) {
240e41f4b71Sopenharmony_ci      // Background
241e41f4b71Sopenharmony_ci      Column()
242e41f4b71Sopenharmony_ci        .width('100%')
243e41f4b71Sopenharmony_ci        .height('100%')
244e41f4b71Sopenharmony_ci        .backgroundColor(0xF0F0F0)
245e41f4b71Sopenharmony_ci
246e41f4b71Sopenharmony_ci      // <Scroll> component
247e41f4b71Sopenharmony_ci      Scroll(this.scroller) {
248e41f4b71Sopenharmony_ci        Row({ space: this.cardSpace }) {
249e41f4b71Sopenharmony_ci          ForEach(taskDataArr, (item:TaskData, index) => {
250e41f4b71Sopenharmony_ci            Column()
251e41f4b71Sopenharmony_ci              .width(this.cardWidth)
252e41f4b71Sopenharmony_ci              .height(this.cardHeight)
253e41f4b71Sopenharmony_ci              .backgroundColor(item.bgColor)
254e41f4b71Sopenharmony_ci              .borderStyle(BorderStyle.Solid)
255e41f4b71Sopenharmony_ci              .borderWidth(1)
256e41f4b71Sopenharmony_ci              .borderColor(0xAFEEEE)
257e41f4b71Sopenharmony_ci              .borderRadius(15)
258e41f4b71Sopenharmony_ci                // Calculate the affine properties of child components.
259e41f4b71Sopenharmony_ci              .scale((this.getProgress(index) >= 0.4 && this.getProgress(index) <= 0.6) ?
260e41f4b71Sopenharmony_ci                {
261e41f4b71Sopenharmony_ci                  x: 1.1 - Math.abs(0.5 - this.getProgress(index)),
262e41f4b71Sopenharmony_ci                  y: 1.1 - Math.abs(0.5 - this.getProgress(index))
263e41f4b71Sopenharmony_ci                } :
264e41f4b71Sopenharmony_ci                { x: 1, y: 1 })
265e41f4b71Sopenharmony_ci              .animation({ curve: Curve.Smooth })
266e41f4b71Sopenharmony_ci                // Apply a pan animation.
267e41f4b71Sopenharmony_ci              .translate({ x: this.cardOffset })
268e41f4b71Sopenharmony_ci              .animation({ curve: curves.springMotion() })
269e41f4b71Sopenharmony_ci              .zIndex((this.getProgress(index) >= 0.4 && this.getProgress(index) <= 0.6) ? 2 : 1)
270e41f4b71Sopenharmony_ci          }, (item:TaskData) => item.toString())
271e41f4b71Sopenharmony_ci        }
272e41f4b71Sopenharmony_ci        .width((this.cardWidth + this.cardSpace) * (taskDataArr.length + 1))
273e41f4b71Sopenharmony_ci        .height('100%')
274e41f4b71Sopenharmony_ci      }
275e41f4b71Sopenharmony_ci      .gesture(
276e41f4b71Sopenharmony_ci        GestureGroup(GestureMode.Parallel,
277e41f4b71Sopenharmony_ci          PanGesture({ direction: PanDirection.Horizontal, distance: 5 })
278e41f4b71Sopenharmony_ci            .onActionStart((event: GestureEvent|undefined) => {
279e41f4b71Sopenharmony_ci              if(event){
280e41f4b71Sopenharmony_ci                this.startTime = event.timestamp;
281e41f4b71Sopenharmony_ci              }
282e41f4b71Sopenharmony_ci            })
283e41f4b71Sopenharmony_ci            .onActionUpdate((event: GestureEvent|undefined) => {
284e41f4b71Sopenharmony_ci              if(event){
285e41f4b71Sopenharmony_ci                this.cardOffset = this.lastCardOffset + event.offsetX;
286e41f4b71Sopenharmony_ci              }
287e41f4b71Sopenharmony_ci            })
288e41f4b71Sopenharmony_ci            .onActionEnd((event: GestureEvent|undefined) => {
289e41f4b71Sopenharmony_ci              if(event){
290e41f4b71Sopenharmony_ci                let time = 0
291e41f4b71Sopenharmony_ci                if(this.startTime){
292e41f4b71Sopenharmony_ci                  time = event.timestamp - this.startTime;
293e41f4b71Sopenharmony_ci                }
294e41f4b71Sopenharmony_ci                let speed = event.offsetX / (time / 1000000000);
295e41f4b71Sopenharmony_ci                let moveX = Math.pow(speed, 2) / 7000 * (speed > 0 ? 1 : -1);
296e41f4b71Sopenharmony_ci
297e41f4b71Sopenharmony_ci                this.cardOffset += moveX;
298e41f4b71Sopenharmony_ci                // When panning left to a position beyond the rightmost position
299e41f4b71Sopenharmony_ci                let cardOffsetMax = -(taskDataArr.length - 1) * (this.displayWidth / 2);
300e41f4b71Sopenharmony_ci                if (this.cardOffset < cardOffsetMax) {
301e41f4b71Sopenharmony_ci                  this.cardOffset = cardOffsetMax;
302e41f4b71Sopenharmony_ci                }
303e41f4b71Sopenharmony_ci                // When panning right to a position beyond the rightmost position
304e41f4b71Sopenharmony_ci                if (this.cardOffset > this.displayWidth / 4) {
305e41f4b71Sopenharmony_ci                  this.cardOffset = this.displayWidth / 4;
306e41f4b71Sopenharmony_ci                }
307e41f4b71Sopenharmony_ci
308e41f4b71Sopenharmony_ci                // Processing when the pan distance is less than the minimum distance
309e41f4b71Sopenharmony_ci                let remainMargin = this.cardOffset % (this.displayWidth / 2);
310e41f4b71Sopenharmony_ci                if (remainMargin < 0) {
311e41f4b71Sopenharmony_ci                  remainMargin = this.cardOffset % (this.displayWidth / 2) + this.displayWidth / 2;
312e41f4b71Sopenharmony_ci                }
313e41f4b71Sopenharmony_ci                if (remainMargin <= this.displayWidth / 4) {
314e41f4b71Sopenharmony_ci                  this.cardOffset += this.displayWidth / 4 - remainMargin;
315e41f4b71Sopenharmony_ci                } else {
316e41f4b71Sopenharmony_ci                  this.cardOffset -= this.displayWidth / 4 - (this.displayWidth / 2 - remainMargin);
317e41f4b71Sopenharmony_ci                }
318e41f4b71Sopenharmony_ci
319e41f4b71Sopenharmony_ci                // Record the pan offset.
320e41f4b71Sopenharmony_ci                this.lastCardOffset = this.cardOffset;
321e41f4b71Sopenharmony_ci              }
322e41f4b71Sopenharmony_ci            })
323e41f4b71Sopenharmony_ci        ), GestureMask.IgnoreInternal)
324e41f4b71Sopenharmony_ci      .scrollable(ScrollDirection.Horizontal)
325e41f4b71Sopenharmony_ci      .scrollBar(BarState.Off)
326e41f4b71Sopenharmony_ci
327e41f4b71Sopenharmony_ci      // Move to the beginning and end positions.
328e41f4b71Sopenharmony_ci      Button('Move to first/last')
329e41f4b71Sopenharmony_ci        .backgroundColor(0x888888)
330e41f4b71Sopenharmony_ci        .margin({ bottom: 30 })
331e41f4b71Sopenharmony_ci        .onClick(() => {
332e41f4b71Sopenharmony_ci          this.clickIndex = !this.clickIndex;
333e41f4b71Sopenharmony_ci
334e41f4b71Sopenharmony_ci          if (this.clickIndex) {
335e41f4b71Sopenharmony_ci            this.cardOffset = this.displayWidth / 4;
336e41f4b71Sopenharmony_ci          } else {
337e41f4b71Sopenharmony_ci            this.cardOffset = this.displayWidth / 4 - (taskDataArr.length - 1) * this.displayWidth / 2;
338e41f4b71Sopenharmony_ci          }
339e41f4b71Sopenharmony_ci          this.lastCardOffset = this.cardOffset;
340e41f4b71Sopenharmony_ci        })
341e41f4b71Sopenharmony_ci    }
342e41f4b71Sopenharmony_ci    .width('100%')
343e41f4b71Sopenharmony_ci    .height('100%')
344e41f4b71Sopenharmony_ci  }
345e41f4b71Sopenharmony_ci}
346e41f4b71Sopenharmony_ci```
347e41f4b71Sopenharmony_ci
348e41f4b71Sopenharmony_ci![en-us_image_0000001599808406](figures/en-us_image_0000001599808406.gif)
349