app端锁定屏幕方向必须用plus.screen.lockorientation,且需条件编译#ifdef app-plus包裹;ios需manifest.json预设方向,android需避免activity硬编码screenorientation;锁屏后须显式恢复,推荐plus.ready中调用并配合onshow监听还原。

uni-app App端如何调用原生API锁定屏幕方向
uni-app 的 uni.setScreenOrientation 在 App 端(iOS/Android)默认不可用,因为 H5 和小程序环境不支持该能力,而 App 端需依赖原生插件或条件编译调用原生层接口。直接写 uni.setScreenOrientation('landscape') 在 App 里会静默失败或报错 setScreenOrientation is not a function。
正确路径是:通过条件编译 + 原生插件(如 DCloud 官方的 screen-orientation 插件)或自定义原生模块实现。DCloud 插件市场已下架部分旧插件,目前推荐使用内置的 plus.screen API(仅限 App 端运行时可用)。
- 必须用
#ifdef APP-PLUS包裹,否则 H5 或小程序构建会报错 -
plus.screen.lockOrientation('landscape-primary')才生效,参数值固定为'portrait'、'landscape-primary'、'landscape-secondary',不能传'landscape' - iOS 上需在
manifest.json → App 设置 → 屏幕方向中勾选对应方向,否则系统级禁止旋转 - Android 8.0+ 需确保 activity 的
android:screenOrientation没被硬编码为portrait(检查nativeplugins/android/res/values/AndroidManifest.xml或自定义基座配置)
怎么安全地切换并恢复默认屏幕方向
App 端锁屏后不会自动恢复,必须显式调用解锁逻辑,否则退出页面仍保持锁定状态。常见错误是只锁不放,导致整个 App 卡死在横屏。
建议封装成可配对的函数,记录上一次状态,并在页面卸载时自动还原:
export const toggleOrientation = (to: 'portrait' | 'landscape-primary' | 'landscape-secondary') => {
#ifdef APP-PLUS
const prev = plus.screen.getOrientation();
// 保存原始方向用于还原
uni.$emit('screen-orientation-prev', prev);
plus.screen.lockOrientation(to);
#endif
};
export const restoreOrientation = () => {
#ifdef APP-PLUS
const prev = uni.$off('screen-orientation-prev') || 'portrait';
plus.screen.lockOrientation(prev);
#endif
};
- 不要依赖
onUnload单点还原——App 后台切前台、tabBar 切换等场景不会触发该钩子 - 更稳妥做法是在全局 mixin 或路由守卫中监听
onShow,判断是否需要还原(比如上个页面锁了屏但当前页不需锁定) -
plus.screen.getOrientation()返回的是当前实际方向字符串,不是布尔值,注意类型校验
为什么 onReady 里调用 lockOrientation 有时无效
因为 plus.screen API 必须在 native ready 后才能调用,而 onReady 时机早于原生渲染完成,尤其在冷启动或首屏加载时容易失败。
- 改用
uni.$on('nvue:ready', ...)(仅 nvue 页面)或plus.ready(() => { ... })确保原生环境就绪 - 如果是 vue 页面(非 nvue),需加延迟兜底:
setTimeout(() => plus.screen.lockOrientation(...), 300) - 真机调试务必用自定义调试基座(非普通“运行到浏览器”),否则
plus对象为 undefined - 某些 Android 厂商(如华为、小米)系统会拦截第三方应用锁屏请求,需引导用户手动开启“允许修改屏幕旋转”权限(无标准 API,只能提示)
横竖屏切换时 UI 错位或白屏怎么办
这不是 uni-app 本身问题,而是 WebView 渲染层未同步重排。尤其在 iOS App 端,lockOrientation 后视口尺寸未及时更新,uni.getSystemInfoSync().windowWidth 仍返回旧值。
- 强制触发一次 resize:调用
uni.$emit('resize')并监听该事件重新计算布局 - 避免在
mounted中直接读取windowWidth,改用uni.onWindowResize动态响应 - nvue 页面表现更稳定,推荐关键横屏页(如视频播放器)用 nvue 实现,其
flex-direction和width能随 orientation 自动适配 - 慎用
transform: rotate(90deg)模拟横屏——会导致 input 失焦、滚动异常、canvas 渲染错乱
真正麻烦的不是怎么锁,而是什么时候该锁、锁多久、谁负责还原。很多团队卡在“锁了横屏,用户切后台再回来还是横屏”,根源在于没把屏幕方向当成一个需要生命周期管理的状态,而不是一次性的指令。











