HarmonyOS ArkUI入门—HarmonyOS ArkUI来开发一个健康饮食应用

news2025/1/13 15:55:30

本文演示如果在DevEco Studio 3里面,用HarmonyOS的ArkUI来开发一个健康饮食应用。体验HarmonyOS 3最新API 9!

获取HarmonyOS应用

HarmonyOS的ArkUI来开发一个健康饮食的ArkUI程序“ArkUIHealthyDiet”,基础代码已经有了[1],个人只需要在基础代码上稍作修改,就能运行了。

通过DevEco Studio 3导入应用

有关DevEco Studio 3的安装配置,可以参考前文《玩转HarmonyOS 3必装DevEco Studio 3,注意避弹[2]》这里就不在赘述。

首选是打开DevEco Studio 3,可以看到如下界面。

点击“Open Project”来导入我们实行装备好的ArkUI程序“ArkUIHealthyDiet”。

导入程序之后,就能在该程序基础上进行代码开发、运行。

通过DevEco Studio 3创建应用

如果想从0开始学习ArkUI,体验完整的HarmonyOS的开发过程,那么建议跟随本文一起来开启ArkUI开发之旅吧。

首选是打开DevEco Studio 3,可以看到如下界面。

在这里插入图片描述


点击“Create Project”来创建ArkUI程序“ArkUIHealthyDiet”。

选择模板

选择空模板Empty Ability,点击“Next”执行下一步。

在这里插入图片描述

配置项目

配置项目信息,重要是以下圈中部分。其他配置按照默认配置即可。点击“Finish”执行下一步。

在这里插入图片描述

运行HarmonyOS应用

打开Device Manager

在这里插入图片描述

在这里插入图片描述

登入华为账号

点击“Sign In”登入个人注册的华为账号。如果没有,则参考本文最后的链接进行注册。

在这里插入图片描述


启动远程模拟器

在这里插入图片描述

运行应用

点击下命的三角形按钮以启动应用

在这里插入图片描述


应用运行效果图如下。

在这里插入图片描述

完善应用

接下来是进入正题,开始我们的健康饮食应用的核心功能的开发了。

构建食物数据模型

要创建食物数据模型来统一存储和管理食物的数据。食物的信息包括:食物名称、卡路里、蛋白质、脂肪、碳水和维生素C等。

在这里插入图片描述


在ets目录下新建model文件夹,用于存放数据模型文件。

在这里插入图片描述


在model目录下创建DataModels.ets,用于存放数据模型。

定义食物数据的存储模型FoodInfo和枚举变量CategoryId,FoodData类包含食物id、名称(name)、分类(category)、图片(image)、热量(calories)、蛋白质(protein)、脂肪(fat)、碳水(carbohydrates)和维生素C(vitaminC)属性等等。

export enum CategoryId {
  Fruit = 0,
  Vegetable,
  Nut,
  Seafood,
  Dessert
}
export type FoodInfo = {
  id: number
  letter: string
  name: string | Resource
  image: Resource
  categoryId: CategoryId
  calories: number
  protein: number
  fat: number
  carbohydrates: number
  vitaminC: number
}

创建食物资源数据。在ets目录下创建mock文件夹,并在mock文件夹下创建MockData.ets。在MockData.ets中声明食物成分数组代码如下:

import { FoodInfo, CategoryId} from '../model/DataModels'
// 构造数据的mock数据
export let mockFoods: Array<FoodInfo> = [
  {
    id: 0,
    letter: 'Kiwi',
    name: $r('app.string.food_name_kiwi'),
    image: $r('app.media.kiwi'),
    categoryId: CategoryId.Fruit,
    calories: 61,
    protein: 0.8,
    fat: 0.6,
    carbohydrates: 14.5,
    vitaminC: 62
  },
  {
    id: 1,
    letter: 'Walnut',
    name: $r('app.string.food_name_walnut'),
    image: $r('app.media.walnut'),
    categoryId: CategoryId.Nut,
    calories: 646,
    protein: 14.9,
    fat: 58.8,
    carbohydrates: 19.1,
    vitaminC: 1.0
  },
  {
    id: 2,
    letter: 'Cucumber',
    name: $r('app.string.food_name_cucumber'),
    image: $r('app.media.cucumber'),
    categoryId: CategoryId.Vegetable,
    calories: 16,
    protein: 0.8,
    fat: 0.2,
    carbohydrates: 2.9,
    vitaminC: 9.0
  },
  {
    id: 3,
    letter: 'Blueberry',
    name: $r('app.string.food_name_blueberry'),
    image: $r('app.media.blueberry'),
    categoryId: CategoryId.Fruit,
    calories: 57,
    protein: 0.7,
    fat: 0.3,
    carbohydrates: 14.5,
    vitaminC: 9.7
  },
  {
    id: 4,
    letter: 'Crab',
    name: $r('app.string.food_name_crab'),
    image: $r('app.media.crab'),
    categoryId: CategoryId.Seafood,
    calories: 97,
    protein: 19,
    fat: 1.5,
    carbohydrates: 0,
    vitaminC: 7.6
  },
  {
    id: 5,
    letter: 'IceCream',
    name: $r('app.string.food_name_ice_cream'),
    image: $r('app.media.icecream'),
    categoryId: CategoryId.Dessert,
    calories: 150,
    protein: 3.5,
    fat: 11,
    carbohydrates: 24,
    vitaminC: 0.6
  },
  {
    id: 6,
    letter: 'Onion',
    name: $r('app.string.food_name_onion'),
    image: $r('app.media.onion'),
    categoryId: CategoryId.Vegetable,
    calories: 40,
    protein: 1.1,
    fat: 0.2,
    carbohydrates: 9,
    vitaminC: 8.0
  },
  {
    id: 7,
    letter: 'Mushroom',
    name: $r('app.string.food_name_mushroom'),
    image: $r('app.media.mushroom'),
    categoryId: CategoryId.Vegetable,
    calories: 20,
    protein: 3.1,
    fat: 0.3,
    carbohydrates: 3.3,
    vitaminC: 206
  },
  {
    id: 8,
    letter: 'Tomato',
    name: $r('app.string.food_name_tomato'),
    image: $r('app.media.tomato'),
    categoryId: CategoryId.Vegetable,
    calories: 15,
    protein: 0.9,
    fat: 0.2,
    carbohydrates: 3.3,
    vitaminC: 14.0
  },
  {
    id: 9,
    letter: 'Pitaya',
    name: $r('app.string.food_name_pitaya'),
    image: $r('app.media.pitaya'),
    categoryId: CategoryId.Fruit,
    calories: 55,
    protein: 1.1,
    fat: 0.2,
    carbohydrates: 13.3,
    vitaminC: 3.0
  },
  {
    id: 10,
    letter: 'Avocado',
    name: $r('app.string.food_name_avocado'),
    image: $r('app.media.avocado'),
    categoryId: CategoryId.Fruit,
    calories: 171,
    protein: 2.0,
    fat: 15.3,
    carbohydrates: 7.4,
    vitaminC: 8.0
  },
  {
    id: 11,
    letter: 'Strawberry',
    name: $r('app.string.food_name_strawberry'),
    image: $r('app.media.strawberry'),
    categoryId: CategoryId.Fruit,
    calories: 32,
    protein: 1.0,
    fat: 0.2,
    carbohydrates: 7.1,
    vitaminC: 47.0
  }
]

name需要考虑国际化,因此,该值是存储在string.json文件中。

在这里插入图片描述


image所引用的食物图片资源,放置在resources >base> media目录下。

在这里插入图片描述


在model目录下创建DataUtil.ets,用于加载健康饮食应用的数据。

import { FoodInfo } from './DataModels'
import { mockFoods } from '../mock/MockData'
export function getFoods(): Array<FoodInfo> {
  return mockFoods
}

已完成好健康饮食应用的数据资源准备,接下来将通过加载这些数据来创建食物列表页面。

构建食物列表List布局

使用List组件和ForEach循环渲染,构建食物列表布局。

修改pages目录下的Index.ets文件,新建FoodList组件作为页面入口组件,FoodListItem为其子组件。List组件是列表组件,适用于重复同类数据的展示,其子组件为ListItem,适用于展示列表中的单元。

import { FoodInfo } from '../model/DataModels'
import { getFoods } from '../model/DataUtil'
@Component
struct FoodListItem {
  private foodItem: FoodInfo
  build() {
    Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
      Image(this.foodItem.image)
        .objectFit(ImageFit.Contain)
        .height(40)
        .width(40)
        .margin({ right: 16 })
      Text(this.foodItem.name)
        .fontSize(14)
        .flexGrow(1)
      Text(this.foodItem.calories + ' kcal')
        .fontSize(14)
    }
    .height(64)
    .margin({ right: 24, left: 32 })
  }
}
@Entry
@Component
struct FoodList {
  private foodItems: FoodInfo[] = getFoods()
  build() {
    Column() {
      Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
        Text('Food List')
          .fontSize(20)
          .margin({ left: 20 })
      }
      .height('7%')
      .backgroundColor('#FFf1f3f5')
      List() {
        ForEach(this.foodItems, item => {
          ListItem() {
            FoodListItem({ foodItem: item })
          }
        }, item => item.id.toString())
      }
      .height('93%')
    }
  }
}

运行应用,可以看到列表的效果如下。

在这里插入图片描述

构建食物详情页面

在pages目录下,创建FoodDetail.ets文件,FoodDetail页面的食物信息都是直接声明的常量,现在要用传递来的FoodData数据来对其进行重新赋值。整体的FoodDetail.ets代码如下。

import router from '@ohos.router'
import { FoodInfo } from '../model/DataModels'
@Component
struct PageTitle {
  build() {
    Flex({ alignItems: ItemAlign.Start }) {
      Image($r('app.media.back'))
        .width(21.8)
        .height(19.6)
      Text('Food Detail')
        .fontSize(21.8)
        .margin({left: 17.4})
    }
    .height(61)
    .backgroundColor('#FFedf2f5')
    .padding({ top: 13, bottom: 15, left: 28.3 })
    .onClick(() => {
      router.back()
    })
  }
}
@Component
struct FoodImageDisplay {
  private foodItem: FoodInfo
  build() {
    Stack({ alignContent: Alignment.BottomStart }) {
      Image(this.foodItem.image)
        .objectFit(ImageFit.Contain)
      Text(this.foodItem.name)
        .fontSize(26)
        .fontWeight(500)
        .margin({ left: 26, bottom: 17.4 })
    }
    .height(357)
    .backgroundColor('#FFedf2f5')
  }
}
@Component
struct ContentTable {
  private foodItem: FoodInfo
  @Builder IngredientItem(title:string, name: string, value: string) {
    Flex() {
      Text(title)
        .fontSize(17.4)
        .fontWeight(FontWeight.Bold)
        .layoutWeight(1)
      Flex() {
        Text(name)
          .fontSize(17.4)
          .flexGrow(1)
        Text(value)
          .fontSize(17.4)
      }
      .layoutWeight(2)
    }
  }
  build() {
    Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Start }) {
      this.IngredientItem('Calories', 'Calories', this.foodItem.calories + 'kcal')
      this.IngredientItem('Nutrition', 'Protein', this.foodItem.protein + 'g')
      this.IngredientItem('', 'Fat', this.foodItem.fat + 'g')
      this.IngredientItem('', 'Carbohydrates', this.foodItem.carbohydrates + 'g')
      this.IngredientItem('', 'VitaminC', this.foodItem.vitaminC + 'mg')
    }
    .height(280)
    .padding({ top: 30, right: 30, left: 30 })
  }
}
@Entry
@Component
struct FoodDetail {
  private foodItem: FoodInfo = router.getParams()[foodInfo]
  build() {
    Column() {
      Stack( { alignContent: Alignment.TopStart }) {
        FoodImageDisplay({ foodItem: this.foodItem })
        PageTitle()
      }
      ContentTable({ foodItem: this.foodItem })
    }
    .alignItems(HorizontalAlign.Center)
  }
}

上述代码引用了路由Router API的接口,通过在页面上引入router,可以调用router的各种接口,从而实现页面路由的各种操作。调用router.getParams()[foodInfo]来获取到列表页面跳转来时携带的foodData对应的数据。

列表与详情页面的跳转

上述详情页面已经引用了路由Router API,能否接受来自路由的参数。那么相应的,列表页面也需要做相应的调整,来触发路由跳转。点击Index后跳转到FoodDetail页面。在FoodListItem内创建Navigator组件,使其子组件都具有路由功能,目标页面target为’pages/FoodDetail’。

修改Index.ets文件,

@Component
struct FoodListItem {
  private foodItem: FoodInfo
  build() {
    // 增加路由导航
    Navigator({ target: 'pages/FoodDetail' }) {
      Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
        Image(this.foodItem.image)
          .objectFit(ImageFit.Contain)
          .height(40)
          .width(40)
          .backgroundColor('#FFf1f3f5')
          .margin({ right: 16 })
        Text(this.foodItem.name)
          .fontSize(14)
          .flexGrow(1)
        Text(this.foodItem.calories + ' kcal')
          .fontSize(14)
      }
      .height(64)
    }
    // 页面间数据传递
    .params({ foodInfo: this.foodItem })
    .margin({ right: 24, left:32 })
  }
}

其中,Navigator为路由容器组件,包装了页面路由的能力,指定页面target后,使其包裹的子组件都具有路由能力。.params方法用于页面间数据传递。

程序运行效果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

相关问题

问题1:路由失效

报错如下:

[manifest_router.cpp(GetPagePath)-(0)] [Engine Log] can’t find this page pages/FoodDetail path

解决方案:

main_pages中添加pages/FoodDetail

在这里插入图片描述

最后

随着鸿蒙开发越来越火热,我了解到现在有很多小伙伴想入行鸿蒙,但又不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。我给大家整理了一份实用的鸿蒙(Harmony OS)开发学习手册资料用来跟着学习是非常有利于帮助大家提升鸿蒙开发技术的。

相对于网上那些碎片化的知识内容,这份学习资料的知识点更加系统化,更容易理解和记忆。资料包含了、应用开发导读(ArkTS)、HarmonyOS 概念、如何快速入门、开发基础知识、基于ArkTS 开发、等鸿蒙开发必掌握的核心知识要点,内容包含了(技术知识点。

在这里插入图片描述


希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

获取这份完整版高清学习路线,请点击→《一小时快速认识HarmonyOS》

鸿蒙(Harmony NEXT)最新学习路线

在这里插入图片描述


有了路线图,怎么能没有学习资料呢,小编也准备了几套HarmonyOS NEXT学习视频 内容包含以下联

内容包含:ArkTS、ArkUI、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→《鸿蒙星河版开发教程》

D·TS语法教程

在这里插入图片描述


领取以上完整高清学习视频,请点击→《鸿蒙 (Harmony OS)D·TS语法教程》小编自己整理的部分学习资料(包含有高清视频、开发文档、电子书籍等)

ArkTS基础链接

在这里插入图片描述


领取以上完整高清学习视频,请点击→《鸿蒙HarmonyOS:ArkTS基础链接》小编自己整理的部分学习资料(包含有高清视频、开发文档、电子书籍等)

TypeScript链接

在这里插入图片描述


领取以上完整高清学习视频,请点击→《HarmonyOS;TypeScript链接》小编自己整理的部分学习资料(包含有高清视频、开发文档、电子书籍等)

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

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

相关文章

DHCP-SNOOPING-嗅探/窥探

DHCP-SNOOPING 私接设备了&#xff0c;非终端收到了报文 所有接口设置为非信任&#xff0c;然后单独配置其中一个接口为信任

《ARM汇编与逆向工程 蓝狐卷 基础知识》

推荐一本专注于Arm逆向分析技术的好书《ARM汇编与逆向工程 蓝狐卷 基础知识》&#xff0c;3月21日将在点赞者中抽取粉丝进行本书包邮免费赠送。 目录 正文内容简介作者简介译者简介目录了解更多 正文 与传统的CISC&#xff08;Complex Instruction Set Computer&#xff0c;复…

聚道云连接器助力航信费控与用友U8无缝对接,赋能供应链管理!

客户介绍 某供应链管理有限公司是一家专注于供应链管理和物流服务的领先企业&#xff0c;在行业内享有盛誉。公司业务遍布全球&#xff0c;拥有庞大的客户群和丰富的行业经验。近年来&#xff0c;公司不断加大数字化投入&#xff0c;以提升运营效率和服务水平。 客户痛点 在…

springboot274基于web的电影院购票系统

电影院购票系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装电影院购票系统软件来发挥其高效…

渗透测试实战思路分析

免责声明&#xff1a;文章来源真实渗透测试&#xff0c;已获得授权&#xff0c;且关键信息已经打码处理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人…

单片机设计-基于树莓派的wifi小车的设计与实现

项目介绍 有两个目的&#xff1a;1&#xff09;实现wifi小车的基本功能&#xff1a;使用树莓派&#xff08;单片机&#xff09;以及各种电子元器件&#xff0c;组装完成一个智能小车&#xff0c;通过Python、Java、C控制树莓派&#xff08;单片机&#xff09;的GPIO&#xff0…

LoadRunner学习:RuntimeSetting、参数化、关联、(unfinished

LoadRunner RuntimeSetting 运行时设置 在Vuser中设置Run-time Settings RunLogic&#xff1a;运行逻辑&#xff0c;决定了脚本真正执行逻辑&#xff0c; Init和End部分代码只能执行一次。决定脚本真正执行逻辑的意思是&#xff0c;在Run中的代码和Number of Iteration决定了…

【Leetcode每日一题】 递归 - 反转链表(难度⭐)(35)

1. 题目解析 题目链接&#xff1a;206. 反转链表 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 一、递归函数的核心任务 递归函数的主要职责是接受一个链表的头指针&#xff0c;并返回该链表逆序后的新头结点。递归…

Linux从0到1——Linux第一个小程序:进度条

Linux从0到1——Linux第一个小程序&#xff1a;进度条 1. 输出缓冲区2. 回车和换行的本质3. 实现进度条3.1 简单原理版本3.2 实际工程版本 1. 输出缓冲区 1. 小实验&#xff1a; 编写一个test.c文件&#xff0c;&#xff1a; #include <stdio.h> #include <unistd.h…

‘sqlcmd‘不是内部或外部命令,也不是可运行的程序或批处理文件。

目录 一、问题 二、下载&安装sqlcmd 实用工具 三、验证 四、结果 一、问题 今天使用批处理文件执行SQLServer数据库的SQL语法时报错&#xff0c;提示sqlcmd不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。&#xff0c;发生这个问题的原因是当前系统缺少…

【开发工具学习_Xshell介绍与安装】

开发工具学习_Xshell介绍与安装 开发工具学习_Xshell介绍与安装Xshell介绍Xshell安装 开发工具学习_Xshell介绍与安装 Xshell介绍 Xshell [1]是一个强大的安全终端模拟软件&#xff0c;它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议。Xshell 通过互联网到远程主…

107. 如何使用Docker以及Docker Compose部署Go Web应用

文章目录 一、为什么需要Docker&#xff1f;二、Docker部署示例1. 准备代码2. 创建Docker镜像3. 编写Dockerfile4. Dockerfile解析5. 构建镜像6. 通过镜像创建容器运行 三、分阶段构建示例四、附带其他文件的部署示例五、关联其他容器六、Docker Compose模式七、总结 本文将介绍…

Android Studio实现内容丰富的安卓图书管理系统

获取源码请点击文章末尾QQ名片联系&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动 项目编号060 1.开发环境android stuido jdk1.8 eclipse mysql tomcat 2.功能介绍 安卓端&#xff1a; 1.注册登录 2.查看图书列表 3.查看图书详情 4.评论图书&#xff0c; 5.…

复习C语言基础中的基础:C语言发展、C89 C99有何区别、C语言特点

参考《C程序设计&#xff08;第五版&#xff09;》&#xff08;谭浩强&#xff09;一书&#xff1a; 1. 发展、C89 C99 2. 特点 记得时不时回顾一下背景特点&#xff0c;加深对C语言的理解。

学古琴,万一学错了,还能改吗?

【古琴】学琴容易&#xff0c;改琴难&#xff1b; 错误的观念形成&#xff0c;需要大量的时间去调整大脑和肢体的动作&#xff1b; 当别人在学习新知识的时候&#xff0c;你却在改错误。 在古琴界因为门派和传承的关系&#xff0c;有大量不科学的毛病"&#xff0c;比如音…

HTML—CSS盒子模型(Box Model)

基本介绍&#xff1a; CSS处理网页时&#xff0c;HTML的每一个标签可以看作是一个盒子&#xff0c;网页布局将指定的标签放到指定的位置上摆放&#xff0c;相当于摆放盒子。 每一个标签(盒子)所包含的内容&#xff1a;从外到内 ①外边距(margin)—规定盒子与盒子之间的距离&…

【ShenYu源码阅读】支持提醒通知设计,来看看开源贡献者都做了什么

相信大家碰到源码时经常无从下手&#x1f643;&#xff0c;不知道从哪开始阅读&#xff0c;面对大量代码晕头转向&#xff0c;索性就读不下去了&#xff0c;又浪费了一次提升自己的机会&#x1f62d;。 我认为有一种方法&#xff0c;可以解决大家的困扰&#xff01;那就是通过阅…

百度飞桨大模型训练营:人工智能与大语言模型

1 人工智能基础概念全景介绍 1.1 人工智能概念 解释这些概念 AI是计算机学科下的一个分支学科&#xff0c;旨在使用计算机使之能像人类一样学习和思考问题机器学习是AI的一个子集&#xff0c;它的一个重要特点就是不需要人去做显示编程&#xff08;不用手撕函数&#xff09;&…

YOLOv7_pose-Openvino和ONNXRuntime推理【CPU】

纯检测系列&#xff1a; YOLOv5-Openvino和ONNXRuntime推理【CPU】 YOLOv6-Openvino和ONNXRuntime推理【CPU】 YOLOv8-Openvino和ONNXRuntime推理【CPU】 YOLOv7-Openvino和ONNXRuntime推理【CPU】 YOLOv9-Openvino和ONNXRuntime推理【CPU】 跟踪系列&#xff1a; YOLOv5/6/7-O…

关系代数-练习

设有一个SPJ数据库&#xff0c;包括4个关系模式S、P、J和 SPJ。 S(SNO, SNAME,STATUS,CITY) ; P(PNO,PNAME,COLOR,WEICHT) ; J(JNO,JNAME,CITY); SPJ(SNO,PNO,JNO,QTY)。 供应商表S由供应商代码(SNO)、供应商姓名(SNAME)、供应商状态(STATUS)、供应商…