
本文将深入讲解在 HarmonyOS 5 中如何控制应用的横竖屏切换包括静态配置、动态控制、监听方向变化以及多设备适配的最佳实践。一、概述横竖屏切换是移动应用开发中的常见需求。在 HarmonyOS 中屏幕方向管理涉及多个层面Ability 配置通过module.json5配置页面的默认方向窗口管理通过windowAPI 动态控制窗口方向布局适配根据方向变化动态调整 UI 布局事件监听监听方向变化并做出响应HarmonyOS 5 提供了灵活的屏幕方向管理能力支持从简单的固定方向到复杂的多设备自适应策略。二、静态配置屏幕方向2.1 module.json5 配置在module.json5文件的abilities标签中通过orientation属性配置页面的默认方向json{ module: { abilities: [ { name: EntryAbility, orientation: landscape // 强制横屏 } ] } }2.2 orientation 可选值值说明unspecified系统自动判断默认portrait固定竖屏landscape固定横屏auto_rotation自动旋转auto_rotation_restricted受限自动旋转landscape_inverted反向横屏portrait_inverted反向竖屏2.3 应用场景视频播放器全局设置为landscape强制横屏播放阅读类应用全局设置为portrait保持竖屏阅读通用应用设置为unspecified允许系统自动适配三、动态控制横竖屏切换3.1 核心 API使用window.setPreferredOrientation()方法动态控制窗口方向typescriptimport { window } from kit.ArkUI; // 获取窗口对象 let windowStage AppStorage.get(windowStage) as window.WindowStage; let mainWindow windowStage.getMainWindowSync(); // 切换为横屏 mainWindow.setPreferredOrientation(window.Orientation.LANDSCAPE); // 切换为竖屏 mainWindow.setPreferredOrientation(window.Orientation.PORTRAIT); // 开启自动旋转 mainWindow.setPreferredOrientation(window.Orientation.AUTO_ROTATION);3.2 在页面中控制方向在 ArkTS 页面中通过onPageShow或aboutToAppear生命周期控制方向typescriptimport { window } from kit.ArkUI; Entry Component struct VideoPlayerPage { private windowStage: window.WindowStage AppStorage.get(windowStage) as window.WindowStage; private mainWindow: window.Window this.windowStage.getMainWindowSync(); onPageShow() { // 进入页面时强制横屏 this.mainWindow.setPreferredOrientation(window.Orientation.LANDSCAPE); } onPageHide() { // 离开页面时恢复竖屏 this.mainWindow.setPreferredOrientation(window.Orientation.PORTRAIT); } build() { // 页面内容 } }3.3 使用回调处理结果typescripttry { mainWindow.setPreferredOrientation( window.Orientation.AUTO_ROTATION, (err: BusinessError) { if (err.code) { console.error(设置方向失败: JSON.stringify(err)); return; } console.info(设置方向成功); } ); } catch (exception) { console.error(设置方向异常: JSON.stringify(exception)); }四、监听横竖屏变化4.1 方法一使用媒体查询推荐mediaqueryAPI 是监听屏幕方向变化的标准方式typescriptimport { mediaquery } from kit.ArkUI; Entry Component struct ScreenRotationPage { State isLandscape: boolean false; private listener?: mediaquery.MediaQueryListener; aboutToAppear() { // 创建横屏监听器 this.listener mediaquery.matchMediaSync((orientation: landscape)); // 注册回调 this.listener.on(change, (result: mediaquery.MediaQueryResult) { this.isLandscape result.matches; console.log(屏幕方向: ${this.isLandscape ? 横屏 : 竖屏}); }); } aboutToDisappear() { // 移除监听器 if (this.listener) { this.listener.off(change); } } build() { Column() { Text(this.isLandscape ? 当前为横屏 : 当前为竖屏) .fontSize(20) } .width(100%) .height(100%) } }4.2 方法二监听窗口尺寸变化通过监听窗口尺寸变化判断横竖屏状态typescriptimport { window } from kit.ArkUI; Entry Component struct SizeChangePage { State isLandscape: boolean false; private windowStage: window.WindowStage AppStorage.get(windowStage) as window.WindowStage; private mainWindow: window.Window this.windowStage.getMainWindowSync(); aboutToAppear() { // 注册窗口尺寸变化监听 this.mainWindow.on(windowSizeChange, (data: window.Size) { // 判断宽高比 const width px2vp(data.width); const height px2vp(data.height); this.isLandscape width height; }); } aboutToDisappear() { this.mainWindow.off(windowSizeChange); } build() { // 根据 isLandscape 渲染不同布局 } }4.3 方法三在 Ability 层监听在UIAbility中通过onConfigurationChanged监听配置变化typescriptimport { UIAbility, Configuration } from kit.AbilityKit; export default class EntryAbility extends UIAbility { onConfigurationChanged(config: Configuration) { // 检查方向变化 if (config.orientation Configuration.Orientation.LANDSCAPE) { console.log(切换到横屏); } else if (config.orientation Configuration.Orientation.PORTRAIT) { console.log(切换到竖屏); } } }五、响应式布局适配5.1 根据方向动态调整布局typescriptEntry Component struct NewsListPage { State isLandscape: boolean false; private listener?: mediaquery.MediaQueryListener; aboutToAppear() { this.listener mediaquery.matchMediaSync((orientation: landscape)); this.listener.on(change, (result) { this.isLandscape result.matches; }); } aboutToDisappear() { this.listener?.off(change); } build() { Column() { // 动态网格横屏双列竖屏单列 Grid() { ForEach(this.newsData, (item: NewsItem) { GridItem() { NewsCard({ news: item }) } }) } .columnsTemplate(this.isLandscape ? 1fr 1fr : 1fr) .rowsGap(10) .columnsGap(10) } } }5.2 使用 GridContainer 实现断点适配typescriptGridContainer() { // 内容 } .columnsTemplate(this.isLandscape ? 1fr 1fr 1fr : 1fr 1fr)六、多设备横竖屏适配策略6.1 设备类型判断不同设备需要不同的横竖屏策略typescriptimport { deviceInfo } from kit.BasicServicesKit; // 判断设备类型 if (deviceInfo.deviceType tablet) { // 平板支持自动旋转 mainWindow.setPreferredOrientation(window.Orientation.AUTO_ROTATION_RESTRICTED); } else { // 手机默认竖屏 mainWindow.setPreferredOrientation(window.Orientation.PORTRAIT); }6.2 基于窗口尺寸的策略推荐使用窗口尺寸判断是否支持旋转typescriptconst BREAKPOINT_MD 600; function getWindowSize(): window.Rect { let windowRect mainWindow.getWindowProperties().windowRect; return windowRect; } function shouldSupportRotation(): boolean { let rect getWindowSize(); let widthVp px2vp(rect.width); let heightVp px2vp(rect.height); let aspectRatio heightVp / widthVp; // 条件1窗口最小边 600vp大屏设备 if (Math.min(widthVp, heightVp) BREAKPOINT_MD) { return true; } // 条件2类方屏宽高比在 0.8~1.2 之间 if (aspectRatio 0.8 aspectRatio 1.2) { return true; } // 条件3平板设备 if (deviceInfo.deviceType tablet) { return true; } return false; // 默认竖屏 }6.3 完整的多设备适配方案在UIAbility中实现完整的旋转策略typescriptimport { UIAbility } from kit.AbilityKit; import { window } from kit.ArkUI; import { deviceInfo } from kit.BasicServicesKit; export default class EntryAbility extends UIAbility { private windowObj?: window.Window; setDefaultOrientation(): void { const BREAKPOINT_MD 600; let windowRect this.windowObj!.getWindowProperties().windowRect; let windowWidthVp px2vp(windowRect.width); let windowHeightVp px2vp(windowRect.height); let aspectRatio windowHeightVp / windowWidthVp; // 判断是否支持旋转 if ( Math.min(windowWidthVp, windowHeightVp) BREAKPOINT_MD || (aspectRatio 0.8 aspectRatio 1.2) || deviceInfo.deviceType tablet ) { // 支持自动旋转 this.windowObj?.setPreferredOrientation( window.Orientation.AUTO_ROTATION_RESTRICTED ); } else { // 竖屏显示 this.windowObj?.setPreferredOrientation( window.Orientation.PORTRAIT ); } } onWindowStageCreate(windowStage: window.WindowStage): void { windowStage.getMainWindow().then((windowObj) { this.windowObj windowObj; this.setDefaultOrientation(); // 监听窗口尺寸变化 this.windowObj.on(windowSizeChange, () { this.setDefaultOrientation(); }); }); windowStage.loadContent(pages/Index); } }七、注意事项与最佳实践7.1 状态保存与恢复横竖屏切换时页面会重新渲染需要使用State保存状态typescriptEntry Component struct MyPage { State videoProgress: number 0; State currentTab: number 0; // State 装饰的变量在配置变更时会自动保留 }7.2 性能优化避免在onConfigurationChanged中进行耗时操作使用State精确控制需要更新的组件大型列表使用 LazyForEach 实现懒加载7.3 折叠屏特殊处理折叠屏设备需要额外关注折叠态变化typescriptimport { display } from kit.ArkUI; // 检查是否为折叠屏 let isFoldable display.isFoldable(); // 获取折叠状态 display.getFoldStatus((err, status) { if (status display.FoldStatus.FOLD_STATUS_EXPANDED) { // 展开态支持横竖屏 } else if (status display.FoldStatus.FOLD_STATUS_FOLDED) { // 折叠态类似手机 } });7.4 常见问题Q1页面固定了方向但是切换页面后方向恢复A方向设置是基于窗口的需要在每个页面的onPageShow中重新设置方向。Q2监听方向变化不生效A检查是否在aboutToDisappear中正确移除监听器避免内存泄漏。Q3横竖屏切换时 UI 闪烁A使用State驱动布局变化避免在build方法中使用复杂的条件判断。八、总结方法适用场景优先级module.json5静态配置整个页面固定方向最低setPreferredOrientation()动态切换方向推荐mediaquery监听响应式布局推荐窗口尺寸监听需要获取具体尺寸备选Ability 配置变更系统级监听深度需求HarmonyOS 5 提供了完整的横竖屏管理能力从简单的固定方向到复杂的多设备自适应开发者可以根据应用需求选择合适的方案。在多设备场景下建议结合设备类型、窗口尺寸和宽高比综合判断是否支持旋转以实现最佳的跨端体验。