uni.setscreenorientation在app端常静默失效,根本原因是ios wkwebview和android 12+系统拦截js方向请求;真正生效需配置manifest.json中app-plus.distribute.orientation并重新云打包,辅以video控件精简和实时尺寸监听。

App端uni.setScreenOrientation为什么总不生效
它在真机上大概率静默失败,不是你代码写错了,而是系统级限制:iOS WKWebView 和 Android 12+ 都会拦截 JS 层的方向请求。官方文档没明说,但实测中这个 API 在 App 端仅对部分低端 Android 机型有效,iOS 几乎完全不可用。
常见错误现象包括:uni.setScreenOrientation 返回 success 但屏幕纹丝不动;或调用后短暂横屏,松手立刻回弹;又或者只在模拟器里成功,一上真机就失效。
- 别在
onLoad或mounted里调用——native view 还没创建,调了等于没调 - 即使挪到
onReady,iOS 仍可能被原生播放器、键盘、全屏控件二次覆盖 - 云打包前没改
manifest.json的原生配置,JS 层再怎么努力也绕不过系统白名单
必须改的原生配置项:manifest.json 中的 app-plus.distribute.orientation
这是 App 端横竖屏控制的真正入口,其他所有 JS 调用都只是“锦上添花”甚至“自我安慰”。不配这里,uni.setScreenOrientation 就是空中楼阁。
iOS 和 Android 的写法不同,不能混用:
- iOS 必须写成数组:
"orientation": ["landscape-primary", "landscape-secondary"](只允许横屏)或["portrait"](只允许竖屏) - Android 推荐单值字符串:
"orientation": "landscape",部分旧版插件不识别数组 - 如果想让某页面支持自动旋转(比如阅读页),iOS 仍要填
["portrait", "landscape-primary", "landscape-secondary"],Android 填"unspecified"
改完必须「重新云打包」或「使用自定义调试基座」,热更新和本地运行都不触发原生层变更。
视频页横屏:关掉 controls 和 enable-danmu 才能抢回控制权
哪怕你已配好 manifest.json,<video></video> 组件在 iOS 上仍大概率锁死竖屏——因为它的原生播放器接管了 orientation 决策。解决方案不是加更多 JS,而是减干扰。
-
controls设为false:禁用系统控件,避免其全屏逻辑覆盖你的方向设置 -
enable-danmu设为false:iOS 下弹幕会强制走另一套全屏渲染路径,一开就绕过所有 JS 控制 - 全屏后监听
@fullscreen-change,在detail.fullscreen === true时立即再调一次uni.setScreenOrientation(仅作 iOS 补救,Android 不依赖此事件)
注意:videoContext.requestFullScreen() 的 Promise resolve 后再调方向 API,比等事件更稳。
横屏布局拿不到正确尺寸?别信 screenWidth/screenHeight
uni.getSystemInfo 返回的是设备物理方向下的固定值,不是当前屏幕朝向的实际可用尺寸。你在横屏时直接用 screenWidth 当画布宽,结果 Canvas 被拉伸、touch 坐标偏移、滚动错乱——这是最隐蔽也最常被忽略的坑。
正确做法是监听原生尺寸变化:
- H5 和 App 都可用
uni.onWindowResize,从res.size拿实时windowWidth/windowHeight - App 端还可监听
plus.screen.onorientationchange,配合plus.screen.getWidth()获取当前方向下的像素宽高 - 游戏或 WebGL 场景务必用后者,因为
onWindowResize在某些 Android 全屏切换时有延迟
真正的横屏控制不在 CSS 旋转,也不在 JS 反复调 API,而在原生配置 + 尺寸监听 + 干扰项清理这三者的闭环。少一个,横屏就不可靠。











