【HarmonyOS NEXT】使用 Navigation 对折叠屏设备页面进行分栏展示,优化 UI 交互

2024-12-25 15:59:23
9次阅读
0个评论

 关键词:折叠屏、navigation、router、路由、分栏、UI

随着科技的发展,手机设备形态也由一面屏向多面屏进行发展,那么软件的UI适配也面临着问题,本篇文章主要解决大屏设备的页面 UI 适配问题,如折叠屏,平板,若不想单独对页面 UI 进行大屏设备的响应式布局的开发,那么可使用官方提供的 navigation 跳转方式,对页面进行分栏展示,从而确保应用能给用户提供良好的 UI 交互,避免出现 “大号APP” 的问题。

本期文章以双折叠屏设备为例,使用 navigation 对页面进行动态分栏跳转及自定义 router 的封装与开发改造。需要注意的是,使用 Navigation 对折叠屏设备进行分栏模式适配后,基础单屏设备(标准屏)并不会出现分栏效果,跟 router 跳转无差异,所以可放心使用。

本期完整demo已提交至Gitee:columnDivision: 【HarmonyOS NEXT】使用 Navigation 对折叠屏设备页面进行分栏展示,优化 UI 交互

目录

效果演示

1. 使用 Navigation() 组件包裹首页面,绑定路由栈

2. 使用 Localstorage 存储路由栈

3. 使用 NavDestination() 组件包裹目标页面,创建页面构建函数

4. 创建 route_map.json 文件,并配置该文件

5. 自定义 router 封装

6. 使用封装的 router 跳转页面

效果演示

未使用 navigation

​编辑

使用 navigation(展开与折叠状态)

​编辑

​编辑

1. 使用 Navigation() 组件包裹首页面,绑定路由栈

应用启动则会进入第一个页面,展示的第一个页面需要使用 Navigation() 对根容器进行包裹,并对其进行路由栈的绑定,后续跳转则需使用绑定的路由栈 pageInfos 进行跳转。

​编辑

2. 使用 Localstorage 存储路由栈

在第一步中创建的 pageInfos 需要被应用共享去使用,我使用的是 Localstorage 方式去存取,也可使用 AppStorage 或单例等其他形式,根据自身业务与开发习惯跳转即可。

因为我使用的是 Localstorage 页面级状态存储的方式,若想被整个 stage 共享,那么需要在 ability 加载时就创建好 Localstorage 并在 loadContent 时传入第二个参数。

​编辑

后续使用即可利用 getShared 获取当前 stage 共享的 localstorage,如:

// 设置 localstorage
LocalStorage.getShared().setOrCreate("NavPathStack", pageInfos)

// 获取 localstorage
LocalStorage.getShared().get("NavPathStack") as NavPathStack

3. 使用 NavDestination() 组件包裹目标页面,创建页面构建函数

使用 navigation 跳转页面,则需要对跳转的目标页面根容器进行改造,外层包裹 NavDestination 组件,并设置 onBackPressed() 回调,因为我们要实现动态的分栏效果,所以在返回手势触发时也需要进行路由栈的计算,详细可查看第 5 步。

组件改造后需要创建构建函数,函数中引入当前的页面组件并进行导出,此处也不可缺少,因为需要在配置文件中进行设置。

​编辑

4. 创建 route_map.json 文件,并配置该文件

在鸿蒙应用开发过程中,页面跳转需要使用到 router ,并在 main_pages.json 中配置页面路由。同理,若想使用 navigation 进行跳转,也需要进行相关的路由配置,不过我们需要手动在 resources/base/profile 下创建 route_map.json 文件,在创建的文件中进行如下路由配置。

字段解释:

name:路由名称,后续跳转时需要使用该名称进行跳转

pageSourceFile:对应页面代码文件的路径

buildFunction:在前一步中改造后导出的构建函数 Builder 名称

​编辑

创建完 route_map.json 并不能立即进行跳转,还需要在 module.json5 中生效该文件,在 module 对象下设置 routerMap 字段,值为 $profile:route_map ,代表刚才在 profile 中创建的 route_map 文件。

​编辑

5. 自定义 router 封装

Navigation 存在默认分栏比例,折叠屏设备在 app 一启动即为分栏展示(右半屏白屏展示,左半屏展示首页),那我们如果想做到 app 一启动,首先全屏展示首页,当需要跳转到下一页时再进行分栏,那么我们可以通过封装自定义 router ,在页面跳转及页面关闭时计算当前路由栈的个数,并动态设置 navBarWidth 分栏的宽度即可实现该效果。

如下代码 router 封装较为简易,仅做演示,我使用的是根据 name 进行跳转,需要根据自身业务进行调整,如页面跳转传参等。

该 Router 类使用 @Observed 装饰,是为了使用类中 navBarWidth 动态属性,在首页面使用 @State 装饰接收 MyRouter,并在首页面的 Navigation 的 .navBarWidth() 中设置 this.MyRouter.navBarWidth ,当类中 navBarWidth 发生变化时,即可进行分栏比例 UI 的动态更新。

​编辑

/**
 * 简易 router 封装
 */
@Observed
export class Router {
  navBarWidth: string = "100%"

  /**
   * 跳转
   * @param name
   * @param pageInfos
   */
  pushDestinationByName(name: string, pageInfos: NavPathStack) {
    pageInfos.pushDestinationByName(name, null)
    this.calcNavBarWidth(pageInfos)
  }

  backPress(pageInfos: NavPathStack) {
    let popR: NavPathInfo | undefined = pageInfos.pop()
    this.calcNavBarWidth(pageInfos)
    return popR
  }

  calcNavBarWidth(pageInfos: NavPathStack) {
    if (pageInfos.getAllPathName().length == 0) {
      this.navBarWidth = "100%"
    } else {
      this.navBarWidth = "50%"
    }
    console.log("luvi pageInfos > " + JSON.stringify(pageInfos))
  }
}

export const MyRouter = new Router()

6. 使用封装的 router 跳转页面

在第 2 步中,创建 Builder 构建函数后并配置了 route_map,并设置了页面名称 name,在第 5 步中封装的 pushDestinationByName 方法需要传递目标页面的 name 与路由栈,方法内则会使用该路由栈进行页面跳转,并计算分栏宽度。

// 直接使用封装的 MyRouter 进行跳转即可
MyRouter.pushDestinationByName("NewsPage", this.pageInfos)

收藏00

登录 后评论。没有帐号? 注册 一个。