写点什么

【HarmonyOS Next】鸿蒙应用折叠屏设备适配方案

作者:GeorgeGcs
  • 2025-03-24
    上海
  • 本文字数:2355 字

    阅读完需:约 8 分钟

【HarmonyOS Next】鸿蒙应用折叠屏设备适配方案

【HarmonyOS Next】鸿蒙应用折叠屏设备适配方案

一、前言


目前应用上架华为 AGC 平台,都会被要求适配折叠屏设备。目前华为系列的折叠屏手机,有华为 Mate 系列(左右折叠,华为 Mate XT 三折叠),华为 Pocket 系列(上下折叠)。

二、适配方案思路探讨

目前鸿蒙应用适配折叠屏的思路分为两种:分栏和全屏适配。




分栏在左右折叠手机上,相当于首页一级页面在左边,二级子页面点开后在右边。三折叠上形态未知,有知道的小伙伴可以同步下。上下折叠手机上,不以分栏的方式呈现,和直板机相似。


单栏(全屏)


全屏适配并且拉伸界面,不进行界面处理。而是处理成平板的 UI 布局形式,和直板机界面排版不一样。这种适配方案效果最好,但是工作量较大。


不过目前华为官方反馈说以后不演进分栏方案了。三折叠和 25 年三月新形态手机的适配都是风险。

三、适配方案实现

传统的 router 路由在折叠屏适配上,无法提供良好支撑。所以建议切换到 Navigation。


因为不管是路由回退栈的处理,还是页面数的限制问题。Navigation 都优于 router,并且华为官方已经明确表示,推荐 Navgation 的方案。


当然如果有了解 HMRouter 的同学,也可以使用,因为 HMRouter 就是在 Navgation 上进行封装和优化的三方库。


分栏设置主页面容器 Navigation,mode 属性为 NavigationMode.Stack:


@Entry@Componentstruct MainPage {  @State message: string = 'Hello World';  // 创建一个页面栈对象并传入Navigation  pageStack: NavPathStack = new NavPathStack()
build() { Navigation(this.pageStack) { // 页面布局 Row() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) .onClick(()=>{ // 跳转到子页面 this.pageStack.pushDestination({ name: "OnePage", }, false); //该false表示不需要转场动画,默认是有的 }) } .width('100%') } .height('100%') } .mode(NavigationMode.Split)
}}
复制代码


细节可参考该文章,点击跳转=》(【HarmonyOS】关于官方推荐的组件级路由Navigation的心得体会)




单栏(全屏)设置主页面容器 Navigation,mode 属性为 NavigationMode.Stack:


@Entry@Componentstruct MainPage {  @State message: string = 'Hello World';  // 创建一个页面栈对象并传入Navigation  pageStack: NavPathStack = new NavPathStack()    // 使用 @State 装饰器定义响应式变量,用于存储组件的宽高  @State width: number = 0  @State height: number = 0
build() { Navigation(this.pageStack) { // 页面布局 Row() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) .onClick(()=>{ // 跳转到子页面 this.pageStack.pushDestination({ name: "OnePage", }, false); //该false表示不需要转场动画,默认是有的 }) } .width('100%') } .height('100%') } // 分为三种模式,(默认)自动NavigationMode.Auto,单页面NavigationMode.Stack和分栏NavigationMode.Split .mode(NavigationMode.Stack) .backgroundColor(Color.Gray) .onSizeChange((width: number, height: number) => { // 当组件大小变化时,更新宽高信息 this.width = width this.height = height }) .onAreaChange( (oldValue: Area, newValue: Area)=>{ // newValue.width }) }}
复制代码


界面需要监听最外层宽高,onSizeChange 和 onAreaChange 都可以,建议使用 onAreaChange,用于判定界面是否需要切换为平板适配模式。【目前官方推荐使用 600vp 作为当页面宽度大于等于一定阈值点】


子页面添加跳转入口函数,添加 NavDestination 生命周期的处理:


// 跳转页面入口函数@Builderexport function OnePageBuilder() {  OnePage()}
@Entry@Componentstruct OnePage { private TAG: string = "OnePage"; @State message: string = 'Hello World'; pathStack: NavPathStack = new NavPathStack();
build() { NavDestination() { Row() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) } .width('100%') } .height('100%') }.onShown(()=>{ console.log(this.TAG, "OnePage onShown"); }) .onReady((context: NavDestinationContext) => { this.pathStack = context.pathStack; }) }}
复制代码


在首页获取到的宽高,可以使用多种方式缓存起来,例如放到 AppStorage,单例中。二级等子页面进入后就可以判定。


当然页面中的动态监听也需要保存。场景需要覆盖,因为在首页时用户可能是折叠状态,进入子页面后展开的情况也有。


当然判定手机折叠屏状态,除了通过宽高,也可通过官方提供的折叠屏状态进行判断,不过在上下折叠屏手机上也会被激活,这里需要额外在判定一下。


import { display } from '@kit.ArkUI';
let ret: boolean = false;// 当前是否是折叠屏ret = display.isFoldable();
if(ret){let callback: Callback<display.FoldStatus> = (data: display.FoldStatus) => { console.info('Listening enabled. Data: ' + JSON.stringify(data));};display.on('foldStatusChange', callback);}

// 页面销毁时,记得取消监听display.off('foldStatusChange', callback);
复制代码



发布于: 刚刚阅读数: 4
用户头像

GeorgeGcs

关注

路漫漫其修远兮,吾将上下而求索。 2024-12-24 加入

历经腾讯,宝马,研究所,金融。 待过私企,外企,央企。 深耕大应用开发领域十年。 OpenHarmony,HarmonyOS,Flutter,H5,Android,IOS。 目前任职鸿蒙应用架构师。 HarmonyOS官方认证创作先锋

评论

发布
暂无评论
【HarmonyOS Next】鸿蒙应用折叠屏设备适配方案_折叠屏_GeorgeGcs_InfoQ写作社区