uni-app video 全屏必须调用 requestfullscreen(),不能靠属性或 css 拉伸;需通过 uni.createvideocontext 获取上下文后调用 ctx.requestfullscreen({direction: 90}),且 id 必须严格一致;全屏状态监听唯一可靠方式是 @fullscreenchange 事件,退出后需立即调用 uni.setscreenorientation({orientation: 'portrait'}) 并设置 body 背景色为 #000。

uni-app video 全屏必须调用 requestFullScreen(),不能靠 fullscreen 属性或 CSS 拉伸
直接写 fullscreen="true" 或加 style="width: 100vw; height: 100vh;" 在真机上完全无效——iOS 和小程序里静默忽略,App 端甚至不响应。原生播放器(AVPlayerLayer / SurfaceView)只认 JS API 调用,且必须由用户手势触发。
关键动作只有两个:uni.createVideoContext('myVideo', this) 获取上下文,再调 ctx.requestFullScreen({ direction: 90 })。其中 id="myVideo" 必须与创建 context 时传入的字符串严格一致(大小写敏感),否则返回空实例。
- 别在
onLoad或mounted里直接调,iOS 会拒绝,Android 报NotAllowedError - H5 端若想自动全屏(如加载完即进),需在
@canplay或@play回调中用this.$nextTick包一层再执行 - 微信小程序要求
:controls="true",否则requestFullScreen()静默失败
H5 端横屏全屏失败?先查 manifest.json 的 orientation 配置
H5 的 requestFullscreen() 在页面方向被锁定时无法触发横屏渲染,90% 的失败源于此。必须在 manifest.json 的 h5 节点下显式配置:
"h5": {
"orientation": "all"
}
"landscape" 无效,"all" 才是唯一生效值。若视频嵌在 iframe(如 YouTube),还需额外加 allow="fullscreen; accelerometer; gyroscope; magnetometer" 属性,否则横屏被拦截。
- CSS 的
transform: rotate(90deg)是伪全屏:viewport 尺寸没变,cover-view定位错乱,控制条交互异常 - 别依赖
screen.orientation或document.fullscreenElement判断状态——它们在 iOS 小程序和 App 端返回不可靠
监听全屏状态只能用 @fullscreenchange 事件
所有平台统一走组件事件:<video></video>。这是唯一准确、及时、跨端一致的监听方式。
onFullscreenChange(e) 中通过 e.detail.fullScreen(布尔值)判断真假,并同步更新 data(如 isFullscreen: false),用于条件渲染封面、隐藏 tabbar 等。
- iOS 小程序里按物理返回键退出全屏,也会触发该事件;H5 端按 ESC 不一定触发,可额外监听
document.onexitfullscreen做兜底(仅限 H5) - 别在该回调里立刻调
requestFullScreen()或exitFullScreen(),容易引发循环 - 退出后页面卡横屏?必须立即调
uni.setScreenOrientation({ orientation: 'portrait' }),尤其 iOS 上明显
全屏时 cover-view 消失不是 bug,是架构决定的
一旦 <video></video> 进入原生全屏,它就脱离 WebView 渲染树,cover-view 失去宿主上下文,自然不显示——这不是兼容性问题,是设计如此。
别写 v-if="!isFullscreen" 切换 cover-view 显示,它根本不会挂载。若需全屏时仍有控件(如返回按钮、进度条),唯一可靠方案是用 subNVue,且 zIndex 必须 ≥ 9999。
- 全屏时背景透出?必须设
document.body.style.backgroundColor = '#000',只改父容器背景在小程序里无效 - 用了自定义导航栏(
navigationStyle: "custom")?要同步隐藏它,否则会浮在黑底之上形成“灰边”











