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

news2024/10/28 7:29:40

关键词:折叠屏、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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2225283.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySql数据库中数据类型

本篇将介绍在 MySql 中的所有数据类型,其中主要分为四类:数值类型、文本和二进制类型、时间日期、String 类型。如下(图片来源:MySQL数据库): 目录如下: 目录 数值类型 1. 整数类型 2. …

[MoeCTF 2022]endian

查看发现是64位文件,且看到了amd64-64-little(这里是小端序) 所以我们要反向输入 对于整数 0x12345678,在小端序存储下的内存布局为: 地址 内容 低地址 0x78 0x56 0x34 高地址 0x12 查看main函数&#xff0c…

Python4

4. 更多控制流工具 除了刚介绍的 while 语句&#xff0c;Python 还用了一些别的。我们将在本章中遇到它们。 4.1. if 语句 if elif else if x<0: x 0 print(Negative changed to zero) elif x0: print( zero) else: print(More) 4.2. for 语句 Pyth…

游戏服务器被攻击有办法防护吗

游戏服务器受到攻击时比较常见的。就算是刚上线的游戏&#xff0c;都会有被攻击的时候。游戏服务器受到攻击的原因以及解决方案有哪些呢&#xff1f; 游戏服务器被攻击的原因有哪些呢&#xff1f; 1、常见的攻击&#xff0c;大部分来自于同行之间的恶意竞争&#xff0c;你的游…

Rust 力扣 - 3. 无重复字符的最长子串

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 我们需要记录当前子串的开始下标&#xff0c;一个哈希表记录字符和遍历过程中最后一次出现的索引 遍历字符串&#xff0c;如果在当前字符在哈希表中有记录&#xff0c;并且索引下标大于当前子串的开始下标&…

Lesson12---queue

Lesson12—queue 本篇博客介绍了cqueue的介绍使用以及模拟实现 文章目录 Lesson12---queue前言一、queue的成员函数1 queue2.empty3.size4.front5.back6.push7.pop 二、相关题目三、模拟实现完整代码 四、deque&#xff08;双端队列&#xff09;总结 前言 queue的文档:https:…

go高并发之路——本地缓存

一、使用场景 试想一个场景&#xff0c;有一个配置服务系统&#xff0c;里面存储着各种各样的配置&#xff0c;比如直播间的直播信息、点赞、签到、红包、带货等等。这些配置信息有两个特点&#xff1a; 1、并发量可能会特别特别大&#xff0c;试想一下&#xff0c;一个几十万…

CANopen中错误帧的制造和观测

本文讲述如何制造和观察CANopen中的错误帧&#xff08;Error frame&#xff09;&#xff0c;以Linux下的“VCAN0”为CAN接口来做测试&#xff0c;所以事先要先创建vcan0 一 制造错误帧 首先安装python CAN&#xff0c; pip3 install python-can然后参考python can的文档编写如…

Android View

前面我们了解了Android四大组件的工作流程&#xff0c;Android中还存在一个和四大组件地位相同的概念&#xff1a;View&#xff0c;用于向用户页面展示内容。我们经常使用的TextView、Button、ImageView控件等都继承于它&#xff0c;也会自定义View实现自定义效果。View类源码内…

2024CSP-J题目简析

扑克牌 1.题目大意&#xff1a;给定n张扑克牌和这n张扑克牌的花色和大小&#xff08;可能会有重复&#xff09;&#xff0c;需要输出还需要多少张牌才能凑齐一副扑克牌&#xff08;这里不考虑大小王&#xff0c;所以共52张&#xff09;。 2.思路概要&#xff1a;由于扑克牌会…

C++ | Leetcode C++题解之第513题找树左下角的值

题目&#xff1a; 题解&#xff1a; class Solution { public:int findBottomLeftValue(TreeNode* root) {int ret;queue<TreeNode *> q;q.push(root);while (!q.empty()) {auto p q.front();q.pop();if (p->right) {q.push(p->right);}if (p->left) {q.push(…

配置smaba (Linux与windows通信)

在Ubuntu上安装Samba是一个简单的过程。以下是详细的步骤&#xff0c;帮助你从安装到基本配置。 步骤1&#xff1a;更新软件包列表 首先&#xff0c;打开终端&#xff0c;确保你的软件包列表是最新的&#xff1a; sudo apt update 步骤2&#xff1a;安装 Samba 接下来…

若依学习 后端传过来的数据在控制台打印为空

导言: 在做若依二次开发时遇到个没见过的bug&#xff0c;用了一些时间排&#xff0c;发现有自己没学过的东西。所以记录一下。后端用的是c#的asp.net core 问题描述&#xff1a; 后端穿过来的有数据的参数(数组)roleIds在控制台打印为空 后端字段定义: 后端数据&#xff1a; 前…

centos-LAMP搭建与配置(论坛网站)

文章目录 LAMP简介搭建LAMP环境安装apache&#xff08;httpd&#xff09;安装mysql安装PHP安装php-mysql安装phpwind LAMP简介 LAMP是指一组通常一起使用来运行动态网站或者服务器的自由软件名称首字母缩写&#xff1a;Linux操作系统&#xff0c;网页服务器Apache&#xff0c;…

【LangChain系列3】【检索模块详解】

目录 前言一、LangChain1-1、介绍1-2、LangChain抽象出来的核心模块1-3、特点1-4、langchain解决的一些行业痛点1-5、安装 二、检索模块详解2-1、文档加载器2-1-1、Demo示例2-1-2、JSON加载2-1-3、CSV加载 2-2、文档转换器2-2-1、按字符进行拆分2-2-2、按代码分割2-2-3、Markdo…

arm 体系架构-过程调用标准AAPCS

一、什么是AAPCS&#xff1f; 旧时&#xff0c;ARM 过程调用标准叫做 APCS (ARM Procedure Call Standard)&#xff0c;Thumb的过程调用标准为 TPCS。如今这两种叫法已经废弃&#xff0c;统一称作 AAPCS (Procedure Call Standard for the ARM Architecture)。 AAPCS 是 ARM …

UE5之5.4 第三人称示例代码阅读

第三人称的代码相对第一人称少了很多&#xff0c;只有一个移动跳跃的能力 构造函数&#xff0c;添加角色的移动属性&#xff0c;限制了当controller移动角色不会乱转&#xff0c;然后创建了一个相机杆&#xff0c;创建了一个跟随相机&#xff0c;绑到相机杆上 然后在这个函数设…

用二分法查找有序容器的插入点

例子&#xff1a; int main() {vector<int> vec { 1,2,3,4,5,7,8,9 };auto n alg.find_binary_insert_pos(vec.begin(), vec.end(), 6);vec.insert(vec.begin() n, 6);_pn(vec);list<int> lst { 1,10,11,9,5 };for (auto& v : lst) {//添加不存在的元素au…

241024-Ragflow离线部署Docker-Rootless环境配置修改

A. 最终效果 B. 文件修改 docker-compose.yml include:- path: ./docker-compose-base.ymlenv_file: ./.envservices:ragflow:depends_on:mysql:condition: service_healthyes01:condition: service_healthyimage: ${RAGFLOW_IMAGE}container_name: ragflow-serverports:- ${…

D50【python 接口自动化学习】- python基础之类

day50 init方法 学习日期&#xff1a;20241027 学习目标&#xff1a;类 -- 64 init方法&#xff1a;如何为对象传递参数&#xff1f; 学习笔记&#xff1a; 魔术方法 init方法 class Klass(object):# 定义初始化方法&#xff0c;类实例化时自动进行初始化def __init__(self…