uni-app app端无法可靠监听方向变化,因ios wkwebview不支持screen.orientation、android各厂商实现不一致,且orientationchange事件基本不触发;唯一稳定方案是用uni.onwindowresize监听尺寸变化并按宽高比判断横竖屏。

uni-app 在 App 端无法可靠监听设备方向改变事件,必须改用 uni.onWindowResize 监听视口尺寸变化来间接判断横竖屏。
为什么 screen.orientation 和 orientationchange 在 App 端基本失效
iOS 原生 WebView(WKWebView)完全不暴露 screen.orientation 对象,typeof screen.orientation 就是 'undefined';Android 各厂商 WebView 行为不一致,返回值可能滞后、错乱或根本为空。标准的 window.addEventListener('orientationchange') 在绝大多数真机上压根不会触发——不是代码写错了,是底层没发事件。你写的监听函数永远不会执行。
常见错误现象:
- 开发时在 H5 模式下能触发,一打包成 App 就静默失败
- Android 某些机型偶尔回调,但
screen.orientation.type返回'portrait-primary'即使设备已明显横置 - 依赖该值做 DOM 旋转后,
<canvas></canvas>绘制偏移、触摸坐标错乱、键盘弹出位置异常
uni.onWindowResize 的注册与清理必须严格配对
这是 App 端唯一稳定可用的入口,但它不是“方向事件”,而是“窗口尺寸变更回调”。它的触发时机由原生层窗口重绘驱动,在 iOS/Android 上都可靠,但必须手动管理生命周期。
正确做法:
- 在
onReady(不是onLoad)中注册:uni.onWindowResize(this.handleResize)——onLoad阶段 native view 尚未初始化,监听无效 - 在
onUnload中必须调用:uni.offWindowResize(this.handleResize)—— 否则页面复用时会叠加多次回调,导致isLandscape反复翻转、布局抖动 - 别用箭头函数注册:
uni.onWindowResize(() => { ... }),这样uni.offWindowResize无法匹配并移除 - 如果页面支持 tabbar 多次进出,建议在
onShow中先off再on,避免残留
如何用 windowWidth / windowHeight 判断横竖屏
不要写 if (res.orientation === 'landscape'),iOS 返回 undefined,Android 返回值不可靠。统一看尺寸:
- 基础判断:
res.size.windowWidth > res.size.windowHeight→ 大概率横屏(99% 普通手机场景成立) - 加阈值防误判:比如刘海屏竖屏时宽高比接近 1,可加条件
Math.abs(w - h) > 100 && w / h > 1.2 - 避免硬编码 class 切换,用响应式变量驱动:
:class="{ 'landscape-mode': isLandscape }" - 别对
<video></video>或<canvas></canvas>元素做transform: rotate(90deg)—— 这是“假横屏”,WebView 容器仍是竖屏状态,会导致输入框、滚动、手势全部错位
uni.setScreenOrientation 在 App 端几乎不可用
文档里写的这个 API,实际在 iOS 上静默失败(无报错、无回调),Android 上受限极多:要求 targetSdkVersion ≥ 28、Activity 未锁定方向、且用户系统“自动旋转”开关必须打开。调用后既不生效也不提示,极易误判为逻辑 bug。
如果你的目标是“某页强制横屏”,正确路径是改原生配置:
- iOS:
unpackage/res/ios/Info.plist中添加UISupportedInterfaceOrientations数组,只保留UIInterfaceOrientationLandscapeLeft或UIInterfaceOrientationLandscapeRight - Android:
unpackage/res/android/AndroidManifest.xml对应 Activity 加android:screenOrientation="landscape" -
manifest.json中的distribute.ios.orientation或distribute.android.orientation是编译时注入,改完必须重新云打包才生效
真正难处理的是 video 全屏后方向被系统接管——此时 uni.onWindowResize 仍会触发,但 UI 已卡在错误朝向。必须在 @fullscreen-change 中主动补调 uni.setScreenOrientation(仅作尝试),并关闭原生 controls。











