应用未调用display或者on('windowSizeChange')方法监听屏幕尺寸变化,对视频播放组件的布局进行调整,未设置RenderFit属性来控制视频画面的填充方式,导致应用视频未能全屏播放,四周出现留白的问题。
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone",
"tablet",
"2in1"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"orientation": "auto_rotation",
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"ohos.want.action.home"
]
}
]
}
],
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
],
"extensionAbilities": [
{
"name": "EntryBackupAbility",
"srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
"type": "backup",
"exported": false,
"metadata": [
{
"name": "ohos.extension.backup",
"resource": "$profile:backup_config"
}
],
}
]
}
} // 监听窗口尺寸变化
this.windowClass.on('windowSizeChange', (data) => {
console.info(`AVPlayerDemo Succeeded in enabling the listener for window size changes. Data:${data}`);
let orientation = display.getDefaultDisplaySync().orientation;
// 横屏
if (orientation == display.Orientation.LANDSCAPE || orientation == display.Orientation.LANDSCAPE_INVERTED) {
this.isLandscape = true;
}
// 竖屏
if (orientation == display.Orientation.PORTRAIT || orientation == display.Orientation.PORTRAIT_INVERTED) {
this.isLandscape = false;
}
}); setWindowLayOut() {
// 监听全屏事件,设置沉浸式窗口
this.windowClass.setWindowLayoutFullScreen(this.isFullScreen);
} XComponent({
type: XComponentType.SURFACE,
controller: this.xComponentController
})
.onLoad(() => {
this.surfaceID = this.xComponentController.getXComponentSurfaceId();
})
.width('100%')
.height('100%')
.renderFit(RenderFit.RESIZE_CONTAIN); 完整示例如下:
import media from '@ohos.multimedia.media';
import { BusinessError } from '@ohos.base';
import { display } from '@kit.ArkUI';
import { common } from '@kit.AbilityKit';
@Entry
@Component
struct Index {
@Watch('setWindowLayOut') @State isFullScreen: boolean = false;
@State isLandscape: boolean = false;
@State isVideo: boolean = true;
@State isPlay: boolean = false;
@State flag: boolean = false;
@State videoFiles: media.AVFileDescriptor[] = [];
@State audioFiles: media.AVFileDescriptor[] = [];
@State sourceFiles: media.AVFileDescriptor[] = [];
@State currentIndex: number = 0;
private avPlayer: media.AVPlayer | undefined = undefined;
private xComponentController = new XComponentController();
private surfaceID: string = '';
private readonly OPERATE_STATE: Array<string> = ['prepared', 'playing', 'paused', 'completed'];
context = this.getUIContext();
uiAbilityContext = this.context.getHostContext() as common.UIAbilityContext;
private windowClass = this.uiAbilityContext.windowStage.getMainWindowSync();
setWindowLayOut() {
// 监听全屏事件,设置沉浸式窗口
this.windowClass.setWindowLayoutFullScreen(this.isFullScreen);
}
aboutToAppear(): void {
// 初始化AVPlayer
this.createAVPlayer();
this.reset(true);
try {
// 监听窗口尺寸变化
this.windowClass.on('windowSizeChange', (data) => {
console.info(`AVPlayerDemo Succeeded in enabling the listener for window size changes. Data:${data}`);
let orientation = display.getDefaultDisplaySync().orientation;
// 横屏
if (orientation == display.Orientation.LANDSCAPE || orientation == display.Orientation.LANDSCAPE_INVERTED) {
this.isLandscape = true;
}
// 竖屏
if (orientation == display.Orientation.PORTRAIT || orientation == display.Orientation.PORTRAIT_INVERTED) {
this.isLandscape = false;
}
});
} catch (exception) {
console.error(`AVPlayerDemo Failed to enable the listener for window size changes. Cause:${exception}`);
}
}
aboutToDisappear(): void {
if (this.avPlayer) {
this.avPlayer.off('error');
this.avPlayer.off('stateChange');
this.avPlayer.release();
}
try {
this.windowClass.off('windowSizeChange');
} catch (exception) {
console.error(`AVPlayerDemo Failed to disable the listener for window size changes. Cause:${exception}`);
}
}
build() {
Column() {
if (!this.isFullScreen) {
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceAround }) {
Column() {
Text('视频播放')
.fontColor(this.isVideo ? Color.Blue : Color.Black)
.fontSize(16)
.fontWeight(this.isVideo ? 500 : 400)
.lineHeight(22)
.margin({ top: 17, bottom: 7 });
Divider()
.strokeWidth(2)
.color('#007DFF')
.opacity(this.isVideo ? 1 : 0);
}
.onClick(() => {
this.isVideo = true;
this.reset(true);
});
}
.margin({ bottom: '8vp' });
}
Flex({
direction: FlexDirection.Column,
justifyContent: this.isFullScreen ? FlexAlign.Center : FlexAlign.Start
}) {
if (this.isVideo) {
this.VideoPlayer();
}
if (!this.isFullScreen) {
this.Buttons();
}
}
.width('100%')
.height('100%')
.backgroundColor(this.isFullScreen ? Color.Black : Color.White);
}
.width('100%')
.height('100%');
}
@Builder
Buttons() {
Column() {
Scroll() {
GridRow({
columns: 2,
gutter: { x: 5, y: 10 },
direction: GridRowDirection.Row
}) {
GridCol({ span: 1, offset: 0, order: 0 }) {
Button('播放').width(140).onClick(() => {
this.play();
});
};
GridCol({ span: 1, offset: 0, order: 0 }) {
Button('暂停').width(140).onClick(() => {
this.isPlay = false;
if (this.avPlayer) {
this.avPlayer.pause();
}
});
};
GridCol({ span: 1, offset: 0, order: 0 }) {
Button('进入全屏').width(140).onClick(() => {
this.isFullScreen = true;
});
};
}
.margin({ bottom: 20, top: 20 })
.borderRadius(20);
}
.scrollBar(BarState.Off);
};
}
@Builder
VideoPlayer() {
Stack({
alignContent: this.isFullScreen ? (this.isLandscape ? Alignment.Bottom : Alignment.Center) : Alignment.Bottom
}) {
Stack() {
if (!this.isPlay) {
// $r('app.media.startIcon')指向资源文件,缺失该文件会编译报错,用户根据自身需求,自行替换。
Image($r('app.media.startIcon'))
.width(50)
.height(50)
.zIndex(2)
.onClick(() => {
this.play();
});
}
Column() {
XComponent({
type: XComponentType.SURFACE,
controller: this.xComponentController
})
.onLoad(() => {
this.surfaceID = this.xComponentController.getXComponentSurfaceId();
})
.width('100%')
.height('100%')
.renderFit(RenderFit.RESIZE_CONTAIN);
}
.zIndex(1)
.onClick(() => {
this.playOrPause();
});
}
.width('100%')
.height(this.isFullScreen ? (this.isLandscape ? '100%' : 260) : '100%');
}
.height(this.isFullScreen ? '100%' : 260)
.backgroundColor(Color.Black)
.width('100%');
}
// 注册avplayer回调函数
setAVPlayerCallback(avPlayer: media.AVPlayer) {
avPlayer.on('timeUpdate', (time: number) => {
console.info(`AVPlayerDemo AVPlayer timeUpdate. time is ${time}`);
});
// error回调监听函数,当avPlayer在操作过程中出现错误时调用 reset接口触发重置流程
avPlayer.on('error', (err: BusinessError) => {
console.error(`AVPlayerDemo Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
avPlayer.reset(); // 调用reset重置资源,触发idle状态
});
// 状态机变化回调函数
avPlayer.on('stateChange', async (state: string) => {
switch (state) {
case 'idle': // 成功调用reset接口后触发该状态机上报
console.info('AVPlayerDemo AVPlayer state idle called.');
if (avPlayer && this.sourceFiles.length > this.currentIndex) {
}
break;
case 'initialized': // avplayer 设置播放源后触发该状态上报
console.info('AVPlayerDemo AVPlayer state initialized called.');
this.reset();
if (this.isVideo) {
avPlayer.surfaceId = this.surfaceID;
}
avPlayer.prepare();
break;
case 'prepared': // prepare调用成功后上报该状态机
console.info('AVPlayerDemo AVPlayer state prepared called.');
this.flag = true;
avPlayer.setSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_00_X);
avPlayer.seek(1, media.SeekMode.SEEK_PREV_SYNC);
break;
case 'completed': // prepare调用成功后上报该状态机
console.info('AVPlayerDemo AVPlayer state completed called.');
this.isPlay = false;
break;
case 'playing': // play成功调用后触发该状态机上报
console.info('AVPlayerDemo AVPlayer state playing called.');
break;
case 'paused': // pause成功调用后触发该状态机上报
console.info('AVPlayerDemo AVPlayer state paused called.');
break;
case 'stopped': // stop接口成功调用后触发该状态机上报
console.info('AVPlayerDemo AVPlayer state stopped called.');
break;
case 'released':
console.info('AVPlayerDemo AVPlayer state released called.');
break;
default:
console.info('AVPlayerDemo AVPlayer state unknown called.');
break;
}
});
}
reset(sourceFlag?: boolean) {
this.isPlay = false;
this.flag = false;
if (sourceFlag) {
this.currentIndex = 0;
this.isFullScreen = false;
if (this.isVideo) {
this.sourceFiles = this.videoFiles;
} else {
this.sourceFiles = this.audioFiles;
}
if (this.avPlayer) {
this.avPlayer.reset();
}
}
}
async play() {
if (!this.avPlayer || this.OPERATE_STATE.indexOf(this.avPlayer.state) === -1 ||
this.OPERATE_STATE.indexOf(this.avPlayer.state) === 1) {
console.error('AVPlayerDemo play failed. no avPlayer or state is not prepared/paused/completed');
return;
}
this.isPlay = true;
if (this.avPlayer.state === 'completed') {
this.avPlayer.seek(1, media.SeekMode.SEEK_PREV_SYNC);
}
this.avPlayer.play();
}
playOrPause() {
if (this.avPlayer) {
if (this.isPlay) {
this.isPlay = false;
this.avPlayer.pause();
} else {
this.play();
}
}
}
createAVPlayer() {
media.createAVPlayer().then((video: media.AVPlayer) => {
if (video != null) {
this.avPlayer = video;
this.setAVPlayerCallback(this.avPlayer);
if (this.avPlayer) {
// 网络链接根据实际情况替换成用户自己的链接,否则无法正常运行
this.avPlayer.url = 'XXXX';
}
console.info('AVPlayerDemo createAVPlayer success');
} else {
console.error('AVPlayerDemo createAVPlayer fail');
}
}).catch((error: BusinessError) => {
console.error(`AVPlayerDemo AVPlayer catchCallback, error message:${error.message}`);
});
}
}