鸿蒙Next媒体展示组件实战:Video与动态布局全解析

今天我们来深入探讨HarmonyOS Next中几种核心媒体展示组件的使用方法,通过实际代码示例展示如何打造丰富的多媒体体验。

HarmonyOS Next为开发者提供了一套强大而灵活的媒体展示组件,使开发者能够轻松实现视频播放、动态布局适应、全屏切换等常见多媒体功能。无论是构建短视频应用、视频直播平台还是内容丰富的媒体浏览应用,这些组件都能提供强有力的支持。

本文将重点介绍Video组件、AVPlayer与XComponent的结合使用,以及如何通过媒体查询实现动态布局,帮助开发者快速掌握鸿蒙Next媒体开发的核心技能。

1. Video组件基础使用

Video组件是鸿蒙多媒体系统中最常用的组件之一,它提供了开箱即用的视频播放功能8。

1.1 基本参数配置

创建一个基础Video组件非常简单,以下是一个基本示例:

typescript

// Video基础使用示例
Video({
  src: $rawfile('video.mp4'), // 视频资源路径,支持本地和网络路径
  previewUri: $r('app.media.preview'), // 未播放时的预览图片
  controller: this.videoController // 视频控制器
})
.width('100%')
.aspectRatio(1.78) // 设置宽高比
.controls(true) // 显示控制栏
.autoPlay(false) // 不自动播放
.loop(false) // 不循环播放
.objectFit(ImageFit.Cover) // 视频显示模式
.onPrepared((event) => {
  console.info('视频准备完成,时长:' + event.duration + '秒');
})
.onUpdate((event) => {
  console.info('当前播放进度:' + event.time);
})
.onFinish(() => {
  console.info('视频播放结束');
})

Video组件支持多种参数配置:8

  • src: 视频源,支持本地路径(如$rawfile('video.mp4'))和网络URL

  • previewUri: 视频未播放时显示的预览图

  • controller: 视频控制器,用于控制播放、暂停等操作

  • currentProgressRate: 播放倍速,支持0.75、1.0、1.25、1.75、2.0

1.2 视频控制功能

通过VideoController可以实现对视频的精确控制:8

typescript

// 创建VideoController
private videoController: VideoController = new VideoController();

// 在build方法中使用
Video({
  src: this.videoSrc,
  controller: this.videoController
})

// 播放控制方法
playVideo() {
  this.videoController.start();
}

pauseVideo() {
  this.videoController.pause();
}

stopVideo() {
  this.videoController.stop();
}

seekTo(position: number) {
  this.videoController.seekTo(position);
}

2. 全屏切换功能实现

全屏切换是视频应用中的常见需求,鸿蒙Next提供了多种实现方式。

2.1 使用Video组件内置全屏功能

Video组件提供了onFullscreenChange回调,可以轻松实现全屏切换:6

typescript

Video({
  src: this.videoSrc,
  controller: this.videoController
})
.onFullscreenChange((event) => {
  // 横竖屏切换
  this.windowChange(event.fullscreen);
})

// 全屏切换方法
windowChange(isFullscreen: boolean) {
  let context = getContext(this);
  window.getLastWindow(context).then((lastWindow) => {
    if (isFullscreen) {
      // 设置全屏
      lastWindow.setPreferredOrientation(window.Orientation.AUTO_ROTATION_LANDSCAPE);
      lastWindow.setWindowSystemBarEnable([]); // 隐藏系统栏
    } else {
      // 退出全屏
      lastWindow.setPreferredOrientation(window.Orientation.PORTRAIT);
      lastWindow.setWindowSystemBarEnable(['status', 'navigation']); // 显示系统栏
    }
  });
}

2.2 使用AVPlayer和XComponent实现高级全屏功能

对于需要更自定义控制的场景,可以使用AVPlayer和XComponent组合:5

typescript

// 初始化AVPlayer
async initAVPlayer() {
  await this.release();
  const context = getContext(this);
  
  // 获取资源文件描述符
  context.resourceManager.getRawFd(this.fileName).then(async (value) => {
    this.avPlayer = await media.createAVPlayer();
    this.avPlayer.fdSrc = {
      fd: value.fd,
      offset: value.offset,
      length: value.length
    };
    
    // 设置surfaceId
    this.setSurfaceID();
  });
}

// 将XComponent与AVPlayer绑定
setSurfaceID() {
  this.avPlayer.surfaceId = this.surfaceID;
}

// 全屏切换动画
toggleFullScreen() {
  animateTo({
    duration: 300,
    onFinish: () => {
      this.isLandscape = !this.isLandscape;
      this.changeOrientation();
    }
  }, () => {
    this.isFullScreen = !this.isFullScreen;
  });
}

// 改变屏幕方向
changeOrientation() {
  let context = getContext(this);
  window.getLastWindow(context).then((lastWindow) => {
    if (this.isLandscape) {
      // 横屏模式
      lastWindow.setWindowLayoutFullScreen(true, () => {
        lastWindow.setWindowSystemBarEnable([]);
        lastWindow.setPreferredOrientation(window.Orientation.AUTO_ROTATION_LANDSCAPE);
      });
    } else {
      // 竖屏模式
      lastWindow.setPreferredOrientation(window.Orientation.UNSPECIFIED, () => {
        lastWindow.setWindowSystemBarEnable(['status', 'navigation'], () => {
          lastWindow.setWindowLayoutFullScreen(false);
        });
      });
    }
  });
}

3. 小窗口播放模式

小窗口播放是现代视频应用的重要特性,允许用户在浏览其他内容时继续观看视频13。

typescript

// 小窗口播放组件
@Component
struct SmallVideoComponent {
  private controller: VideoController;
  private currentTime: number = 0;

  build() {
    Column() {
      Video({
        src: $rawfile('video.mp4'),
        controller: this.controller
      })
      .width(200)
      .height(120)
      .controls(false)
      .objectFit(ImageFit.Cover)
      .onUpdate((event) => {
        this.currentTime = event.time;
      })
    }
    .onClick(() => {
      // 点击小窗口切换回全屏
      this.switchToFullScreen();
    })
  }
}

// 在主页中实现滚动时切换小窗口
@Entry@Component
struct MainPage {
  private scroller: Scroller = new Scroller();
  @State isSmallWindow: boolean = false;

  build() {
    Scroll(this.scroller) {
      Column() {
        // 主内容区域
        if (!this.isSmallWindow) {
          VideoPlayerComponent()
        }
        
        // 其他内容
        ForEach(this.contentList, (item) => {
          ContentItem(item)
        })
      }
      .onScroll(() => {
        // 滚动超过500vp时切换为小窗口
        if (this.scroller.currentOffset().yOffset > 500 && !this.isSmallWindow) {
          this.isSmallWindow = true;
        } else if (this.scroller.currentOffset().yOffset <= 500 && this.isSmallWindow) {
          this.isSmallWindow = false;
        }
      })
    }
    
    // 显示小窗口
    if (this.isSmallWindow) {
      SmallVideoComponent()
        .position({x: 20, y: 20})
    }
  }
}

4. 基于媒体查询的动态布局

鸿蒙的媒体查询模块允许根据设备特性动态调整布局,提供响应式体验2。

typescript

import mediaquery from '@ohos.mediaquery';

// 创建媒体查询监听器
let resolutionListener = mediaquery.matchMediaSync('(resolution > 2dppx)');
let orientationListener = mediaquery.matchMediaSync('(orientation: landscape)');

// 根据设备分辨率调整布局
resolutionListener.on('change', (mediaQueryResult) => {
  if (mediaQueryResult.matches) {
    // 高分辨率设备布局
    this.videoWidth = '100%';
    this.videoHeight = 360;
    this.controlsSize = 24;
  } else {
    // 低分辨率设备布局
    this.videoWidth = '100%';
    this.videoHeight = 240;
    this.controlsSize = 20;
  }
});

// 根据屏幕方向调整布局
orientationListener.on('change', (mediaQueryResult) => {
  if (mediaQueryResult.matches) {
    // 横屏布局
    this.isLandscape = true;
    this.videoWidth = '100%';
    this.videoHeight = '100%';
  } else {
    // 竖屏布局
    this.isLandscape = false;
    this.videoWidth = '100%';
    this.videoHeight = 300;
  }
});

// 在组件中使用响应式变量
Video({
  src: this.videoSrc,
  controller: this.videoController
})
.width(this.videoWidth)
.height(this.videoHeight)
.controls(true)

5. 直播流媒体实现

鸿蒙Next同样支持直播流媒体播放,以下是实现直播功能的关键代码13:

typescript

// 直播页面组件
@Component
struct LivePage {
  private liveController: VideoController = new VideoController();
  @State currentLive: LiveDataModel = null;
  @State liveList: LiveDataModel[] = [];

  aboutToAppear() {
    // 获取直播数据
    this.getLiveData();
  }

  // 获取直播数据
  async getLiveData() {
    try {
      this.liveList = await LiveUtils.getLiveList();
      if (this.liveList.length > 0) {
        this.currentLive = this.liveList[0];
      }
    } catch (error) {
      console.error('获取直播数据失败: ' + JSON.stringify(error));
    }
  }

  build() {
    Swiper() {
      ForEach(this.liveList, (liveItem) => {
        Column() {
          Video({
            src: liveItem.streamUrl,
            controller: this.liveController
          })
          .width('100%')
          .height('100%')
          .objectFit(ImageFit.Cover)
          .controls(true)
          .loop(true)
          
          // 直播叠加信息
          LiveOverlay(liveItem)
        }
      })
    }
    .index(this.currentIndex)
    .autoPlay(false)
    .indicator(false)
    .vertical(true)
    .onChange((index) => {
      // 切换直播流
      this.liveController.stop();
      this.currentLive = this.liveList[index];
      this.liveController.start();
    })
  }
}

6. 性能优化技巧

在媒体应用开发中,性能优化至关重要56。

6.1 使用LazyForEach懒加载

typescript

// 使用LazyForEach优化长列表性能
LazyForEach(this.liveDataSource, (liveItem: LiveDataModel) => {
  LiveItemComponent({ liveItem: liveItem })
}, (liveItem: LiveDataModel) => liveItem.id.toString())

6.2 组件复用优化

typescript

// 使用@Reusable装饰器实现组件复用
@Reusable
@Component
struct VideoPlayerComponent {
  @Prop videoItem: VideoItem;

  build() {
    Column() {
      Video({
        src: this.videoItem.url,
        previewUri: this.videoItem.thumbnail
      })
      .width('100%')
      .height(200)
    }
  }
}

总结

HarmonyOS Next提供了丰富而强大的媒体展示组件,从简单的Video组件到高级的AVPlayer与XComponent组合,可以满足各种多媒体应用场景的需求。通过本文介绍的几种媒体展示组件的使用方法,开发者可以快速构建功能丰富、性能优异的媒体应用。

关键要点包括:135

  1. Video组件提供了开箱即用的视频播放功能,适合大多数基本场景

  2. AVPlayer与XComponent组合提供了更高级的自定义控制能力

  3. 全屏切换可以通过Video组件内置功能或自定义实现

  4. 小窗口播放增强了用户体验,允许后台播放

  5. 媒体查询实现了响应式布局,适应不同设备特性

  6. 性能优化技术如LazyForEach和@Reusable确保了流畅体验

鸿蒙Next的媒体能力仍在不断发展,建议开发者定期查阅官方文档以获取最新功能和最佳实践。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

移动端开发者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值