HarmonyOS鸿蒙Next中video组件横屏时的实现方式

HarmonyOS鸿蒙Next中video组件横屏时的实现方式 自定义播放器,横屏全屏播放时不能够像video组件处理的那么优雅。希望获得指导性代码,谢谢。

3 回复

可以参考下面的代码,主要使用了

代码:

import media from '@ohos.multimedia.media';
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';
import { BusinessError } from '@ohos.base';

export class AVPlayerDemo {
  private count: number = 0;
  surfaceID: string = ''; // surfaceID用于播放画面显示,具体的值需要通过Xcomponent接口获取,相关文档链接见上面Xcomponent创建方法
  private isSeek: boolean = true; // 用于区分模式是否支持seek操作
  private fileSize: number = -1;
  private fd: number = 0;

// 注册avplayer回调函数
setAVPlayerCallback(avPlayer: media.AVPlayer) {
  // startRenderFrame首帧渲染回调函数
  avPlayer.on('startRenderFrame', () => {
    console.info(`AVPlayer start render frame`);
  })
  // seek操作结果回调函数
  avPlayer.on('seekDone', (seekDoneTime: number) => {
    console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
  })
  // error回调监听函数,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程
  avPlayer.on('error', (err: BusinessError) => {
    console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
    avPlayer.reset(); // 调用reset重置资源,触发idle状态
  })
  // 状态机变化回调函数
  avPlayer.on('stateChange', async (state: string, reason: media.StateChangeReason) => {
    switch (state) {
      case 'idle': // 成功调用reset接口后触发该状态机上报
        console.info('AVPlayer state idle called.');
        // avPlayer.release(); // 调用release接口销毁实例对象
        break;
      case 'initialized': // avplayer 设置播放源后触发该状态上报
        console.info('AVPlayer state initialized called.');
        avPlayer.surfaceId = this.surfaceID; // 设置显示画面,当播放的资源为纯音频时无需设置
        avPlayer.prepare();
        break;
      case 'prepared': // prepare调用成功后上报该状态机
        console.info('AVPlayer state prepared called.');
        avPlayer.play(); // 调用播放接口开始播放
        break;
      case 'playing': // play成功调用后触发该状态机上报
        console.info('AVPlayer state playing called.');
        this.count++;
        break;
      case 'paused': // pause成功调用后触发该状态机上报
        console.info('AVPlayer state paused called.');
        // avPlayer.play(); // 再次播放接口开始播放
        break
    }
  });

// 以下demo为使用资源管理接口获取打包在HAP内的媒体资源文件并通过fdSrc属性进行播放示例
async avPlayerFdSrcDemo() {
  // 创建avPlayer实例对象
  let avPlayer: media.AVPlayer = await media.createAVPlayer();
  // 创建状态机变化回调函数
  this.setAVPlayerCallback(avPlayer);
  // 通过UIAbilityContext的resourceManager成员的getRawFd接口获取媒体资源播放地址
  // 返回类型为{fd,offset,length},fd为HAP包fd地址,offset为媒体资源偏移量,length为播放长度
  let context = getContext(this) as common.UIAbilityContext;
  let fileDescriptor = await context.resourceManager.getRawFd('videoTest.mp4');
  let avFileDescriptor: media.AVFileDescriptor =
    { fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length };
  this.isSeek = true; // 支持seek操作
  // 为fdSrc赋值触发initialized状态机上报
  avPlayer.fdSrc = avFileDescriptor;
  // await avPlayer.play();
}
}

view页面:

import { AVPlayerDemo } from '../model/AVPlayerDemo';
import window from '@ohos.window'

// xxx.ets
@Entry
@Component
struct PreviewArea {
  private surfaceId: string = ''
  private xComponentContext: Record<string, () => void> = {}
  xComponentController: XComponentController = new XComponentController()
  XComWidth: string = '100%';
  XComHeight: string = '400';

  build() {
    Stack() {
      XComponent({
        id: 'xcomponent',
        type: XComponentType.SURFACE,
        controller: this.xComponentController
      })
        .onLoad(() => {
          this.xComponentController.setXComponentSurfaceSize({ surfaceWidth: 1920, surfaceHeight: 1080 })
          this.surfaceId = this.xComponentController.getXComponentSurfaceId()
          this.xComponentContext = this.xComponentController.getXComponentContext() as Record<string, () => void>
          const AVPlayer = new AVPlayerDemo();
          AVPlayer.surfaceID = this.surfaceId;
          AVPlayer.avPlayerFdSrcDemo();
        })
        .width(this.XComWidth)
        .height(this.XComHeight)
      Column() {
        Button('横屏播放').onClick((event: ClickEvent) => {
          this.XComHeight = '100%';
          window.getLastWindow(getContext(), (err, windowclass) => {
            windowclass.setPreferredOrientation(window.Orientation.LANDSCAPE)
          });
        })
        Button('竖屏播放').onClick((event: ClickEvent) => {
          this.XComHeight = '400';
          window.getLastWindow(getContext(), (err, windowclass) => {
            windowclass.setPreferredOrientation(window.Orientation.PORTRAIT)
          });
        })
      }
    }
  }
}

更多关于HarmonyOS鸿蒙Next中video组件横屏时的实现方式的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,video组件横屏时的实现方式主要依赖于系统的屏幕旋转功能和布局管理。当设备旋转时,系统会自动调整video组件的显示方式以适应横屏模式。

具体实现步骤如下:

  1. 设置屏幕旋转支持:在config.json文件中,确保orientation属性设置为landscapesensorLandscape,以允许屏幕旋转到横屏模式。

  2. 布局调整:在UI布局文件中,使用DirectionalLayoutDependentLayout等布局管理器,确保video组件能够根据屏幕方向自动调整大小和位置。

  3. 全屏显示:在横屏模式下,通常需要将video组件设置为全屏显示。可以通过设置video组件的widthheight属性为match_parent来实现。

  4. 事件处理:监听屏幕旋转事件,在屏幕旋转时动态调整video组件的显示状态。可以使用onConfigurationChanged方法来处理屏幕方向变化。

  5. 媒体控制:在横屏模式下,确保播放控制按钮(如播放、暂停、音量控制等)能够正常显示和操作。可以通过调整布局或使用MediaController组件来实现。

通过以上步骤,可以在HarmonyOS鸿蒙Next中实现video组件在横屏模式下的正常显示和操作。

在HarmonyOS鸿蒙Next中,实现video组件横屏播放的方式主要依赖于屏幕方向的设置。可以通过以下步骤实现:

  1. 设置屏幕方向:在config.json中配置orientationlandscape,强制应用以横屏模式运行。
  2. 使用Video组件:在js文件中引入Video组件,并在struct中定义Video的宽高,确保其适应横屏布局。
  3. 动态调整布局:根据屏幕方向动态调整Video组件的宽高,确保视频播放时始终填充屏幕。

示例代码:

@Entry
@Component
struct VideoExample {
  private videoController: VideoController = new VideoController();

  build() {
    Column() {
      Video({
        src: 'https://example.com/sample.mp4',
        controller: this.videoController
      })
        .width('100%')
        .height('100%')
    }.width('100%').height('100%')
  }
}
回到顶部