HarmonyOS 鸿蒙Next全屏播放
HarmonyOS 鸿蒙Next全屏播放
如何解决AVPlayer在List组件中无法实现全屏播放问题
【解决方案】
AVPlayer只是把Surface画布绑定到AVPlayer上,不提供旋转、全屏接口,这些都要应用自己操作Surface全屏、旋转来实现,AVPlayer只是一个不带界面的播放器。所以实现全屏需要通过操作Surface实现全屏、旋转。 在点击全屏按钮时,隐藏其它ListItem,仅显示选中项;点击横屏按钮时,设置窗口方向,并设置XComponent组件宽高铺满屏幕,实现全屏播放效果。
1.初始化视频列表数据源,示例代码如下:
private data: myVideoSourceDate = new myVideoSourceDate([]);
aboutToAppear(): void {
let list: VideoSource[] = [
new VideoSource('videoTest1', 'videoTest1.mp4'),
new VideoSource('videoTest2', 'videoTest2.mp4'),
new VideoSource('videoTest3', 'videoTest3.mp4'),
new VideoSource('videoTest4', 'videoTest4.mp4')
];
this.data = new myVideoSourceDate(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(this.getUIContext().getHostContext()).then((win) => {
win.setPreferredOrientation(orientation).then((data) => {
console.info('setWindowOrientation: ' + orientation + ' Succeeded. Data: ' + JSON.stringify(data));
}).catch((err: string) => {
console.info('setWindowOrientation: Failed. Cause: ' + JSON.stringify(err));
});
}).catch((err: string) => {
console.info('setWindowOrientation: Failed to obtain the top window. Cause: ' + JSON.stringify(err));
});
}
// 设置沉浸式窗口
setFullScreen(isLayoutFullScreen: boolean) {
window.getLastWindow(this.getUIContext().getHostContext()).then((win) => {
win.setWindowLayoutFullScreen(isLayoutFullScreen);
}).catch((err: string) => {
console.info('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播放视频(ArkTS):实现端到端播放原始媒体资源。
- 窗口沉浸式能力:在看视频、玩游戏等场景下,隐藏状态栏、导航栏等不必要的系统窗口,从而获得更佳的沉浸式体验。
- 窗口方向:设置主窗口的方向。
更多关于HarmonyOS 鸿蒙Next全屏播放的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在鸿蒙 5(HarmonyOS 5)中,AVPlayer 本身没有“一键全屏”接口,而 List 组件又把每个 ListItem 当成独立卡片渲染,导致“点击全屏”后播放器仍然被限制在原来的 Item 容器里,无法真正铺满窗口。 解决思路就是 “跳出 List 容器”+“手动控制窗口” 两步走,官方示例与社区实践都验证了这套方案可行,核心步骤如下:
1. 数据与 UI 结构
- 用 LazyForEach 渲染视频列表,每个 Item 里放一个 XComponent 给 AVPlayer 当画布。
- 额外定义两个状态变量
isLayoutFullScreen: boolean→ 是否进入全屏isLandScape: boolean→ 是否横屏
2. 点击“全屏”时做三件事
// 1. 隐藏其它 ListItem(只保留当前项)
this.isLayoutFullScreen = true
// 2. 让窗口沉浸式 + 旋转
window.getLastWindow(getContext(this))
.then(win => {
win.setPreferredOrientation(window.Orientation.LANDSCAPE) // 横屏
win.setWindowLayoutFullScreen(true) // 隐藏状态栏/导航栏
})
// 3. 把当前 XComponent 宽高改为 100%
// 这样视觉上就“跳出”了 List,占满整个屏幕。
3. 退出全屏再反向操作
this.isLayoutFullScreen = false
win.setPreferredOrientation(window.Orientation.PORTRAIT)
win.setWindowLayoutFullScreen(false)
// Item 恢复 200 dp 高度,列表重新出现
在HarmonyOS鸿蒙Next中,全屏播放功能通过系统提供的全屏模式接口实现。开发者可使用window模块的setFullScreen方法,调用时传入true参数即可进入全屏状态。退出全屏则传入false。该功能适用于视频播放、游戏等场景,确保界面元素自动适配屏幕尺寸,无需手动调整布局。全屏状态下,状态栏和导航栏默认隐藏,由系统统一管理交互行为。
在HarmonyOS Next中,AVPlayer在List组件内实现全屏播放的常见问题通常源于组件层级和窗口管理限制。以下是核心解决方案:
-
使用全屏窗口模式
通过window模块创建独立全屏窗口,将AVPlayer移至新窗口播放:let context = getContext(this) as common.UIAbilityContext; let windowClass: window.Window | null = null; window.createWindow(context, "fullscreen", (err, data) => { windowClass = data; windowClass.moveTo(0, 0).resetSize(display.getDefaultDisplaySync().width, display.getDefaultDisplaySync().height); }); -
动态切换播放器容器
点击列表项时,将AVPlayer从List容器迁移至全屏窗口的根节点:// 获取全屏窗口根组件 let fullscreenRoot = windowClass.getComponentRoot(); // 将AVPlayer节点移至全屏窗口 fullscreenRoot.appendChild(avPlayerNode); -
状态同步与返回处理
监听全屏窗口关闭事件,将AVPlayer归位至原始List容器,并保持播放状态同步。 -
List项复用优化
通过if/else条件渲染控制播放器实例,避免多个AVPlayer同时存在导致内存泄漏。
此方案通过窗口级播放器迁移,有效规避了List滚动容器对全屏功能的限制。注意在全屏窗口销毁时需正确释放AVPlayer资源。

