基于HarmonyOS Next鸿蒙开发保姆级基础入门到开发实战教程——以构建“不晚”元服务为例

本文正在参加华为鸿蒙有奖征文征文活动

百川奔腾入海,千帆共进有为,鸿蒙与你共未来!鸿蒙生态千帆起 HarmonyOS NEXT!

全新 HarmonyOSNEXT 开发者预览版将在今年第一季度面向所有开发者开放。华为宣布将于 2024 年 1 月 18 日举行"鸿蒙生态千帆启航仪式",揭秘鸿蒙生态和 HarmonyOS NEXT 进阶新篇章。

项目背景

2024年1月18日,HarmonyOS NEXT 正式发布。全新 HarmonyOS NEXT 开发者预览版在今年第一季度面向所有开发者开放。鸿蒙生态和 HarmonyOS NEXT 已然进阶新篇章。

随着国家越来越重视教育,我通过对一系列鸿蒙开发课程的学习,决定开发一款基于HarmonyOS Next 的学习平台元服务。

随着移动互联网的快速发展,学习平台已成为人们获取知识、提升技能的重要途径。然而,当前市场上的学习平台普遍存在内容繁杂、用户学习体验不佳、互动性差等问题。为了解决这些问题,我们决定开发一个基于HarmonyOS Next的学习平台,旨在为用户提供更优质、高效的学习体验。

在这个项目中,我们将基于HarmonyOS Next 版本,构建一个学习平台元服务。

实战开发前必备:

默认大家的开发环境已经配好

DevEco Studio 4.0

Navicat Premium 16

IntelliJ IDEA 2022.3.2

MySQL 8.0

Redis

支持对应鸿蒙版本的HarmonyOS 真机 或者 OpenHarmony开发板

采用技术:ArkTS、SpringCould、MySQL、Redis、内网穿透工具或者云服务器等等开发相关。

一.HarmonyOS Next快速入门指南

1.1DevEco Studio 指南

随着1月18日版本发布,HarmonyOS NEXT越来越引人关注。其开发开发工具(IDE)---DevEco Studio 4.0本次也是做出了很多重大更新。

面向全场景多设备,提供一站式的分布式应用开发平台,支持分布式多端开发、分布式多端调测、多端模拟仿真,全方位的质量与安全保障。

HUAWEI DevEco Studio是基于IntelliJ IDEA Community开源版本打造,面向华为终端全场景多设备的一站式集成开发环境(IDE),为开发者提供工程模板创建、开发、编译、调试、发布等E2E的HarmonyOS应用/服务开发。

本次我们来深入讲解新版本-DevEco Studio 4.0并使用一个开发案例来详细学习。

版本:DevEco Studio 4.0 Release

1.1.1 特点介绍

DevEco Studio 4.0是一个集成开发环境(IDE),专门为开发者提供一站式的HarmonyOS应用和服务开发支持。

以下是DevEco Studio 4.0的一些主要特点:

  • 高效智能代码编辑:支持多种语言,如ArkTS、JavaScript、C/C++等,提供代码高亮、智能补齐、错误检查、自动跳转、格式化、查找等功能,以提升代码编写的效率。
  • 低代码可视化开发:拥有丰富的UI界面编辑能力,支持自由拖拽组件和可视化数据绑定,能够快速预览效果,所见即所得。同时支持卡片的零代码开发,降低开发门槛和提升界面开发效率。
  • 多端双向实时预览:支持UI界面代码的双向预览、实时预览、动态预览、组件预览以及多端设备预览,便于快速查看代码运行效果。
  • 全新构建体系:通过Hvigor编译构建工具,可以一键完成应用及服务的编译和打包,更好地支持ArkTS/JS开发。
  • 一站式信息获取:基于开发者了解、学习、开发、求助的用户旅程,在DevEco Studio中提供一站式的信息获取平台,高效支撑开发者活动。
  • 高效代码调试:提供TS、JS 、C/C++代码的断点设置,单步执行、变量查看等调试能力,提升应用及服务的问题分析效率。

1.1.2 应用开发流程

使用DevEco Studio 4.0开发鸿蒙应用过程十分简单明了,见下图。

完成开发准备进入开发应用编写代码,运行调试没问题后申请完证书就可以直接发布大到华为应用市场。

1.1.3 DevEco Studio 4.0入门与配置

环境配置流程如下所示:

1.1.3.1 DevEco Studio 4.0安装

原生鸿蒙 HarmonyOS NEXT 在1 月 18 日 启航,我们必须体验一下新版本的DevEco Studio,作者将带领大家从0到1保姆级教程的体验。

这里以作者的Windows环境为例,macOS安装过程基本相同。

Windows环境

运行环境要求

为保证DevEco Studio正常运行,建议电脑配置满足如下要求:

  • 操作系统:Windows10 64位、Windows11 64位
  • 内存:8GB及以上
  • 硬盘:100GB及以上
  • 分辨率:1280*800像素及以上
  1. 由于作者是提前拿到的新版本,所以下载方式会有不一样,待官方公布4.0 版本后,我们可以直接到官方下载:

2.打开下载完的安装包,我们进行安装,如版本有细小差异属版本迭代的正常现象,操作流程一样,不影响体验效果。

3.安装过程非常简单过程如下图,记得勾选DevEco Studio,如果需要添加到电脑环境变量可以勾选Add "bin" folder to the PATH。

4.然后就可以运行。

1.1.3.2 DevEco Studio 4.0开发环境配置

1.我们可以选择不导入设置。

2.然后我们就可以开始配置环境了。我下面这个图的错误非常的经典。

爆红:Select an empty directory to install Node.js 或者 ohpm

原因:之前本地环境下载安装过DevEco Studio,卸载的时候并没有卸载Node.js或者ohpm,我们这里可以直接选择本地的Node.js或者ohpm,当然也可以把本地的Node.js或者ohpm删除,然后重新下载一个。(如果是第一次下载可以直接选择下载)

解决方案:选择本地Node.js或者ohpm删除,重新下载即可。

3.选择一个空目录,用来存放HarmonyOS SDK,单击Next进入下一步。

4.环境诊断

DevEco Studio提供了开发环境诊断的功能。DevEco Studio开发环境诊断项包括电脑的配置、网络的连通情况、依赖的工具或SDK是否安装等。如果检测结果为未通过,请根据检查项的描述和修复建议进行处理。

5.SDK手动配置点击Unzip,如下图。

Source path 填写sdk压缩包存放的目录,Destination path 填写SDK配置目录。填写完路径后点击Unzip,开始解压。(这里需要较为漫长的等待,5min左右~)

5.开发环境配置到这里就完成了,下面我们进行一个简单的DEmo实现。

1.1.4创建项目

HarmonyOS是一款面向万物互联时代的、全新的分布式操作系统。运行在HarmonyOS的应用分为两种形态:

  • 传统方式的需要安装的应用(即传统概念中的HarmonyOS应用,可简称应用)。
  • 提供特定功能、免安装的应用(即元服务,原名为原子化服务)。

1.我们点击创建项目,这里可以创建Application应用或Atomic Service元服务,以Application应用为例。选择一个空模板。

2.SDK。应用模型选择Stage模型。Stage模型概念图如下:

我们鸿蒙应用开发有俩种模型:Stage模型和FA模型

鸿蒙系统的Stage模型和FA模型在应用开发中有一些不同点:

  • 设计出发点:Stage模型是为了解决FA模型无法解决的开发场景问题,方便开发者更加方便地开发出分布式环境下的复杂应用。
  • 应用能力与系统功耗的平衡:Stage模型通过Ability与UI分离、严格的后台管控、基于场景的服务机制及单进程模型来达成应用能力与整体系统功耗的平衡。而FA模型在这方面的考虑可能较少。
  • 多设备和多窗口形态的支持:Stage模型支持多设备和多窗口形态的特点,这是FA模型所不具备的。
  • 应用组件共享:在Stage模型中,多个应用组件共享同一个ArkTS引擎实例,应用组件之间可以方便的共享对象和状态,同时减少复杂应用运行对内存的占用。而在FA模型中,每个应用组件独享一个ArkTS引擎实例。
  • 进程内共享对象:Stage模型支持进程内共享对象,这意味着开发者不需要考虑线程之间的对象共享,只需要聚焦在分布式的交互场景上。而FA模型在这方面可能有限制。
  • 应用运行规则:Stage模型重新定义了应用运行规则,从根本上解决了后台抢占系统资源的问题,例如减少后台常驻进程数量和内存开销,使后台进程行为更加有序,充分保障前台进程所需资源。而FA模型在这方面可能没有Stage模型那么精细。

1.1.4.1配置插件

1.这是一个非常经典的报错,我们可以学习一下:

报错信息: ERR_PNPM_FETCH_404  GET repo.harmonyos.com/npm/@ohos/h...: Not Found - 404

报错原因:判断应该是版本暂未开发,目前插件需要自己手动配置。如果后续发布版本,这步可以忽略。

解决方案:手动配置插件。

2.下载的安装包里有dependencies,我们需要将其放到我们的工程目录下。

3.打开hvigor目录下的hvigor-config.json5文件,修改hvigorVersion和dependencies字段内的信息。

perl 复制代码
{ 
​
 "hvigorVersion": "file:../dependencies/hvigor-3.0.10-s.tgz", 
​
 "dependencies": { 
​
  "@ohos/hvigor-ohos-plugin": "file:../dependencies/hvigor-ohos-plugin-3.0.10-s.tgz", 
​
  "rollup": "file:../dependencies/rollup.tgz", 
​
 } 
​
}

配置完成后,我们点击再次尝试即可。

成功截图如下:

我们可以看到,可以正常输出helloword了,到这里我们就完成了项目的配置与运行项目。

后面我们就可以愉快的编写我们的项目了!

1.1.5 智能编辑

DevEco Studio的智能编辑优点就太多了,像:智能代码高亮、代码智能补全、代码错误检查、代码自动跳转、代码格式化、代码查找、提升代码编写效率等等

智能代码高亮---我们可以在下图明显看到

编辑器能够根据代码的语法和结构,以不同的颜色和样式突出显示代码的不同部分。这样可以帮助开发者更清晰地阅读和理解代码,快速地识别代码中的关键字、变量、函数等元素。同时,智能代码高亮还可以提高代码的可读性和可维护性,使得代码更易于理解和修改。

在DevEco Studio中,智能代码高亮可以根据不同的编程语言和主题进行定制,以满足不同开发者的需求。开发者可以根据自己的喜好选择不同的颜色和样式,或者使用编辑器提供的默认设置。

代码智能补全、代码错误检查、代码自动跳转、代码格式化、代码查找等等功能大家可以去到官方查看详细的介绍,这里就不多赘述了。快捷键给到大家

快捷键如下:

快捷键 Windows Mac
代码高亮 File > Settings或快捷键Ctrl+Alt+S DevEco Studio > Preferences,快捷键为Command+英文逗号
代码自动跳转 按住Ctrl键 按住Ctrl键
代码格式化 Ctrl + Alt + L,可以快速对选定范围的代码进行格式化。Ctrl + Alt + Shift + L,可以快速对当前整个文件进行格式化 Command+Option +L,可以快速对选定范围的代码进行格式化。Command+Option+L,可以快速对当前整个文件进行格式化
代码折叠 Ctrl + 加号键 Command+Option+加号键
代码快速注释 Ctrl+/ Command+/
代码结构树 Alt + 7 / Ctrl + F12 Command+7
代码查找 两次Shift 两次Shift
查看Java接口文档 Ctrl+Q F1

1.2简单案例-鸿蒙版计算器实现

1.2.1 环境

DevEco Studio 4.0

API版本:10

1.2.2项目背景

随着科技的快速发展,人们对移动设备的需求日益增长,尤其是对高效、便捷的移动应用的需求。在这个背景下,鸿蒙系统作为一个新兴的移动操作系统,凭借其独特的分布式技术、强大的性能和安全保障,吸引了大量的开发者与用户。

鸿蒙版计算器(ArkTS)API 10实现,正是在这样的背景下诞生的。首先,随着鸿蒙系统的普及,越来越多的开发者开始关注鸿蒙生态,并希望为鸿蒙用户提供更多优质的应用。计算器作为手机的基本工具之一,其功能性和用户体验对用户来说至关重要。因此,开发一个符合鸿蒙系统特性的计算器应用成为了迫切的需求。

ArkTS是鸿蒙系统中的一种新型编程语言,它结合了TypeScript和JavaScript的特性,为开发者提供了更加便捷的开发体验。通过使用ArkTS,开发者可以更加高效地开发出性能优越、功能丰富的应用。而API 10作为ArkTS中的一个重要版本,提供了更多强大的功能和性能优化,使得开发者能够更好地利用ArkTS开发出优秀的鸿蒙应用。

鸿蒙版计算器(ArkTS)API 10实现的项目背景是:在鸿蒙系统日益普及的背景下,为了满足鸿蒙用户对优质计算器应用的需求,以及利用ArkTS和API 10的优势,提高开发效率和应用的性能与功能,而进行的一次技术探索与实践。

1.2.3实现过程

基于基础组件、容器组件,实现一个支持加减乘除混合运算的计算器。效果如图所示:

栅格容器

在GridRow栅格组件中,允许开发者使用breakpoints自定义修改断点的取值范围,最多支持6个断点,除了默认的四个断点外,还可以启用xl,xxl两个断点,支持六种不同尺寸(xs, sm, md, lg, xl, xxl)设备的布局设置。

计算器页面功能构建思路-核心结构:

typescript 复制代码
  // 数字按钮点击事件处理
  numClick(num:string){
    // ... 一些逻辑
  }
​
  // 等号按钮点击事件处理
  equalClick(){
    // ... 一些逻辑
  }
​
  // 运算符按钮点击事件处理
  calClick(cType:String){
    // ... 一些逻辑
  }
​
  // 清除按钮点击事件处理
  clearClick(){
    // ... 一些逻辑
  }
​
  // 删除按钮点击事件处理
  deleClick(){
    // ... 一些逻辑
  }
​
  // 拼接数字数组
  montageNumArr(){
    // ... 一些逻辑
  }
​
  // 构建UI
  build() {
    // ... 一些UI布局代码
  }
}
​
// 子组件,表示每个计算器按钮
@Component
struct ClItem {
  // ... 一些属性
  build(){
    // ... 一些UI布局代码
  }
}

让我们逐步解析代码:

  1. 结构体 Index:
  • 代表计算器的主要结构。

  • 使用了 @Entry@Component 注解。

  • 定义了几个状态 (@State):

  • message: 一个字符串,初始化为 'Hello World'。

  • Number: 一个包含数字按钮的字符串数组。

  • Number2: 另一个包含数字按钮的字符串数组。

  • isEnd: 一个布尔值,表示计算是否完成。

  • calArr: 一个数组,用于存储中间计算结果。

  • calString: 一个字符串,用于存储计算表达式。

  • num: 一个字符串,表示当前输入的数字。

  • numArr: 一个字符串数组,用于存储当前输入的数字的各个部分。

  1. numClick 函数:
  • 处理数字按钮的点击事件。

  • 如果计算已经结束,调用 clearClick 清空状态。

  • 避免多个连续的零输入。

  • 避免重复输入小数点。

  1. equalClick 函数:
  • 处理等号按钮的点击事件。

  • 如果计算尚未结束,将当前数字追加到计算表达式中。

  • 解析并执行乘法和除法。

  • 解析并执行加法和减法。

  • 将最终结果设置为显示的数字,标记计算结束。

  1. doClick 函数:
  • 空函数,没有实际实现。
  1. calClick 函数:
  • 处理运算符按钮的点击事件。

  • 将当前数字追加到计算表达式中,并更新显示。

  1. clearClick 函数:
  • 处理清空按钮的点击事件。

  • 清空各种状态,重置计算器。

  1. deleClick 函数:
  • 处理删除按钮的点击事件。

  • 从当前数字中删除最后一个字符,更新显示。

  1. montageNumArr 函数:
  • 将数字数组拼接成一个字符串,更新显示。
  1. build 函数:
  • 使用 ArkTS 的 Flex 布局和 Text、Image、Grid 等组件构建计算器的界面。

  • 包含数字按钮和运算符按钮的网格。

  1. 结构体 ClItem:
  • 表示计算器中的每个按钮。

  • 包含内容、字体颜色、背景颜色、字体大小和边框半径等属性。

  • 使用 Text 组件构建按钮。

这段代码实现了一个基本的计算器应用,具有基本的数字输入、运算和显示功能。

1.2.4 实现效果

我们实现了一个简单的计算器应用,具有基本的数字输入、运算和显示功能。计算器的界面采用了灵活的布局,分为两个部分:

  1. 显示区域:
  • 位于计算器的顶部,用于显示当前的计算表达式和结果。

  • 显示区域包括两个文本框,一个用于显示计算表达式 (calString),另一个用于显示当前输入的数字 (num)。

  • 文本框采用不同的样式,包括字体大小、颜色和对齐方式。

  1. 按钮区域:
  • 位于计算器的底部,分为两个部分,一个包含数字按钮,另一个包含运算符按钮。

  • 数字按钮部分是一个网格,包含数字 0 到 9、小数点、百分号等按钮。每个按钮具有不同的样式和点击事件。

  • 运算符按钮部分也是一个网格,包含加法、减法、乘法、除法、等号等按钮。同样,每个按钮具有不同的样式和点击事件。

点击不同的按钮会触发相应的事件处理函数,实现不同的功能,例如添加数字、执行运算、清空显示等。整体而言,这个计算器应用提供了一个直观且用户友好的界面,使用户能够进行基本的数学运算。

1.3UX特性介绍

我们本次着重来突出一下几点:空间感的手势动效、真实感手势动效、光影设计、粒子动效设计、造型圆角。看这几个名称较难理解其中的含义,我们来解读一下:

  1. 空间感手势动效:简单说,就是让人感觉在用真实的手在操作。比如滑动屏幕时,感觉手指真的在屏幕上划过,而不是简单的上下左右移动。
  2. 真实感手势动效:就像真的在做某个动作一样。比如点击一个按钮,它不仅会动一下,还会有点击的声音和震动,让人感觉真的按下了某个东西。
  3. 光影设计:就是让界面看起来更有立体感和真实感。比如在界面上加一个光源,让某个部分看起来更亮,其他部分更暗,就像真的一样。
  4. 粒子动效设计:这可以让界面看起来更有意思。比如在下雨的天气里,屏幕上的按钮会像被雨滴打中一样跳动,非常有趣。
  5. 造型圆角:就是把界面的边角变得圆滑,不会那么锐利和刺眼。这样用起来感觉更友好和舒适。

鸿蒙开发技术在设计时考虑了很多细节,希望用户用起来不仅功能强大,而且感觉也很好,这就是UX设计理念。

1.4 元服务介绍

HarmonyOS是一款面向万物互联时代的、全新的分布式操作系统。运行在HarmonyOS的应用分为两种形态:

· 传统方式的需要安装的应用(即传统概念中的HarmonyOS应用,可简称应用)。

· 提供特定功能、免安装的应用(即元服务,原名为原子化服务)。

1.4.1元服务的特点

① 免安装,更轻量化地将服务带给用户

② 一键服务直达,将用户感兴趣的内容前置、外显

③ 跨端转移,多终端设备间无缝流转

④ 情景智能卡片推荐,随心定制、更懂用户

1.4.2 服务卡片

鸿蒙万能卡片是元服务的主要展现形式之一(其他形式包括语音和图标等)。每个万能卡片都是一种始终可见的元服务或应用,将重要信息以卡片的形式展示在桌面上,通过轻量交互实现服务的便捷访问。

二."不晚"元服务的实现

2.1项目介绍

本实战为快速开发的极简版本,项目整体开发时间只用了2天(不算服务端),已满足本文技术教学要求。 主要特点:

  • 多元登录方式: 用户可选择账号密码登录,接入华为认证服务实现更安全的登录,或者使用测试登录方式进行评估和测试。
  • 数据库支持: 题目等学习数据使用数据库进行存储,确保数据的安全性和可靠性,同时提供了卡片刷新和页面跳转等灵活的功能。
  • 排行榜和积分系统: 提供积分排行榜,用户可以查看自己在学习中的排名,激发学习竞争力。
  • 丰富的活动积分:可以查看发布活动。
  • 桌面卡片快捷操作: 用户可以将排行榜和活动详情等卡片添加到桌面,方便快捷地参与活动和查看排名。

目标用户: "不晚"旨在服务广大学习者,包括但不限于学生、开发者、技术爱好者等,为他们提供一个全面、高效、有趣的学习平台。 通过集成华为技术和提供个性化学习体验,该平台致力于帮助用户更轻松地获取知识,提高学习效率,并促进学习社群的交流与分享。 登录提供多种登录方式:

  • 账号密码登录(后端SpringCloud 服务生成Token保持登录状态,下文详细说明)。
  • 接入华为认证服务---AGC认证服务,以实现用户登录,展示个人账户信息
  • 测试登录:账号admin 密码admin (供测试用户进入应用,因后端部署较为复杂预留此入口

参与活动以及积分排行等功能。 实现用户成绩和排名,增加用户对学习活动的兴趣。 使用云数据库存储题目,实现卡片的刷新和页面跳转等功能。 排行榜卡片和活动卡片 可以将卡片添加到桌面,参与活动和查看排名更加方便快捷

运行条件

DevEco Studio 4.0、IntelliJ IDEA 2022.3.2

MySQL 8.0、 Redis 3.0.504、SpringCloud 2022.0.2

ArkTS语言、Stage模型

内网穿透工具(向部分功能提供数据服务)或者云服务器

运行说明

  1. 连接设备
  2. 在DevEco Studio运行Open Harmony项目源码
  3. 配置Mysql和Redis
  4. 启动后端服务SpringCloud
  5. 启动内网穿透工具
  6. 运行项目到设备

2.1 应用创建

2.1.1 元服务项目创建

项目创建在上文有这详细的教程与讲解,这里只列举一些关键的步骤。

只需按下面选择对应的项目模板进行创建。

2.1.2 SpringCloud服务与数据库

本文只要讲解鸿蒙应用开发,服务端创建与开发过程省略不写。启动服务端如下图。

Redis 3.0.504 启动 6379 端口

数据库如下:

2.2 基础页面实现

2.2.1 登录页面实现

基础页面介绍一下登录页面,登录页面包含上下logo、元服务名称、用户名输入框、密码框、登录注册按钮等,实现过程简单。

核心实现代码:

scss 复制代码
build() {
    Row() {
      Column({space:17}) {
        Image($r("app.media.logo11")).width(80)
        Text(""不晚"元服务")
          .fontSize(30)
        TextInput({ placeholder: '输入用户名' })
          .width(300)
          .height(60)
          .fontSize(20)
          .onChange((value: string) => {
            this.username = value
          })
        TextInput({ placeholder: '输入密码' })
          .width(300)
          .height(60)
          .fontSize(20)
          .type(InputType.Password)
          .onChange((value: string) => {
            this.password = value
          })
        Button('登录')
          .width(300)
          .height(60)
          .fontSize(20)
          .backgroundColor('#0F40F5')
          .onClick(() => {
            this.S_login();
          })
​
        Row() {
          Button('第三方登陆')
            .width("140vp")
            .height("80vp")
            .fontSize(20)
            .margin({
              bottom: 40,
              top: 60,
              right: 20
            })
          Button('立即注册')
            .width("140vp")
            .height("80vp")
            .fontSize(20)
            .margin({
              bottom: 40,
              top: 60,
            })
        }
        Image($r("app.media.logo")).width(80)
​
​
​
      }
      .width('100%')
    }
    .height('100%')
  }

本页面实现代码简单,下面是简单的代码解析:

  1. build() 方法:这是一个用于构建用户界面的函数或方法。
  2. Row():表示一行的布局容器。
  3. Column({space:17}):表示一列的布局容器,具有额外的空间(17)。
  4. Image($r("app.media.logo11")).width(80):插入一个图像,图像路径可能由 $r("app.media.logo11") 提供,并设置图像宽度为80。
  5. Text(""不晚"元服务").fontSize(30):插入文本,显示为"不晚"元服务,并设置字体大小为30。
  6. TextInput({ placeholder: '输入用户名' }):插入一个文本输入框,具有占位符(placeholder)'输入用户名'。
  7. .onChange((value: string) => { this.username = value }):指定当文本输入框的值变化时执行的回调函数,将输入的值赋给变量 this.username
  8. 类似地,有一个密码输入框和相应的回调函数,用于存储密码值。
  9. Button('登录'):创建一个按钮,显示文本"登录"。
  10. .onClick(() => { this.S_login(); }):指定按钮被点击时执行的回调函数,调用 this.S_login() 方法。
  11. Row():创建另一行布局容器。
  12. 类似地,创建两个按钮,一个用于第三方登录,另一个用于立即注册。设置它们的宽度、高度、字体大小和外边距。
  13. Image($r("app.media.logo")).width(80):插入另一幅图像,可能路径由 $r("app.media.logo") 提供,并设置宽度为80。
  14. .width('100%').height('100%'):设置最外层的 Row() 的宽度和高度为100%。

整体上,这段代码构建一个用户登录界面,包括用户名、密码输入框,登录按钮以及一些其他相关的UI元素。

2.2.2 元服务首页实现

首页设计如下:上面是一个轮播图,中间是可以跳转到对应页面的图片按钮。下面是功能详情,包括最下面的导航栏。

页面布局代码很简单,由于篇幅较长,只展示一些核心代码:

核心代码

scss 复制代码
Tabs({ barPosition: BarPosition.End, controller: this.mTabController }) {
  TabContent() {
    // ... 选项卡1的内容
  }
  .tabBar(this.TabBuilder(0));
  // TabContent2 和 TabContent3 同样方式创建
}

链接云端数据库关键代码

javascript 复制代码
import formInfo from '@ohos.app.form.formInfo';
import formBindingData from '@ohos.app.form.formBindingData';
import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility';
import formProvider from '@ohos.app.form.formProvider';
import agconnect from '@hw-agconnect/api-ohos';
import { AGConnectCloudDB, CloudDBZone, CloudDBZoneConfig, CloudDBZoneQuery } from '@hw-agconnect/database-ohos';

底部导航栏核心实现代码:

less 复制代码
 @State bartext: string[] = ['首页','活动类表','个人中心']
  @State barlogo: string[] = ['bar01','bar02','bar03']
  // Image('images/'+String(activity.type)+".png")
​
  @Builder TabBuilder(index: number) {
    Column() {
      // Image(index == this.mCurrentPage ?  $r('app.media.bar2'): $r('app.media.bar1'))
      Image('images/'+String(this.barlogo[index])+".png")
        .width('24vp')
        .height('24vp')
        .objectFit(ImageFit.Contain)
      Text(this.bartext[index])
        .fontSize('10fp')
        .fontWeight(500)
        .margin({ top: '4vp' });
    }.justifyContent(FlexAlign.Center);

带参跳转页面:

php 复制代码
              .onClick(() => {
                router.replaceUrl({
                  url: "page/MainPage",
                  params: {
                    name: this.paramsFromIndex?.['name']
                  }
                })
              })

首页是一个包含多个选项卡的页面,详细功能内容如下:

  • 导入所需的模块和组件,包括路由 (router)、提示操作 (promptAction)、Web视图 (web_webview) 和网络请求 (http)。
  • 在 Index 组件中,定义了一些状态 (@State),包括从路由获取的参数 (paramsFromIndex)、播放器数据 (playerData)、当前页数 (mCurrentPage),以及一些其他控制器和资源。
  • 在 build 方法中,创建了一个包含多个选项卡的页面,每个选项卡代表不同的内容。
  • 页面的第一个选项卡包含了一些图片、文字和按钮,以及一个用于观看视频的 Video 组件。还有一个按钮,当点击时会触发 HTTP 请求,获取排行榜数据,并在获取数据后跳转到另一个页面显示排行榜。
  • 页面的第二个选项卡包含了一个视频播放器,用户可以点击按钮来开始播放视频或切换到下一个视频。
  • 页面的第三个选项卡包含了一些个人信息和操作,包括退出登录、题目上传、通知和排行榜。用户可以点击这些操作来执行相应的功能。
  • 使用 Tabs 组件创建了包含选项卡的布局,并在每个选项卡中定义了不同的内容。

2.3 排行榜页面实现

排行榜页面效果图如下,可能有的小伙伴比较奇怪为什么写着OpenHarmony,这个功能页面是我之前项目里的一个页面,我发现和这个案例比较契合,可以直接移植过来。这又侧面体现了我们鸿蒙系统的强大。我们移植过来的页面功能样式是基本相同的。

排行榜页面在应用中起着至关重要的作用,它可以展示用户之间的比赛成绩、竞争和表现。无论是游戏、学习应用还是社交媒体平台,排行榜页面都具有广泛的应用。

核心代码:

typescript 复制代码
import router from '@ohos.router';
@Entry
@Component
struct LeaderboardPage {
  // 玩家数据数组,每个元素包含玩家姓名和分数
​
  @State paramsFromIndex: object = router.getParams()
  @State playerData: string[][] = this.paramsFromIndex?.['playerData']
​
  build() {
​
    Column() {
      Row() {
        Button("<")
          .width("68.78vp")
          .height("46.26vp")
          // .margin({ left: -60 })
          .fontColor("#fffff")
          .type(ButtonType.Circle)
          .fontSize("27fp")
          .onClick(() => {
            router.replaceUrl({
              url: "page/homepage",
              params: {
                name: this.paramsFromIndex?.['name']
              }
            })
          });
​
        Text("排行榜")
          .width("80%")
          .height("60vp")
          .fontColor("#0654ef")
          .textAlign(TextAlign.Center)
          .fontSize("30fp");
      }
​
      Column() {
        Image($r('app.media.pai'))
          .width("350.42vp")
          .height("189.02vp")
          .margin({
            top:10,
            bottom:20
          })
      }
      Row() {
​
        Text("   姓名")
          .width("45%")
          .fontSize("20fp")
          .fontColor(Color.Blue); // 可以调整表头的样式
​
        Text("成绩")
          .width("35%")
          .fontSize("20fp")
          .fontColor(Color.Blue);
​
        Text("操作")
          .width("35%")
          .fontSize("20fp")
          .fontColor(Color.Blue);
      }
      // .width("50%")
      // 遍历玩家数据数组,创建玩家条目
      ForEach(this.playerData, (player, index) => {
        Row() {
          Text(`${index + 1}.`)
            .width("10%")
            .fontSize("18fp");
​
          Text(player[0]) // 玩家姓名
            .width("30%")
            .fontSize("18fp");
​
          Text(`得分: ${player[1]}`) // 玩家得分
            .width("40%")
            .fontSize("18fp");
​
          Text("查看")
            .width("20%")
            .fontColor(Color.Red)
            .fontSize("18fp")
            .onClick(() => {
              // this.onCreate();
              // this.onCreate()
              // 在此处理查看详情的逻辑
              AlertDialog.show({
                title: "查看",
                message: `姓名: ${player[0]}\n得分: ${player[1]}`,
              });
              // console.error('JSON解析错误:', this.playerData2);
            });
​
        }
        .width("95%")
        .margin({ top: '10vp' })
        .margin(10)
      });
    }
    .width('100%')
  }
}

代码总结: 1.创建 LeaderboardPage 组件,用于显示排行榜数据 2.定义了一个页面组件,用于显示排行榜数据,并提供了返回按钮和查看按钮等交互功能。排行榜数据来自路由参数,并以表格的形式呈现在页面上。用户可以点击查看按钮来查看玩家的详细信息。

2.4 个人中心页面实现

个人中心我设计了俩版,设计比较简约,只保留了刚需的功能入口。第一版如下:

第二版如下:

核心代码:

php 复制代码
   Column() {
          Column() {
            Stack() {
              Image($r('app.media.logo11'))
                .width("121.1vp")
                .height("109.21vp")
                .offset({ x: "-0.33vp", y: "-20.98vp" })
                .borderRadius(100)
              Text("目前积分\n300")
                .width("117.86vp")
                .height("70.81vp")
                .offset({ x: "-83.43vp", y: "85.87vp" })
                .fontSize("16fp")
                .textAlign(TextAlign.Center)
              Text("当前登录账号\n"+this.paramsFromIndex?.['name'])
                .width("117.86vp")
                .height("70.81vp")
                .offset({ x: "89.98vp", y: "83.11vp" })
                .fontSize("16fp")
                .textAlign(TextAlign.Center)
            }
            .width("99.7%")
            .height("275.66vp")
            .offset({ x: "0.46vp", y: "-292.54vp" })
            // .backgroundColor("#8adff5")
            Stack() {
              Stack() {
                Image($r('app.media.tuichu'))
                  .width("62.73vp")
                  .height("51.92vp")
                  .offset({ x: "-131.91vp", y: "0vp" })
                  .objectFit(ImageFit.ScaleDown)
                Text("退出登录")
                  .width("262.68vp")
                  .height("43.79vp")
                  .offset({ x: "34.29vp", y: "-0.17vp" })
                  .fontSize("17fp")
              }
              .onClick(() => {
                router.replaceUrl({
                  url: "pages/Index"
                  // this.paramsFromIndex?.['name']
                })
              })
              .width("99.1%")
              .height("62.73vp")
              .offset({ x: "-1.67vp", y: "46.05vp" })
              Stack() {
                Image($r('app.media.shangchuan'))
                  .width("62.73vp")
                  .height("51.92vp")
                  .offset({ x: "-131.91vp", y: "0vp" })
                Text("题目上传")
                  .width("262.68vp")
                  .height("43.79vp")
                  .offset({ x: "34.29vp", y: "-0.17vp" })
                  .fontSize("17fp")
              }
              .width("99.1%")
              .height("62.73vp")
              .offset({ x: "1.33vp", y: "-36.77vp" })
              Stack() {
                Image($r('app.media.tongzhi'))
                  .width("62.73vp")
                  .height("51.92vp")
                  .offset({ x: "-131.91vp", y: "0vp" })
                  .objectFit(ImageFit.ScaleDown)
                Text("通知")
                  .width("262.68vp")
                  .height("43.79vp")
                  .offset({ x: "34.29vp", y: "-0.17vp" })
                  .fontSize("17fp")
              }
              .width("99.1%")
              .height("62.73vp")
              .offset({ x: "-1.67vp", y: "-115.67vp" })
              Stack() {
                Image($r('app.media.paihangbang'))
                  .width("62.73vp")
                  .height("51.92vp")
                  .offset({ x: "-131.91vp", y: "0vp" })
                  .objectFit(ImageFit.ScaleDown)
                  .interpolation(ImageInterpolation.None)
                Text("排行榜")
                  .width("262.68vp")
                  .height("43.79vp")
                  .offset({ x: "34.29vp", y: "-0.17vp" })
                  .fontSize("17fp")
              }
              .width("99.1%")
              .height("62.73vp")
              .offset({ x: "-1.67vp", y: "-192.39vp" })
​
            }
            .width("99.4%")
            .height("465.88vp")
            .offset({ x: "0.92vp", y: "-286.87vp" })
          }
          .width("100%")
          .height("100%")
          .offset({ x: "0vp", y: "311.31vp" })
          .justifyContent(FlexAlign.Center)
        }
        .width("100%")
        .height("100%")

简要解析:

  1. 顶层 Column 组件
  • 占据整个屏幕的宽度和高度。

  • 内容包含一个嵌套的 Column 组件。

  1. 第二层 Column 组件
  • 占据整个屏幕的宽度和高度。

  • 内容包含一个嵌套的 Stack 组件。

  1. Stack 组件
  • 包含多个元素的叠加。

  • 包括一个带有圆形边框的图片和两个文本元素。

  • 另外,还有一个嵌套的 Stack 组件,其中包含了四个按钮,每个按钮包括一个图片和一个文本元素。

  • 每个按钮都有点击事件,并且具有特定的样式和布局参数。

2.5服务卡片的实现

2.5.1 卡片的介绍

元服务是一种基于HarmonyOS的特有服务提供方式,无需用户安装,具备即用即走的优势。元服务的核心优势包括交互便捷、状态实时刷新、合时宜的主动推荐、主动服务等。 元服务的主要呈现形态是万能卡片,可以在桌面上"永远打开",让信息外显、动态刷新、一键服务直达等特性。用户可以通过负一屏、应用市场、小艺建议等丰富的系统级入口便捷获取服务,系统也会基于场景主动推荐服务,实现服务"找"人。 元服务的卡片具备以下特性:

  • 可自定义:用户可以自定义元服务万能卡片的组合,在桌面即可一眼获取多项服务信息,做到桌面实时提示,重要信息外显。
  • 信息全面:元服务卡片可以提供全面的信息,如新闻资讯、便捷生活、旅游出行等领域的最新内容和服务推荐。
  • 高效便捷:元服务无需下载安装APP,可以带来跨设备运行、提供即点即用、即用即走的卡片化体验,还能做到信息外显、状态实时刷新。
  • 智能推荐:元服务的另一大特色是基于用户意图,针对用户想要达成的目标精准地推荐服务。

此外,在AI的加持下,元服务能够根据时间、地点、事件等信息,并学习用户习惯,合时宜地为用户提供可能需要的服务。 元服务卡片是一种高效、智能、便捷的服务获取方式,能够满足用户多元化的需求,提升用户的使用体验。

2.5.2 卡片的实现过程

学习活动卡片实现较为简单,由于博主我现在还没有拿到适配新版本的设备,无法运行到真机,导致无法执行卡片功能,现在我们只能一起看一下样式:

核心代码:

ini 复制代码
 onNextQuestion() {
    const nextIndex = this.currentQuestionIndex + 1;
    if (nextIndex < this.title.length) {
      this.currentQuestionIndex = nextIndex;
      this.showExplanation = false; // 清空显示解析状态
      this.ende=false;
    } else {
      this.ende=true;
    }
  }
less 复制代码
//题目
  @State title: string[] = ['ArkTS学习活动','鸿蒙千帆起'];
  //地点
  @State where: string[] = ['北京大学'
    , '深圳科技园'];
  //时间
  @State time: string[] = ['2024.1.14 晚'
    , '2024.1.18 下午'];
  //图片
  @State img: string[][] = [['2'],['4'],['5']];
  //是否报名
  @State flag: string[] = ['0', '0','0','0','0','0'];

本页面用于管理和展示活动信息,并提供报名功能。代码结构清晰,使用了状态来管理组会的标题、地点、时间、图片和报名状态等信息。界面采用了层叠和垂直线性布局,使得界面看起来整洁。

报名按钮根据报名状态显示不同的样式,并且当所有组会都报名完成时,显示一个特殊的按钮表示已全部报名。点击事件处理函数目前为空,可以考虑添加一些具体的操作。

整体而言,这段代码为组会活动提供了一个简单而有效的界面和功能。

百川奔腾入海,千帆共进有为,鸿蒙与你共未来!鸿蒙生态千帆起 HarmonyOS NEXT!

五.总结

HarmonyOS Next和DevEco Studio 4.0入门指南介绍了最新版本的HarmonyOS开发工具,强调了其全场景多设备支持和一站式分布式应用开发平台。DevEco Studio 4.0的特点包括高效智能代码编辑、低代码可视化开发、多端双向实时预览等。

文章详细解释了DevEco Studio 4.0的安装和配置过程,以及应用开发流程和智能编辑功能。此外,还提供了一个简单的计算器应用案例和介绍了HarmonyOS的UX设计理念和元服务特点。总体而言,文章提供了对HarmonyOS Next和DevEco Studio 4.0的全面了解,为开发者提供了实用的信息和指南。

"不晚"元服务,元服务作为HarmonyOS的一个重要概念,具有独立入口、免安装的特点,为用户提供了更轻量化的服务访问方式。通过万能卡片等形态,用户可以更方便地访问重要信息和功能。这种形式使应用更具便捷性,尤其适用于未来的智能设备。

"不晚"元服务用于服务广大学习者,包括学生、开发者、技术爱好者等。主要特点包括多元登录方式,数据库支持,排行榜和积分系统,丰富的活动积分以及桌面卡片快捷操作。通过集成华为技术,该平台旨在提供全面、高效、有趣的学习体验,帮助用户轻松获取知识,提高学习效率,并促进学习社群的交流与分享。项目运行条件包括使用DevEco Studio、IntelliJ IDEA、MySQL、Redis、SpringCloud等工具和环境。整体而言,该项目致力于使学习更有趣和动力,提供方便的学习体验。

本次的.HarmonyOS Next ,ArkTS语言,HarmonyOS的元服务和DevEco Studio 4.0开发工具,为开发者提供了构建现代化、轻量化、高性能应用的便捷方式。这些技术和工具将帮助开发者更好地适应未来的智能设备和服务提供方式。

本文详细介绍了.HarmonyOS Next 的部分新特性与鸿蒙开发应用实战。突出了鸿蒙开发的优点,帮助广大开发者学习鸿蒙技术。

千帆起、万物生、众行远,鸿蒙生态跨越山海。 百川奔腾入海,千帆共进有为,鸿蒙与你共未来!

相关推荐
abc80021170341 小时前
前端Bug 修复手册
前端·bug
Best_Liu~1 小时前
el-table实现固定列,及解决固定列导致部分滚动条无法拖动的问题
前端·javascript·vue.js
_斯洛伐克2 小时前
下降npm版本
前端·vue.js
苏十八3 小时前
前端进阶:Vue.js
前端·javascript·vue.js·前端框架·npm·node.js·ecmascript
st紫月3 小时前
用MySQL+node+vue做一个学生信息管理系统(四):制作增加、删除、修改的组件和对应的路由
前端·vue.js·mysql
乐容4 小时前
vue3使用pinia中的actions,需要调用接口的话
前端·javascript·vue.js
似水明俊德5 小时前
ASP.NET Core Blazor 5:Blazor表单和数据
java·前端·javascript·html·asp.net
至天5 小时前
UniApp 中 Web/H5 正确使用反向代理解决跨域问题
前端·uni-app·vue3·vue2·vite·反向代理
与墨学长6 小时前
Rust破界:前端革新与Vite重构的深度透视(中)
开发语言·前端·rust·前端框架·wasm
H-J-L6 小时前
Web基础与HTTP协议
前端·http·php