HarmonyOS鸿蒙Next中如何解决AVPlayer在List组件中无法实现全屏播放问题
HarmonyOS鸿蒙Next中如何解决AVPlayer在List组件中无法实现全屏播放问题
【问题现象】
在List组件中,AVPlayer播放器作为ListItem的子元素,视频播放无法全屏显示。
【背景知识】
【定位思路】
- AVPlayer只是把Surface画布绑定到AVPlayer上,不提供旋转、全屏接口,这些都要应用自己操作Surface全屏、旋转来实现,AVPlayer只是一个不带界面的播放器。所以实现全屏需要通过操作Surface实现全屏、旋转。
- 在点击全屏按钮时,隐藏其它ListItem,仅显示选中项;点击横屏按钮时,设置窗口方向,并设置XComponent组件宽高铺满屏幕,实现全屏播放效果。
【解决方案】
1. 初始化视频列表数据源
代码示例如下:
private data: myVideoSourceData = new myVideoSourceData([]);
aboutToAppear(): void {
let list: VideoSource[] = [
new VideoSource("文案1", "IAP支付白屏.mp4"),
new VideoSource("文案2", "IAP支付白屏.mp4"),
new VideoSource("文案3", "video3.mp4"),
new VideoSource("文案4", "video4.mp4")
];
this.data = new myVideoSourceData(list);
}
2. List + LazyForEach组件渲染视频列表
代码示例如下:
build() {
// 通过显隐控制控制其他listItem是否展示
Column() {
Text(this.item.text)
.visibility(this.isLayoutFullScreen === false ? Visibility.Visible : Visibility.None)
Stack() {
XComponent({ id: 'video_player_id', type: XComponentType.SURFACE, controller: this.mXComponentController })
.onLoad(() => {
this.player = new AVPlayerDemo();
this.player.setSurfaceID(this.mXComponentController.getXComponentSurfaceId());
})
.height(this.isLayoutFullScreen ? (this.isLandScape ? '100%' : 200) : "100%")
// 视频按钮布局
// ...
}
.backgroundColor(Color.Black)
.height(this.isLayoutFullScreen ? "100%" : 200)
}
.onVisibleAreaChange([0.2, 1.0], async (isVisible: boolean, currentRatio: number) => {
if (!isVisible && currentRatio < 0.2) {
if (this.player && isPlaying.length !== 0 && this.player === isPlaying[0]) {
console.info('onVisibleAreaChange')
this.player.release();
isPlaying[0].release();
isPlaying.pop();
}
}
})
.width('100%')
}
3. 窗口方向(横屏)、窗口沉浸式设置
代码示例如下:
// 设置窗口方向
setR(orientation: number) {
window.getLastWindow(getContext(this)).then((win) => {
win.setPreferredOrientation(orientation).then((data) => {
console.log('setWindowOrientation: ' + orientation + ' Succeeded. Data: ' + JSON.stringify(data));
}).catch((err: string) => {
console.log('setWindowOrientation: Failed. Cause: ' + JSON.stringify(err));
});
}).catch((err: string) => {
console.log('setWindowOrientation: Failed to obtain the top window. Cause: ' + JSON.stringify(err));
});
}
// 设置沉浸式窗口
setFullScreen(isLayoutFullScreen: boolean) {
window.getLastWindow(getContext(this)).then((win) => {
win.setWindowLayoutFullScreen(isLayoutFullScreen, (err: BusinessError) => {
const errCode: number = err.code;
if (errCode) {
console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(err));
return;
}
console.info('Succeeded in setting the window layout to full-screen mode.');
});
}).catch((err: string) => {
console.log('setWindowOrientation: Failed to obtain the top window. Cause: ' + JSON.stringify(err));
});
}
4. 添加全屏、退出全屏、横屏等按钮
代码示例如下:
Button("点击全屏")
.onClick(() => {
this.fangDaIndex = this.index
this.isLayoutFullScreen = true
this.setFullScreen(this.isLayoutFullScreen)
})
.backgroundColor(this.bkColor)
Button("退出全屏")
.onClick(() => {
this.setR(1);
this.isLayoutFullScreen = false;
this.isLandScape = false;
this.setFullScreen(this.isLayoutFullScreen)
})
.backgroundColor(this.bkColor)
Button("横屏")
.onClick(() => {
this.fangDaIndex = this.index;
this.setR(4);
this.isLandScape = true;
this.isLayoutFullScreen = true;
this.setFullScreen(this.isLayoutFullScreen)
})
.backgroundColor(this.bkColor)
解决问题后截图展示:
【总结】
AVPlayer可以自定义全屏效果,当需要在List组件中实现AVPlayer全屏播放效果时,可以通过隐藏其它组件,设置窗口横屏、沉浸式,并且使XComponent组件铺满全屏,从而达到全屏播放的效果。
该方案,对于List+Video实现的视频列表同样有效。但是对于多层嵌套的场景,需要结合NodeContainer实现。
更多关于HarmonyOS鸿蒙Next中如何解决AVPlayer在List组件中无法实现全屏播放问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
1 回复
更多关于HarmonyOS鸿蒙Next中如何解决AVPlayer在List组件中无法实现全屏播放问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,通过以下步骤解决AVPlayer在List组件中无法实现全屏播放问题:
- 初始化视频列表数据源:创建视频数据源并初始化。
- 使用List + LazyForEach组件渲染视频列表:通过显隐控制其他ListItem是否展示,使用XComponent绑定AVPlayer的Surface画布。
- 设置窗口方向和沉浸式窗口:通过
setPreferredOrientation
设置窗口方向为横屏,通过setWindowLayoutFullScreen
设置沉浸式窗口。 - 添加全屏、退出全屏、横屏等按钮:通过按钮点击事件控制全屏、退出全屏和横屏操作,调整XComponent组件的宽高以铺满屏幕。
具体代码实现如下:
// 设置窗口方向
setR(orientation: number) {
window.getLastWindow(getContext(this)).then((win) => {
win.setPreferredOrientation(orientation).then((data) => {
console.log('setWindowOrientation: ' + orientation + ' Succeeded. Data: ' + JSON.stringify(data));
}).catch((err: string) => {
console.log('setWindowOrientation: Failed. Cause: ' + JSON.stringify(err));
});
}).catch((err: string) => {
console.log('setWindowOrientation: Failed to obtain the top window. Cause: ' + JSON.stringify(err));
});
}
// 设置沉浸式窗口
setFullScreen(isLayoutFullScreen: boolean) {
window.getLastWindow(getContext(this)).then((win) => {
win.setWindowLayoutFullScreen(isLayoutFullScreen, (err: BusinessError) => {
const errCode: number = err.code;
if (errCode) {
console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(err));
return;
}
console.info('Succeeded in setting the window layout to full-screen mode.');
});
}).catch((err: string) => {
console.log('setWindowOrientation: Failed to obtain the top window. Cause: ' + JSON.stringify(err));
});
}
// 添加全屏、退出全屏、横屏等按钮
Button("点击全屏")
.onClick(() => {
this.fangDaIndex = this.index
this.isLayoutFullScreen = true
this.setFullScreen(this.isLayoutFullScreen)
})
.backgroundColor(this.bkColor)
Button("退出全屏")
.onClick(() => {
this.setR(1);
this.isLayoutFullScreen = false;
this.isLandScape = false;
this.setFullScreen(this.isLayoutFullScreen)
})
.backgroundColor(this.bkColor)
Button("横屏")
.onClick(() => {
this.fangDaIndex = this.index;
this.setR(4);
this.isLandScape = true;
this.isLayoutFullScreen = true;
this.setFullScreen(this.isLayoutFullScreen)
})
.backgroundColor(this.bkColor)
通过以上步骤,可以在List组件中实现AVPlayer的全屏播放效果。