App端强制横屏必须修改原生配置,JS层uni.setScreenOrientation在真机上无效;iOS需配置UISupportedInterfaceOrientations,Android需设置android:screenOrientation="landscape";页面级pageOrientation仅对小程序和H5生效。

App端强制横屏必须改原生配置,JS层调用uni.setScreenOrientation基本无效
在真机 App 上,uni.setScreenOrientation 调用后既不报错也不生效,不是你代码写错了,而是 iOS 和 Android 系统从 12+ 开始严格限制 Web 层对屏幕方向的控制权。uni-app 的 JS API 无法绕过这一限制,文档里写的“支持”仅适用于模拟器或极旧机型。
真正起效的方式只有一种:修改原生工程配置,让系统级 Activity 或 ViewController 强制横屏。CSS 的 transform: rotate(90deg) 只是视觉假旋转,会导致触摸坐标错乱、Canvas 尺寸异常、键盘弹出失败等问题,游戏或视频类场景绝对不能用。
- iOS:在
ios/manifest.json的UISupportedInterfaceOrientations中只保留UIInterfaceOrientationLandscapeLeft和UIInterfaceOrientationLandscapeRight - Android:在
android/app/src/main/AndroidManifest.xml对应的<activity>标签中添加android:screenOrientation="landscape" - 若只要某一页横屏(如游戏页),Android 可单独为该 Activity 配置;iOS 则需配合原生插件动态设置
UIDevice.current.setValue,纯 JS 无解
页面级横屏配置在 pages.json 中写法完全失效
pages.json 里的 pageOrientation: "landscape" 在 App 端被直接忽略——它只对小程序平台(如微信、QQ)和 H5 生效。你在 App 端写了也白写,打包后不会有任何变化。
常见错误是把小程序那套配置照搬到 App 工程里,比如:
{"path": "pages/game/game", "style": {"pageOrientation": "landscape"}}
这段在 App 真机上毫无作用。想让某页面横屏,唯一可靠路径是:把它对应到一个独立的、已在原生层声明为 landscape 的 Activity(Android)或 ViewController(iOS)。
- 不要依赖
onLoad或onShow里调用plus.screen.lockOrientation来“补救”——很多机型锁不住,且退出后方向不恢复 - 云打包或自定义基座必须重新生成,热重载和调试器里的“运行”按钮不会触发原生配置更新
- 检查是否误用了
app-plus.distribute.ios.orientation这类旧字段,新版 manifest.json 已弃用
视频全屏时临时横屏,plus.screen.lockOrientation 是唯一可行方案
对于视频播放这类需要“进入全屏时横屏、退出后恢复竖屏”的场景,plus.screen.lockOrientation 是目前 App 端唯一能稳定干预方向的 JS 接口,但必须满足三个前提:
- 仅限真机测试,H5 和模拟器不支持
- 必须监听
video组件的@fullscreenchange事件,而不是靠onShow或定时器 - 退出时务必手动恢复,不能依赖页面卸载逻辑,因为原生播放器生命周期独立于 Vue 实例
示例关键逻辑:
onFullscreenChange(e) {
if (e.detail.fullScreen) {
plus.screen.lockOrientation('landscape-primary');
} else {
plus.screen.lockOrientation('portrait-primary');
}
}
注意:landscape-primary 比 landscape 更稳定;Android 部分机型还需额外调用 plus.navigator.setFullscreen(false) 配合,否则返回后 WebView 容器尺寸残留。
横屏后返回竖屏状态卡住?问题根源不在 JS,而在原生容器未重置
用户从横屏视频页返回后页面仍保持横屏,不是 plus.screen.lockOrientation("portrait") 没调用,而是原生 WebView 容器本身没收到“尺寸重绘”指令。尤其在 Android 上,WebView 的 onConfigurationChanged 可能被拦截,导致 CSS 布局卡在旧宽高比。
解决思路不是加更多 JS 监听,而是确保原生层做了两件事:
- 在
AndroidManifest.xml中移除android:configChanges="orientation|screenSize"(除非你真有完整处理逻辑) - 在 iOS 原生插件里,于播放器
onstatechanged回调为ended或idle后,主动触发[webView setNeedsLayout]和[webView layoutIfNeeded] - 避免在横屏页使用
uni.getSystemInfoSync().screenWidth初始化 Canvas —— 它返回的是设备物理宽度,不是当前横屏下的可用视口宽度;应改用window.innerWidth / window.innerHeight并监听resize事件


















