1# @ohos.multimedia.movingphotoview (MovingPhotoView) 2 3The **MovingPhotoView** component is used to play moving photos and control the playback status. 4 5> **NOTE** 6> 7> - This component is supported since API version 12. Updates will be marked with a superscript to indicate their earliest API version. 8> - Currently, the **MovingPhotoView** component cannot be used in Previewer. 9 10## Modules to Import 11 12``` 13import { MovingPhotoView, MovingPhotoViewController, MovingPhotoViewAttribute } from '@kit.MediaLibraryKit'; 14``` 15 16## MovingPhotoView 17 18> **NOTE** 19> 20> - Currently, live attributes cannot be set. 21> - Currently, **expandSafeArea** in the ArkUI common attribute **ComponentOptions** cannot be set. 22> - When this component is long pressed to trigger playback, the component area is zoomed in to 1.1 times. 23> - This component uses [AVPlayer](../apis-media-kit/_a_v_player.md#avplayer) to play moving photos. A maximum of three [AVPlayers](../apis-media-kit/_a_v_player.md#avplayer) can be used at the same time. Otherwise, frame freezing may occur during the playback. 24 25MovingPhotoView(options: MovingPhotoViewOptions) 26 27**Parameters** 28 29 30| Name | Type | Mandatory| Description | 31| ------- | --------------------------------------------------------- | ---- | -------------- | 32| options | [MovingPhotoViewOptions](#movingphotoviewoptions) | Yes | Moving photo information.| 33 34## MovingPhotoViewOptions 35 36 37| Name | Type | Mandatory| Description | 38| ----------- | ------------------------------------------------------------------------------------------------ | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------- | 39| movingPhoto | [MovingPhoto](js-apis-photoAccessHelper.md#movingphoto12) | Yes | **MovingPhoto** instance. For details, see [MovingPhoto](js-apis-photoAccessHelper.md#movingphoto12).<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 40| controller | [MovingPhotoViewController](#movingphotoviewcontroller) | No | Controller used to control the playback status of the moving photo.<br>**Atomic service API**: This API can be used in atomic services since API version 12. | 41| imageAIOptions<sup>18+</sup> | [ImageAIOptions](../apis-arkui/arkui-ts/ts-image-common.md#imageaioptions) | No | AI options. You can set the image analyzer type or bind an image analyzer controller.<br>**Atomic service API**: This API can be used in atomic services since API version 18.| 42 43## Properties 44 45In addition to the [universal properties](../apis-arkui/arkui-ts/ts-component-general-attributes.md), the following properties are supported. 46 47### muted 48 49muted(isMuted: boolean) 50 51Sets whether to mute the player. 52 53**Atomic service API**: This API can be used in atomic services since API version 12. 54 55**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 56 57**Parameters** 58 59 60| Name | Type | Mandatory| Description | 61| ------- | ------- | ---- | ---------------------------- | 62| isMuted | boolean | Yes | Whether to mute the player.<br>Default value: **false**<br>The value **true** means to mute the player; the value **false** means the opposite.| 63 64### objectFit 65 66objectFit(value: ImageFit) 67 68Sets the display mode of the moving photo. 69 70**Atomic service API**: This API can be used in atomic services since API version 12. 71 72**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 73 74**Parameters** 75 76 77| Name| Type | Mandatory| Description | 78| ------ | ----------------------------------------------------------------------------- | ---- | -------------------------------- | 79| value | [ImageFit](../apis-arkui/arkui-ts/ts-appendix-enums.md#imagefit) | Yes | Image scale type.<br>Default value: **Cover**| 80 81### autoPlayPeriod<sup>13+</sup> 82 83autoPlayPeriod(startTime: number, endTime: number) 84 85Sets the autoplay period, which is a configuration item of **autoPlay**. 86 87Before this API is called, [autoPlay](#autoplay13) must be set to **true**. Otherwise, the specified video play period (**startTime**, **endTime**) does not take effect. 88 89**Atomic service API**: This API can be used in atomic services since API version 13. 90 91**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 92 93**Parameters** 94 95 96| Name | Type | Mandatory| Description | 97| ------- | ------- | ---- | ---------------------------- | 98| startTime| number| Yes | Start playback time, in ms.<br>The value must be greater than or equal to 0.| 99| endTime| number| Yes | End playback time, in ms.<br>The value must be greater than **startTime**.| 100 101### autoPlay<sup>13+</sup> 102 103autoPlay(isAutoPlay: boolean) 104 105Sets autoplay. After the moving photo is played once, a static image is displayed. 106 107**Atomic service API**: This API can be used in atomic services since API version 13. 108 109**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 110 111**Parameters** 112 113 114| Name | Type | Mandatory| Description | 115| ------- | ------- | ---- | ---------------------------- | 116| isAutoPlay| boolean| Yes | Whether to enable autoplay.<br>The value **true** means to enable autoplay; the value **false** means the opposite.<br>Default value: **false**| 117 118### repeatPlay<sup>13+</sup> 119 120repeatPlay(isRepeatPlay: boolean) 121 122Sets repeat play. **repeatPlay** is mutually exclusive with **autoPlay** and **Long Press**, and takes precedence over them. 123 124**Atomic service API**: This API can be used in atomic services since API version 13. 125 126**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 127 128**Parameters** 129 130 131| Name | Type | Mandatory| Description | 132| ------- | ------- | ---- | ---------------------------- | 133| isRepeatPlay| boolean| Yes | Whether to enable repeat play.<br>The value **true** means to enable repeat play; the value **false** means the opposite.<br>Default value: **false**| 134 135### enableAnalyzer<sup>18+</sup> 136 137enableAnalyzer(enabled: boolean) 138 139Sets the AI analyzer. Currently, the AI analyzer supports features, such as subject recognition, text recognition, and object search. 140 141**Atomic service API**: This API can be used in atomic services since API version 18. 142 143**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 144 145**Parameters** 146 147 148| Name | Type | Mandatory| Description | 149| ------- | ------- | ---- | ---------------------------- | 150| enabled| boolean| Yes | Whether to enable the AI analyzer.<br>The value **false** means to disable the AI analyzer; **true** means the opposite.<br>Default value: **true**| 151 152## Events 153 154In addition to [universal events](../apis-arkui/arkui-ts/ts-component-general-events.md), the following events are supported. 155 156### onComplete<sup>13+</sup> 157 158onComplete(callback: MovingPhotoViewEventCallback) 159 160Called when the image of a moving photo is loaded. 161 162**Atomic service API**: This API can be used in atomic services since API version 13. 163 164**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 165 166**Parameters** 167 168 169| Name | Type | Mandatory| Description | 170| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 171| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | Yes | Callback to be invoked when the image of a moving photo is loaded.| 172 173### onStart 174 175onStart(callback: MovingPhotoViewEventCallback) 176 177Called when a moving photo starts playing. 178 179**Atomic service API**: This API can be used in atomic services since API version 12. 180 181**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 182 183**Parameters** 184 185 186| Name | Type | Mandatory| Description | 187| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 188| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | Yes | Callback to be invoked when a moving photo starts playing.| 189 190### onPause 191 192onPause(callback: MovingPhotoViewEventCallback) 193 194Called when the playback is paused. 195 196**Atomic service API**: This API can be used in atomic services since API version 12. 197 198**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 199 200**Parameters** 201 202 203| Name | Type | Mandatory| Description | 204| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 205| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | Yes | Callback to be invoked when the playback of a moving photo is paused.| 206 207### onFinish 208 209onFinish(callback: MovingPhotoViewEventCallback) 210 211Called when the playback is finished. 212 213**Atomic service API**: This API can be used in atomic services since API version 12. 214 215**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 216 217**Parameters** 218 219 220| Name | Type | Mandatory| Description | 221| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 222| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | Yes | Callback to be invoked when the playback of a moving photo ends.| 223 224### onError 225 226onError(callback: MovingPhotoViewEventCallback) 227 228Called when the playback fails. 229 230**Atomic service API**: This API can be used in atomic services since API version 12. 231 232**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 233 234**Parameters** 235 236 237| Name | Type | Mandatory| Description | 238| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 239| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | Yes | Callback to be invoked when the playback of a moving photo fails.| 240 241### onStop 242 243onStop(callback: MovingPhotoViewEventCallback) 244 245Called when the playback is stopped by **stop()**. 246 247**Atomic service API**: This API can be used in atomic services since API version 12. 248 249**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 250 251**Parameters** 252 253 254| Name | Type | Mandatory| Description | 255| -------- | ------------------------------------------------------------- | ---- | ------------------------------ | 256| callback | [MovingPhotoViewEventCallback](#movingphotovieweventcallback) | Yes | Callback to be invoked when the playback of a moving photo is stopped.| 257 258## MovingPhotoViewEventCallback 259 260declare type MovingPhotoViewEventCallback = () => void 261 262Defines a callback to be invoked when the playback status of a moving photo changes. 263 264## MovingPhotoViewController 265 266A **MovingPhotoViewController** object can be used to control a **MovingPhotoView** component. For details, see [@ohos.multimedia.media](../apis-media-kit/js-apis-media.md). 267 268### startPlayback 269 270startPlayback(): void 271 272Starts playback. 273 274**Atomic service API**: This API can be used in atomic services since API version 12. 275 276**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 277 278### stopPlayback 279 280stopPlayback(): void 281 282Stops playback. Once started again, the playback starts from the beginning. 283 284**Atomic service API**: This API can be used in atomic services since API version 12. 285 286**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 287 288### refreshMovingPhoto<sup>18+</sup> 289 290refreshMovingPhoto(): void 291 292Forcibly refreshes the video and image resources loaded by the **MovingPhotoView** component. This API will interrupt the ongoing actions of the component. Exercise caution when using it. 293 294**Atomic service API**: This API can be used in atomic services since API version 18. 295 296**System capability**: SystemCapability.FileManagement.PhotoAccessHelper.Core 297 298## Example 1: Play a moving photo in multiple modes. 299 300```ts 301// xxx.ets 302import { photoAccessHelper } from '@kit.MediaLibraryKit'; 303import { emitter } from '@kit.BasicServicesKit'; 304import { dataSharePredicates } from '@kit.ArkData'; 305import { MovingPhotoView, MovingPhotoViewController, MovingPhotoViewAttribute } from '@kit.MediaLibraryKit'; 306 307const PHOTO_SELECT_EVENT_ID: number = 80001 308 309@Entry 310@Component 311struct MovingPhotoViewDemo { 312 @State src: photoAccessHelper.MovingPhoto | undefined = undefined 313 @State isMuted: boolean = false 314 controller: MovingPhotoViewController = new MovingPhotoViewController() 315 316 aboutToAppear(): void { 317 emitter.on({ 318 eventId: PHOTO_SELECT_EVENT_ID, 319 priority: emitter.EventPriority.IMMEDIATE, 320 }, (eventData: emitter.EventData) => { 321 this.src = AppStorage.get<photoAccessHelper.MovingPhoto>('mv_data') as photoAccessHelper.MovingPhoto 322 }) 323 } 324 325 aboutToDisappear(): void { 326 emitter.off(PHOTO_SELECT_EVENT_ID) 327 } 328 329 build() { 330 Column() { 331 Row() { 332 Button('PICK') 333 .margin(5) 334 .onClick(async () => { 335 let context = getContext(this) 336 try { 337 let uris: Array<string> = [] 338 const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions() 339 photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE 340 photoSelectOptions.maxSelectNumber = 2 341 const photoViewPicker = new photoAccessHelper.PhotoViewPicker() 342 let photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoViewPicker.select(photoSelectOptions) 343 uris = photoSelectResult.photoUris 344 if (uris[0]) { 345 this.handlePickerResult(context, uris[0], new MediaDataHandlerMovingPhoto()) 346 } 347 } catch (e) { 348 console.error(`pick file failed`) 349 } 350 }) 351 } 352 .alignItems(VerticalAlign.Center) 353 .justifyContent(FlexAlign.Center) 354 .height('15%') 355 356 Row() { 357 Column() { 358 MovingPhotoView({ 359 movingPhoto: this.src, 360 controller: this.controller 361 }) 362 .width('100%') 363 .height('100%') 364 .muted(this.isMuted) 365 .autoPlay(true) 366 .repeatPlay(false) 367 .autoPlayPeriod(0, 600) 368 .objectFit(ImageFit.Cover) 369 .onComplete(() => { 370 console.log('Completed'); 371 }) 372 .onStart(() => { 373 console.log('onStart') 374 }) 375 .onFinish(() => { 376 console.log('onFinish') 377 }) 378 .onStop(() => { 379 console.log('onStop') 380 }) 381 .onError(() => { 382 console.log('onError') 383 }) 384 } 385 } 386 .height('70%') 387 388 Row() { 389 Button('start') 390 .onClick(() => { 391 this.controller.startPlayback() 392 }) 393 .margin(5) 394 Button('stop') 395 .onClick(() => { 396 this.controller.stopPlayback() 397 }) 398 .margin(5) 399 Button('mute') 400 .onClick(() => { 401 this.isMuted = !this.isMuted 402 }) 403 .margin(5) 404 } 405 .alignItems(VerticalAlign.Center) 406 .justifyContent(FlexAlign.Center) 407 .height('15%') 408 } 409 } 410 411 async handlePickerResult(context: Context, uri: string, handler: photoAccessHelper.MediaAssetDataHandler<photoAccessHelper.MovingPhoto>): Promise<void> { 412 let uriPredicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates(); 413 uriPredicates.equalTo('uri', uri) 414 let fetchOptions: photoAccessHelper.FetchOptions = { 415 fetchColumns: [], 416 predicates: uriPredicates 417 }; 418 let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context) 419 let assetResult = await phAccessHelper.getAssets(fetchOptions) 420 let asset = await assetResult.getFirstObject() 421 let requestOptions: photoAccessHelper.RequestOptions = { 422 deliveryMode: photoAccessHelper.DeliveryMode.FAST_MODE, 423 } 424 try { 425 photoAccessHelper.MediaAssetManager.requestMovingPhoto(context, asset, requestOptions, handler) 426 } catch (err) { 427 console.error("request error: ", err) 428 } 429 } 430} 431 432class MediaDataHandlerMovingPhoto implements photoAccessHelper.MediaAssetDataHandler<photoAccessHelper.MovingPhoto> { 433 async onDataPrepared(movingPhoto: photoAccessHelper.MovingPhoto) { 434 AppStorage.setOrCreate('mv_data', movingPhoto) 435 emitter.emit({ 436 eventId: PHOTO_SELECT_EVENT_ID, 437 priority: emitter.EventPriority.IMMEDIATE, 438 }, { 439 }) 440 } 441} 442``` 443## Example 2: Enable the AI analyzer. 444 445```ts 446// xxx.ets 447import { photoAccessHelper } from '@kit.MediaLibraryKit'; 448import { emitter } from '@kit.BasicServicesKit'; 449import { dataSharePredicates } from '@kit.ArkData'; 450import { MovingPhotoView, MovingPhotoViewController, MovingPhotoViewAttribute } from '@kit.MediaLibraryKit'; 451import visionImageAnalyzer from '@hms.ai.visionImageAnalyzer'; 452const PHOTO_SELECT_EVENT_ID: number = 80001 453 454@Entry 455@Component 456struct MovingPhotoViewDemo { 457 @State src: photoAccessHelper.MovingPhoto | undefined = undefined 458 @State isMuted: boolean = false 459 controller: MovingPhotoViewController = new MovingPhotoViewController() 460 private aiController: visionImageAnalyzer.VisionImageAnalyzerController = 461 new visionImageAnalyzer.VisionImageAnalyzerController() 462 private options: ImageAIOptions = { 463 types: [ImageAnalyzerType.SUBJECT, ImageAnalyzerType.TEXT, ImageAnalyzerType.OBJECT_LOOKUP], 464 aiController: this.aiController 465 } 466 467 aboutToAppear(): void { 468 emitter.on({ 469 eventId: PHOTO_SELECT_EVENT_ID, 470 priority: emitter.EventPriority.IMMEDIATE, 471 }, (eventData: emitter.EventData) => { 472 this.src = AppStorage.get<photoAccessHelper.MovingPhoto>('mv_data') as photoAccessHelper.MovingPhoto 473 }) 474 } 475 476 aboutToDisappear(): void { 477 emitter.off(PHOTO_SELECT_EVENT_ID) 478 } 479 480 build() { 481 Column() { 482 Row() { 483 Button('PICK') 484 .margin(5) 485 .onClick(async () => { 486 let context = getContext(this) 487 try { 488 let uris: Array<string> = [] 489 const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions() 490 photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE 491 photoSelectOptions.maxSelectNumber = 2 492 const photoViewPicker = new photoAccessHelper.PhotoViewPicker() 493 let photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoViewPicker.select(photoSelectOptions) 494 uris = photoSelectResult.photoUris 495 if (uris[0]) { 496 this.handlePickerResult(context, uris[0], new MediaDataHandlerMovingPhoto()) 497 } 498 } catch (e) { 499 console.error(`pick file failed`) 500 } 501 }) 502 } 503 .alignItems(VerticalAlign.Center) 504 .justifyContent(FlexAlign.Center) 505 .height('15%') 506 507 Row() { 508 Column() { 509 MovingPhotoView({ 510 movingPhoto: this.src, 511 controller: this.controller, 512 imageAIOptions: this.options 513 }) 514 .width('100%') 515 .height('100%') 516 .muted(this.isMuted) 517 .autoPlay(true) 518 .repeatPlay(false) 519 .autoPlayPeriod(0, 600) 520 .objectFit(ImageFit.Cover) 521 .enableAnalyzer(true) 522 .onComplete(() => { 523 console.log('Completed'); 524 }) 525 .onStart(() => { 526 console.log('onStart') 527 }) 528 .onFinish(() => { 529 console.log('onFinish') 530 }) 531 .onStop(() => { 532 console.log('onStop') 533 }) 534 .onError(() => { 535 console.log('onError') 536 }) 537 } 538 } 539 .height('70%') 540 541 Row() { 542 Button('start') 543 .onClick(() => { 544 this.controller.startPlayback() 545 }) 546 .margin(5) 547 Button('stop') 548 .onClick(() => { 549 this.controller.stopPlayback() 550 }) 551 .margin(5) 552 Button('mute') 553 .onClick(() => { 554 this.isMuted = !this.isMuted 555 }) 556 .margin(5) 557 } 558 .alignItems(VerticalAlign.Center) 559 .justifyContent(FlexAlign.Center) 560 .height('15%') 561 } 562 } 563 564 async handlePickerResult(context: Context, uri: string, handler: photoAccessHelper.MediaAssetDataHandler<photoAccessHelper.MovingPhoto>): Promise<void> { 565 let uriPredicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates(); 566 uriPredicates.equalTo('uri', uri) 567 let fetchOptions: photoAccessHelper.FetchOptions = { 568 fetchColumns: [], 569 predicates: uriPredicates 570 }; 571 let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context) 572 let assetResult = await phAccessHelper.getAssets(fetchOptions) 573 let asset = await assetResult.getFirstObject() 574 let requestOptions: photoAccessHelper.RequestOptions = { 575 deliveryMode: photoAccessHelper.DeliveryMode.FAST_MODE, 576 } 577 try { 578 photoAccessHelper.MediaAssetManager.requestMovingPhoto(context, asset, requestOptions, handler) 579 } catch (err) { 580 console.error("request error: ", err) 581 } 582 } 583} 584 585class MediaDataHandlerMovingPhoto implements photoAccessHelper.MediaAssetDataHandler<photoAccessHelper.MovingPhoto> { 586 async onDataPrepared(movingPhoto: photoAccessHelper.MovingPhoto) { 587 AppStorage.setOrCreate('mv_data', movingPhoto) 588 emitter.emit({ 589 eventId: PHOTO_SELECT_EVENT_ID, 590 priority: emitter.EventPriority.IMMEDIATE, 591 }, { 592 }) 593 } 594} 595``` 596## Example 3: Use moving photos in an atomic service. 597 598```ts 599// xxx.ets 600import { photoAccessHelper, MovingPhotoView, MovingPhotoViewController, MovingPhotoViewAttribute } from '@kit.MediaLibraryKit'; 601 602let context = getContext(this) 603let data: photoAccessHelper.MovingPhoto 604async function loading() { 605 try { 606 // Ensure that the media assets corresponding to imageFileUri and videoFileUri exist in the application sandbox directory. 607 let imageFileUri = 'file://{bundleName}/data/storage/el2/base/haps/entry/files/xxx.jpg'; 608 let videoFileUri = 'file://{bundleName}/data/storage/el2/base/haps/entry/files/xxx.mp4'; 609 data = await photoAccessHelper.MediaAssetManager.loadMovingPhoto(context, imageFileUri, videoFileUri); 610 console.info('load moving photo successfully'); 611 } catch (err) { 612 console.error(`load moving photo failed with error: ${err.code}, ${err.message}`); 613 } 614} 615@Entry 616@Component 617struct Index { 618 controller: MovingPhotoViewController = new MovingPhotoViewController() 619 @State ImageFit: ImageFit | undefined | null = ImageFit.Contain; 620 @State flag: boolean = true; 621 @State autoPlayFlag: boolean = true; 622 @State repeatPlayFlag: boolean = false; 623 @State autoPlayPeriodStart: number = 0; 624 @State autoPlayPeriodEnd: number = 500; 625 aboutToAppear(): void { 626 loading() 627 } 628 629 build() { 630 NavDestination() { 631 Column() { 632 Stack({ alignContent: Alignment.BottomStart }) { 633 MovingPhotoView({ 634 movingPhoto: data, 635 controller: this.controller 636 }) 637 .width(300) 638 .height(400) 639 .muted(this.flag) 640 .objectFit(this.ImageFit) 641 .autoPlay(this.autoPlayFlag) 642 .autoPlayPeriod(this.autoPlayPeriodStart, this.autoPlayPeriodEnd) 643 .repeatPlay(this.repeatPlayFlag) 644 .onComplete(() => { 645 console.info('onComplete') 646 }) 647 .onStart(() => { 648 console.info('onStart') 649 }) 650 .onStop(() => { 651 console.info('onStop') 652 }) 653 .onPause(() => { 654 console.info('onPause') 655 }) 656 .onFinish(() => { 657 console.info('onFinish') 658 }) 659 .onError(() => { 660 console.info('onError') 661 }) 662 } 663 664 Row() { 665 Button('Play') 666 .onClick(() => { 667 this.controller.startPlayback() 668 }) 669 Button('StopPlay') 670 .onClick(() => { 671 this.controller.stopPlayback() 672 }) 673 Button('refreshMovingPhoto') 674 .onClick(() => { 675 this.controller.refreshMovingPhoto() 676 }) 677 Button('mute').id('MovingPhotoView_true') 678 .onClick(() => { 679 this.flag = false 680 }) 681 } 682 } 683 } 684 } 685} 686``` 687