当前位置: 首页 > news >正文

从零开始开发纯血鸿蒙应用之实现起始页

从零开始开发纯血鸿蒙应用

  • 一、前言
  • 二、主要页面
  • 三、应用起始页
  • 四、MainPageContent 实现
    • 1、一级结构
    • 2、二级结构
      • 2.1、EmptyContent
      • 2.2、FileListContent
        • 2.2.1、ViewAction:
        • 2.2.2、EditAction
        • 2.2.3、DeleteAction
        • 2.2.4、ShareAction
  • 五、载入起始页的时机
  • 五、总结

一、前言

从本篇开始,将对 TxtEdit 的业务功能进行逐一实现,而业务功能是宿主在一个个具体的应用页面上的,所以,当务之急,便是将 TxtEdit 的主要页面、即用于编辑和浏览纯文本文件的页面进行实现。

目前,第一版实现中,主要页面有如下几个:
在这里插入图片描述
像那些用于说明app开发者信息,以及进行问题反馈等页面,个人认为属于非关键的主要页面,因此,在应用开发过程中,其优先级较低,可以放在最后去实现。

二、主要页面

TxtEdit 在版本 1.0.x 的主要页面,共有三套:

  • 应用起始页,由一个 page 文件组成
  • 内部文件处理页,由两个 page 文件组成,分别用于编辑和浏览应用的沙箱文件
  • 外部文件处理页,也是两个 page 文件组成,用于浏览和导入。

三、应用起始页

应用起始页,由 Index.ets 文件实现,页面路由为 pages/Index,它的代码内容结构如下:
在这里插入图片描述
根据 build 函数体,可知 TxtEdit 的起始页,和众多app的起始页一样,都是采用 Tabs 组件进行页面结构搭建,我这里,由于追求简洁和实用,Tabs 里面的 TabContent 也即所谓 Tab 页,只有两个。

在鸿蒙UI中,Tabs 组件具有横向纵向两种方向,并且 tabBar 也即 Tab 页标题栏,允许传入一个注解 @Builder 的 UI 构建函数,从而实现更美观或更个性化的应用起始页,由于本人美术天赋较差,设计不出让人眼前一亮的 UI 样式,只有如下的简简单单的:

@Builder
tabBuilder(title: string, targetIndex: number) {Column() {Text(title).fontColor(this.currentIndex === targetIndex ? '#ff0af10a' : '#fff5f6f5')}.width('100%').height(60).justifyContent(FlexAlign.Center)
}

只做了根据Tab页是否被选中进行Tab标题颜色的变更。

为了达到 Tabs 组件居底布局,页面标题居顶布局,我将 Tabs 套在一个使用了 BottomColumn 样式的 Column 文件中,再将这个 Column 放在一个使用 RootTopColumn 样式的 Column 文件中。

TxtEdit 的起始页中的第一个 Tab 页,即文件 Tab 页,顾名思义,用于展示文件列表,方便用户进行内部文件的操作和管理,这时候,涉及到无内部文件和有内部文件两种状态的页面内容,要以什么样的方式进行载入?

方案不外乎两种,一种是在 TabContent 里面直接做条件渲染,根据条件使用不同的Content ,另一种是TabContent 里面使用一个直接展示的 Content,将条件渲染下移到该Content里面

本人采取的就是第二种方案:

build() {Column(){PageTitleBar({ title: 'TxtEdit'})Column(){Tabs(){TabContent(){Column(){MainPageContent()}.attributeModifier(this.centerColumn)}.tabBar(this.tabBuilder('文件', 0))TabContent(){AboutPageContent()}.tabBar(this.tabBuilder('关于', 1))}.attributeModifier(this.blackTabs).onChange((index) => {this.currentIndex = index})}.attributeModifier(this.bottomColumn)}.attributeModifier(this.rootContainer)
}

四、MainPageContent 实现

在我尚未叙述具体实现时,屏幕前的你,对于 MainPageContent 的实现,心里有什么样的方案?是否认为,用一个类似 if-else 的语法结构,就能够实现无文件页面和有文件页面的载入显示?

如果是这样,那么你大概没有考虑到,用户场景存在着一种情况,就是从有文件到无文件的状态回退。此外,实时的 UI 刷新,比如用户创建第一个文件结束后,回到起始页,应当将用户创建的文件展示在文件列表中,而不是要用户杀掉app进程重新进入才能看到。

总的来说,app页面的实现,并非是想当然而,需要将可能的动态刷新场景兜底住,才能给用户一个较好的UI体验和交互操作体验。

1、一级结构

本篇后续,以及后面的每一篇博文,为了控制篇幅,主要是内容字符数,源码会贴的比较少,更多以图片的形式展示,完整源码还请访问gitee仓库获取,当然了,gitCode仓库也是准备了的。

在这里插入图片描述
由简入繁,先看一下函数体都收起时的内容。整体上,在 MainPageContent 中,最开始的地方,定义了一组辅助 UI 刷新的私有字段或状态变量,其中,状态变量是触发 UI 刷新所不可或缺的。

在页面即将渲染时,也即生命周期函数 aboutToAppear 所对应的阶段,需要做一些初始化工作:
在这里插入图片描述
利用项目内部 API,即 FileUtil 去获取内部文件的文件名列表,并且根据列表的空与非空,决定最终渲染的内容是 EmptyContent 还是 FileListContent,我这里所采用的条件渲染控制,并非鸿蒙UI所支持的 if-else 语法,而是组件属性 visibility,如此做法,其考量就是让UI代码更纯粹些
在这里插入图片描述
为了满足实时刷新UI内容的需要,doRefresh 函数做了如下工作:
在这里插入图片描述
虽然,和 aboutToAppear 很像,却也是必不可少的,毕竟已经通过装饰器 @Watch 与 refresh 做了绑定,而 refresh 实际上是一个应用全局的UI状态存储 中的字段,利用应用全局的UI状态存储机制,可以做到在B页面控制A页面进行UI更新,具体用法后面会给出。

2、二级结构

MainPageContent 的二级结构,实际对应的就是 EmptyContent 和 FileListContent。鉴于 EmptyContent 的实现更为简单,所以分析顺序就从 EmptyContent 开始。
在这里插入图片描述

2.1、EmptyContent

在这里插入图片描述

如图所示,开始处也是一批字段的定义,其中的 dialog 字段实际是一个 自定义弹窗
在这里插入图片描述
通过代入 CustomDialogController 的参数 alignment,将弹窗设置为页面居中显示,这里需要提醒一下 DevEco Studio 的 UI 预览器和真机显示上,在自定义弹窗上的区别,预览器显示弹窗是默认居中的,但真机则不是如此;另一个带入 CustomDialogController 的参数,用于控制是否允许自动关闭弹窗,即点击弹窗外的区域时是否允许关闭弹窗,显然,我这里设置为不允许,因此,弹窗的关闭只能通过显示在弹窗上的两个按钮去进行:
在这里插入图片描述
这个弹窗的打开动作,我将它放在“新建或导入按钮”中。

2.2、FileListContent

在这里插入图片描述
FileListContent 的结构,与 EmptyContent 的结构很相似,只不过“新建或导入”按钮上方,变成了一个列表组件。列表组件的列表项,根据fileList也即内部文件名列表动态生成,每个列表项都是由 RecentFileItem 实现:
在这里插入图片描述
RecentFileItem 的实现如下:
在这里插入图片描述
其显示效果如图:
在这里插入图片描述
点击“操作”文本,会有弹出式菜单显示出来,该菜单提供四个操作:查看、编辑、分享和删除。弹出式菜单的使用,只需在鸿蒙UI组件的bindMenu传入菜单绘制方法即可,也就是这里的 OptionMenu 方法:
在这里插入图片描述
四个操作的响应逻辑,通过 RecentFileItem 的四个函数参数载入,每一个具体实现逻辑,下面一一介绍:

2.2.1、ViewAction:

在这里插入图片描述
该动作的含义,就是浏览当前列表项对应的沙箱文件,实现代码比较简单,就是将对应的沙箱文件名通过路由参数带入到 ViewFilePage 中。

2.2.2、EditAction

在这里插入图片描述
动作含义就是编辑当前列表项对应的沙箱文件,由于实现代码与 ViewAction 类似,便不过多赘述。

2.2.3、DeleteAction

在这里插入图片描述
动作含义就是删除当前列表项对应的沙箱文件,在实现方面,主要用项目内部 API FileUtil.deleteFile(this.ctx, item) 实现文件的删除,而在删除成功的回调处理中,会对 TxtEdit 的起始页进行 UI 更新,即当最后一个内部文件被删除时,起始页重新显示无文件对应的页面内容;否则仍旧显示文件列表

2.2.4、ShareAction

在这里插入图片描述
该动作的含义,就是分享当前列表项对应的沙箱文件,在具体实现方面,也是用了一个项目内部 API,其都对应的具体代码如下:
在这里插入图片描述
主要就是利用鸿蒙系统提供的系统分享面板进行文件的分享:
在这里插入图片描述
要呼出如上的系统分享面板,需要做以下几方面的工作:
1)判断要分享的文件是否存在,避免引起其他应用出现异常
2)获取待分享文件对应的 utdTypeId
3)借助 systemShare.SharedData 包装分享内容,因为系统分享面板只接受 systemShare.SharedData 的数据
4)创建并持有 systemShare.ShareController,即系统分享面板控制器
5)借助系统分享面板控制器拉起系统分享面板,并对是否成功拉起面板进行回调处理

五、载入起始页的时机

在鸿蒙应用开发框架中,应用起始页的载入时机为,应用声明周期函数 onWindowStageCreate
在这里插入图片描述
在该函数中,会通过系统 API windowStage.loadContent 去加载某个 Page 作为起始页,而这里就是 'pages/Index'

五、总结

正所谓台上一分钟台下十年功,看起来很简单的应用起始页,实现起来往往需要对多种动态刷新和操作交互进行处理,更需要保证页面间的数据流透传方向不出错、以及应用全局范围的信号起作用等。

相关文章:

从零开始开发纯血鸿蒙应用之实现起始页

从零开始开发纯血鸿蒙应用 一、前言二、主要页面三、应用起始页四、MainPageContent 实现1、一级结构2、二级结构2.1、EmptyContent2.2、FileListContent2.2.1、ViewAction:2.2.2、EditAction2.2.3、DeleteAction2.2.4、ShareAction 五、载入起始页的时机五、总结 一…...

CG顶会论文阅读|《科技论文写作》硕士课程报告

文章目录 一、基本信息1.1 论文基本信息1.2 课程基本信息1.3 博文基本信息 二、论文评述(中英双语)2.1 研究问题(Research Problem)2.2 创新点(Innovation/Contribution)2.3 优点(Why this pape…...

【Python运维】使用Python与Docker进行高效的容器化应用管理

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着容器化技术的广泛应用,Docker已成为现代软件开发与运维中不可或缺的工具。Docker容器提供了一种轻量级、可移植的方式来部署和管理应用…...

【人工智能】基于Python与OpenCV构建简单车道检测算法:自动驾驶技术的入门与实践

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着自动驾驶技术的快速发展,车道检测作为自动驾驶系统中的一个重要组成部分,起着至关重要的作用。本文将介绍如何利用Python与OpenCV库构…...

实时数仓: Hudi 表管理、Flink 性能调优或治理工具脚本

1. Hudi 表管理 1.1 Hudi 表基础管理 创建 Hudi 表 在 HDFS 上创建一个 Hudi 表(以 Merge-on-Read 为例): CREATE TABLE real_time_dw.dwd_order_fact (order_id STRING,user_id STRING,product_id STRING,amount DOUBLE,order_date STRIN…...

Kotlin 数据类与密封类

Kotlin 数据类与密封类 引言 在 Kotlin 中,数据类和密封类是两种非常重要的类类型,它们各自具有独特的用途和优势。数据类主要用于存储数据,而密封类则用于表示受限的类层次结构。在本篇文章中,我们将深入探讨 Kotlin 中的数据类…...

大模型推理加速调研(框架、方法)

大模型推理加速调研(框架、方法) 大模型推理框架调研总结推理框架TensorRT-LLMllama.cppmnn-llmfastllmmlc-llm 环境搭建&部署推理环境llama.cppfastllmmnn-llmvllm vllm_openai_completions.pylmdeployTensorRT-LLM 大模型加速技术总结模型压缩量化…...

C语言进阶(3)--字符函数和字符串函数

本章重点 重点介绍处理字符和字符串的库函数的使用和注意事项 目录 0.前言 1.函数介绍 1.1 strlen - 计算字符串长度 1.2 strcpy - 复制字符串 1.3 strcat - 追加字符串 1.4 strcmp - 字符串比较 1.5 strncpy - 受限制复制 1.6 strncat - 受限制追加 1.7 strncmp - 受限制比…...

微服务拆分的艺术:构建高效、灵活的系统架构

目录 一、微服务拆分的重要性 二、微服务拆分的策略 1. 按照业务领域拆分 2. 按照团队结构拆分 3. 按照业务边界拆分 4. 按照数据和数据库拆分 5. 按照用户界面或外部接口拆分 6. 按照功能模块或领域驱动设计拆分 7. 按照性能和可伸缩性需求拆分 三、微服务拆分的实践…...

记录一次电脑被入侵用来挖矿的过程(Trojan、Miner、Hack、turminoob)

文章目录 0、总结1、背景2、端倪3、有个微软的系统更新,就想着更新看看(能否冲掉问题)4、更新没成功,自动重启电脑5、风险文件(好家伙命名还挺规范,一看名字就知道出问题了)6、开机有一些注册表…...

计算机xinput1_4.dll丢失怎么修复?

电脑运行时常见问题及修复指南 作为软件开发从业者,深知电脑在日常使用中难免会遇到各种问题,如文件丢失、文件损坏和系统报错等。这些问题不仅影响工作效率,还可能带来数据丢失的风险。本文将详细介绍一些常见问题及其解决办法,…...

高等数学学习笔记 ☞ 连续函数的运算与性质

1. 连续函数的运算 1. 连续函数的四则运算: (1)若函数在点处连续,则函数在点处也连续。 (2)若函数在区间上连续,则函数在区间上也连续。 2. 反函数的连续性: 若函数在定义域上是单…...

k8s基础(4)—Kubernetes-Service

Service概述 抽象层 ‌k8s的Service是一种抽象层,用于为一组具有相同功能的Pod提供一个统一的入口地址,并通过负载均衡将网络流量分发到这些Pod上。‌ Service解决了Pod动态变化的问题,例如Pod的IP地址和端口可能会发生变化,通过…...

CAN或者CANFD的Busoff的恢复时间会受到报文周期的影响么?

目录 分析恢复机制角度快恢复和慢恢复策略角度特殊情况分析分析 Busoff的恢复时间通常不会直接受到报文周期的影响,以下是具体分析: 恢复机制角度 CAN总线的节点在Busoff状态下,恢复过程主要是等待总线上出现128个连续的11bit隐性位,与报文周期并无直接关联。无论报文周…...

【DevOps】Jenkins部署

Jenkins部署 文章目录 Jenkins部署资源列表基础环境一、部署Gilab1.1、安装Gitlab1.2、修改配置文件1.3、加载配置文件1.4、访问Gitlab1.5、修改root登录密码1.6、创建demo测试项目1.7、上传代码1.8、验证上传的代码 二、部署Jenkins所需软件2.1、部署JDK2.2、部署Tomcat2.3、部…...

【MATLAB第112期】基于MATLAB的SHAP可解释神经网络回归模型(敏感性分析方法)

【MATLAB第112期】基于MATLAB的SHAP可解释神经网络回归模型(敏感性分析方法) 引言 该文章实现了一个可解释的神经网络回归模型,使用BP神经网络(BPNN)来预测特征输出。该模型利用七个变量参数作为输入特征进行训练。为…...

【Shell编程 / 4】函数定义、脚本执行与输入输出操作

文章目录 函数 与 脚本定义函数示例:简单的 Shell 函数函数参数返回值 脚本执行创建脚本执行脚本 输入输出输出:echo 和 printf输入:read 命令 命令行参数示例:传递参数 函数 与 脚本 在 Shell 编程中,函数和脚本是组…...

RK3588+麒麟国产系统+FPGA+AI在电力和轨道交通视觉与采集系统的应用

工业视觉识别系统厂家提供的功能主要包括: 这些厂家通过先进的视觉识别技术,实现图像的采集、处理与分析。系统能够自动化地完成质量检测、物料分拣、设备监控等任务,显著提升生产效率和产品质量。同时,系统具备高度的灵活性和可扩…...

MySQL 01 02 章——数据库概述与MySQL安装篇

一、数据库概述 (1)为什么要使用数据库 数据库可以实现持久化,什么是持久化:数据持久化意味着将内存中的数据保存到硬盘上加以“固化”持久化的主要作用是:将内存中的数据存储在关系型数据库中,当然也可以…...

运行framework7

安装 framework7 下载地址https://gitcode.com/gh_mirrors/fr/framework7-vue node 下载 https://nodejs.cn/#ionic 配置npm 的镜像源 npm config set registry https://registry.npmmirror.com 下载nvm 进行nvm管理https://www.downza.cn/soft/352547.html 我一开始使用node…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线, n r n_r nr​ 根接收天线的 MIMO 系…...

什么是VR全景技术

VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...

【Linux】Linux安装并配置RabbitMQ

目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...

深入解析 ReentrantLock:原理、公平锁与非公平锁的较量

ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...

宠物车载安全座椅市场报告:解读行业趋势与投资前景

一、什么是宠物车载安全座椅? 宠物车载安全座椅是一种专为宠物设计的车内固定装置,旨在保障宠物在乘车过程中的安全性与舒适性。它通常由高强度材料制成,具备良好的缓冲性能,并可通过安全带或ISOFIX接口固定于车内。 近年来&…...

OpenHarmony标准系统-HDF框架之I2C驱动开发

文章目录 引言I2C基础知识概念和特性协议,四种信号组合 I2C调试手段硬件软件 HDF框架下的I2C设备驱动案例描述驱动Dispatch驱动读写 总结 引言 I2C基础知识 概念和特性 集成电路总线,由串网12C(1C、12C、Inter-Integrated Circuit BUS)行数据线SDA和串…...