欢迎光临
我们一直在努力

HarmonyOS ArkWeb 系列之全屏视频与布局联动:onFullScreenEnter/Exit 实战

文章目录

      • 问题:Web 全屏和 App 布局的冲突
      • 核心代码
      • 配套的 HTML 文件
      • 进阶:有多个 UI 层级时的处理
      • `onFullScreenEnter` 的 event 参数
      • 注意 Visibility.None vs Hidden
      • 写在最后

用户在 App 里看网页视频,点"全屏"按钮,视频应该铺满整个屏幕,顶部的标题栏、底部的 TabBar 都要隐藏;退出全屏,布局恢复原样。这个场景在视频类 App 里极其常见。ArkWeb 提供了 onFullScreenEnter 和 onFullScreenExit 两个回调,让你精确控制全屏时的布局变化。

问题:Web 全屏和 App 布局的冲突

默认情况下,网页里的视频点全屏,视频在 Web 组件区域内放大——但 Web 组件本身的高度是固定的,不会自动撑满屏幕。你需要在全屏时主动隐藏其他 UI 组件,让 Web 组件占据整个视窗。

核心代码

import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct WebFullScreenDemo {
controller: webview.WebviewController = new webview.WebviewController();
readonly HEADER_HEIGHT = 100; // 顶部区域高度

// 控制顶部组件是否可见
@State isHeaderVisible: boolean = true;

build() {
Column() {
// 顶部标题区域
Text('视频播放页面')
.width('100%')
.height(this.HEADER_HEIGHT)
.textAlign(TextAlign.Center)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.backgroundColor('#e1dede')
// 全屏时隐藏,非全屏时显示
// 用 Visibility.None 而非 Visibility.Hidden
// None 不占位,Hidden 占位但不显示
.visibility(this.isHeaderVisible ? Visibility.Visible : Visibility.None)

// Web 组件
Web({
src: $rawfile('FullScreen.html'),
controller: this.controller
})
.onFullScreenEnter((event) => {
// 进入全屏:隐藏顶部,让 Web 铺满
console.info('进入全屏模式');
this.isHeaderVisible = false;
})
.onFullScreenExit(() => {
// 退出全屏:恢复顶部
console.info('退出全屏模式');
this.isHeaderVisible = true;
})
.width('100%')
.height('100%')
.zIndex(10) // 全屏时 z 轴在最上层
.zoomAccess(true) // 允许缩放(视频全屏常需要)
}
.width('100%')
.height('100%')
}
}

配套的 HTML 文件

放在 rawfile/FullScreen.html:

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>全屏视频示例</title>
<style>
body { margin: 0; padding: 16px; background: #1a1a1a; color: white; }
video {
width: 100%;
border-radius: 8px;
background: #000;
}
.controls { margin-top: 12px; display: flex; gap: 10px; }
button {
flex: 1;
padding: 12px;
border: none;
border-radius: 6px;
background: #007AFF;
color: white;
font-size: 15px;
cursor: pointer;
}
#status { margin-top: 8px; font-size: 13px; color: #aaa; text-align: center; }
</style>
</head>
<body>
<video id="myVideo" controls playsinline
src="test_video.mp4">

您的浏览器不支持 video 标签
</video>

<div class="controls">
<button onclick="enterFullscreen()">进入全屏模式</button>
<button onclick="exitFullscreen()">退出全屏模式</button>
</div>

<p id="status">就绪</p>

<script>
const video = document.getElementById('myVideo');
const status = document.getElementById('status');

// 进入全屏(兼容不同浏览器前缀)
function enterFullscreen() {
const req = video.requestFullscreen
|| video.webkitRequestFullscreen
|| video.mozRequestFullScreen;
if (req) {
req.call(video)
.then(() => { status.textContent = '已进入全屏'; })
.catch(err => { status.textContent = '全屏失败:' + err.message; });
}
}

// 退出全屏
function exitFullscreen() {
const exit = document.exitFullscreen
|| document.webkitExitFullscreen
|| document.mozCancelFullScreen;
if (exit) {
exit.call(document)
.then(() => { status.textContent = '已退出全屏'; })
.catch(err => { status.textContent = '退出失败:' + err.message; });
}
}

// 监听全屏状态变化
document.addEventListener('fullscreenchange', () => {
if (document.fullscreenElement) {
status.textContent = '🎬 全屏中';
} else {
status.textContent = '📱 正常模式';
}
});
</script>
</body>
</html>

进阶:有多个 UI 层级时的处理

如果你的页面有 TabBar、状态栏等多个需要在全屏时隐藏的组件:

import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct WebFullScreenAdvanced {
controller: webview.WebviewController = new webview.WebviewController();

@State isFullScreen: boolean = false;

build() {
Stack() {
// 主内容区
Column() {
// 顶部导航栏
Row() {
Text('← 返回').fontSize(16)
Blank()
Text('视频详情').fontSize(18).fontWeight(FontWeight.Bold)
Blank()
Text('分享').fontSize(16)
}
.width('100%')
.height(56)
.padding({ left: 16, right: 16 })
.backgroundColor(Color.White)
.visibility(this.isFullScreen ? Visibility.None : Visibility.Visible)

// Web 视频区域
Web({ src: $rawfile('FullScreen.html'), controller: this.controller })
.onFullScreenEnter(() => {
this.isFullScreen = true;
})
.onFullScreenExit(() => {
this.isFullScreen = false;
})
.width('100%')
.height(this.isFullScreen ? '100%' : 220) // 全屏时撑满
.zoomAccess(true)

// 视频描述、评论等区域(全屏时隐藏)
if (!this.isFullScreen) {
Column() {
Text('视频描述内容…')
.fontSize(14)
.padding(16)
}
.layoutWeight(1)
}
}
.width('100%')
.height('100%')
}
.width('100%')
.height('100%')
}
}

onFullScreenEnter 的 event 参数

.onFullScreenEnter((event) => {
// event.handler:全屏处理器,可用于主动退出全屏
// event.videoWidth:全屏视频的宽度
// event.videoHeight:全屏视频的高度
if (event) {
console.info('全屏视频尺寸:', event.videoWidth, 'x', event.videoHeight);
// 可以保存 handler,在 ArkTS 里主动退出全屏
// this.fullScreenHandler = event.handler;
}
this.isHeaderVisible = false;
})

注意 Visibility.None vs Hidden

这个细节很重要:

// Hidden:组件不显示,但仍然占位,全屏时顶部会留白
.visibility(Visibility.Hidden)

// None:组件不显示,也不占位,全屏时布局收缩
.visibility(Visibility.None)

全屏时必须用 Visibility.None,否则被隐藏的组件虽然不可见,但占据的空间还在,Web 无法真正铺满全屏。

写在最后

全屏联动这个功能说简单也简单——就是在回调里切换 @State 变量。说坑也有坑——Visibility.None 和 Visibility.Hidden 的区别、zIndex 设置、Web 组件高度的动态切换,都容易踩。搞清楚这几个点,实现起来就很顺畅。

赞(0)
未经允许不得转载:171主机测评 » HarmonyOS ArkWeb 系列之全屏视频与布局联动:onFullScreenEnter/Exit 实战
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址