视频播放出现闪屏
========

#### 问题现象

当视频播放组件的生命周期开始时，界面短暂闪烁，出现其他视频中不期望出现的颜色。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/39/v3/N-YgC5HgRQa1MMLbRx20Ug/zh-cn_image_0000002658790425.png?HW-CC-KV=V1&HW-CC-Date=20260709T134002Z&HW-CC-Expire=86400&HW-CC-Sign=4A0437C185A186ABD83C6C5DE790C9211DFC16C0E53CB57996D1F41D90D24110 "点击放大")

#### 背景知识

*   [Video](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-media-components-video)：用于播放视频文件并控制其播放状态的组件。其previewUri参数可设置视频未播放时的预览图片。
*   [backgroundcolor](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-background#backgroundcolor)属性：通用属性，为组件添加背景颜色，默认为白色。

#### 问题定位

1.  使用DevEco Testing查看问题组件，该组件为Video组件。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/b9/v3/n-8oAzKNS_-qfGmJ2ZGpyA/zh-cn_image_0000002628551064.png?HW-CC-KV=V1&HW-CC-Date=20260709T134002Z&HW-CC-Expire=86400&HW-CC-Sign=166CDB39C531FCE47A2F1CEADC6884EA3A4239A78EE378B4A87E75CBB66CE48E "点击放大")
    
2.  查看该Video组件的设置，该Video组件未设置previewUri参数显示预览图。
    
    @Entry
    @Component
    export struct Index {
      @State videoSrc: ResourceStr = '';
      controller: VideoController = new VideoController();
    
      build() {
        Stack({ alignContent: Alignment.Start }) {
          Video({
            _// 未设置previewUri参数显示预览图_
            src: this.videoSrc,
            controller: this.controller
          })
        }
      }
    }
    

#### 分析结论

使用Video组件时，未通过previewUri参数设置预览图，在Video组件的加载过程中界面显示Video组件背景。这会导致在视频播放的过程中出现预期之外的色彩，引发闪屏问题。

#### 修改建议

使用Video组件时，通过previewUri参数设置预览图，避免短暂黑屏、白屏、彩屏的出现。

import { window } from '@kit.ArkUI';
import { common } from '@kit.AbilityKit';

interface DurationObject {
  duration: number;
}

interface TimeObject {
  time: number;
}

@Entry
@Component
struct Index {
  private imgSrc: ResourceStr = $r('app.media.myposter1'); _// $r('app.media.myposter1')需要替换为开发者需要的图片资源文件_
  @State videoSrc: ResourceStr = '';
  controller: VideoController = new VideoController();
  @State isPlay: boolean = false;
  @State durationTime: number = 0;
  @State currentTime: number = 0;
  @State sliderWidth: number = 230;
  @State @Watch('changeOrientation') isFull: boolean = false;
  context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;

  aboutToAppear(): void {
    _// 模拟视频加载_
    setTimeout(() => {
      this.videoSrc = $rawfile('video1.mp4'); _// $rawfile('video1.mp4')需要替换为开发者需要的视频资源文件_
    }, 1000);
    window.getLastWindow(this.context).then((lastWindow) => {
      lastWindow.setWindowLayoutFullScreen(true);
      let systemBarProperties: window.SystemBarProperties = {
        statusBarColor: '#00000000',
        statusBarContentColor: '#ffffff'
      };
      lastWindow.setWindowSystemBarProperties(systemBarProperties);
    });
  }

  timeConvert(time: number): string {
    let min: number = Math.floor(time / 60);
    let second: string = (time % 60).toFixed(0);
    second = second.padStart(2, '0');
    return \`${min}:${second}\`;
  }

  changeOrientation() {
    let context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
    window.getLastWindow(context).then((lastWindow) => {
      lastWindow.setPreferredOrientation(this.isFull ? window.Orientation.AUTO\_ROTATION\_LANDSCAPE :
        window.Orientation.PORTRAIT);
     _ // 进入全屏时进入沉浸式，退出全屏时再显示状态栏和导航栏_
      lastWindow.setWindowLayoutFullScreen(this.isFull);
      lastWindow.setWindowSystemBarEnable(this.isFull ? \[\] : \['status', 'navigation'\]);
    });
  }

  onPageHide(): void {
   _ // 应用退到后台时暂停视频_
    this.controller.pause();
  }

  onPageShow(): void {
    _// 应用返回时播放视频_
    this.controller.start();
  }

  build() {
    Stack({ alignContent: Alignment.Start }) {
      Video({
        previewUri: this.imgSrc, _// 设置previewUri参数显示预览图_
        src: this.videoSrc,
        controller: this.controller
      })
        .width('100%')
        .objectFit(ImageFit.Contain)
        .controls(false)
        .loop(true)
        .autoPlay(true)
        .backgroundColor(Color.Black)
        .onPrepared((e?: DurationObject) => {
          this.isPlay = true;
          if (e !== undefined) {
            this.durationTime = e.duration;
          }
        })
        .onUpdate((e?: TimeObject) => {
          if (e !== undefined) {
            this.currentTime = e.time;
          }
        })
        .onSizeChange(() => {
          this.sliderWidth = this.isFull ? 650 : 230;
        });

      Stack() {
        Row() {
         _ // $r('app.media.ic\_video\_play')和$r('app.media.ic\_video\_pause')需要替换为开发者需要的图片资源文件_
          Image(this.isPlay ? $r('app.media.ic\_video\_play') : $r('app.media.ic\_video\_pause'))
            .width(25)
            .height(25)
            .onClick(() => {
              if (this.isPlay) {
                this.controller.pause();
                this.isPlay = false;
              } else {
                this.controller.start();
                this.isPlay = true;
              }
            });

          _// 左侧时间_
          Text(this.timeConvert(this.currentTime))
            .fontColor(Color.White)
            .textAlign(TextAlign.End)
            .fontWeight(FontWeight.Regular)
            .margin({ left: 10 });

          Slider({
            value: this.currentTime,
            min: 0,
            max: this.durationTime,
            style: SliderStyle.OutSet
          })
            .blockColor(Color.White)
            .trackColor(Color.Gray)
            .selectedColor('#007DFF')
            .showTips(false)
            .width(this.sliderWidth)
            .onChange((value: number, mode: SliderChangeMode) => {
              if (mode === SliderChangeMode.Begin) {
                this.controller.pause();
              } else if (mode === SliderChangeMode.Moving) {
                this.controller.setCurrentTime(value);
              } else if (mode === SliderChangeMode.End) {
                this.controller.start();
              }
            });

         _ // 右侧时间_
          Text(this.timeConvert(this.durationTime))
            .id('durationTimeText')
            .fontColor(Color.White)
            .fontWeight(FontWeight.Regular);

         _ // $r('app.media.out')和$r('app.media.full')需要替换为开发者需要的图片资源文件_
          Image(this.isFull ? $r('app.media.out') : $r('app.media.full'))
            .width(20)
            .height(20)
            .objectFit(ImageFit.Contain)
            .onClick(() => {
              this.isFull = !this.isFull; _// 进入全屏或退出全屏_
            })
            .margin({ left: 5 });
        }
        .width('100%')
        .justifyContent(FlexAlign.Center)
        .padding({ left: 10, right: 5 })
        .margin({ bottom: 5 });
      }
      .width('100%')
      .height('100%')
      .alignContent(Alignment.Bottom);
    }
    .height('100%')
    .width('100%')
    .backgroundColor(Color.Black)
    .expandSafeArea(\[SafeAreaType.SYSTEM\], \[SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM\]); _// 扩展页面区域到导航栏和状态栏_
  }
}

效果图如下：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/1b/v3/ccCtrN6HQt-eSWKINPfCWw/zh-cn_image_0000002658910381.png?HW-CC-KV=V1&HW-CC-Date=20260709T134002Z&HW-CC-Expire=86400&HW-CC-Sign=87884D86EFB4C8FAAA1BF5B5CBB5C25555B0456902DA44FB499A3F78EA2DFEEE "点击放大")