期末项目实战:基于鸿蒙ArkTs语言的健康检测App饮食记录分组开发

第五篇:饮食记录分组开发

8.1底层原理

在食物列表中,用户点击食物列表右侧的加号按钮,就可以添加对应的饮食记录了,比如用户点击早餐,系统则添加

上述图片包含的模型:

图片1上方包含了食物统计信息的模型,下方是饮食记录的分组的模型还有饮食j记录本身的模型。

图片2存在一个食物信息的数据模型。这也是我们的出发点,从底层的食物数据模型往上写,因为饮食记录是基于食物数据模型来的,没有食物那就没有饮食记录了。

但是我们发现在饮食记录中还存在一列为“运动”的记录,那么我们则要添加相应的运动项目而不能再是食物的信息了,所以我们还需要一个与运动相关的表如图三。该页面有运动的详细信息。

我们发现食物的列表项与运动的列表项极其相似(图二与图三)都是一个TabBar模型。有TabBar和TabContent,所以我们可以把它们抽取成一个数据模型。

用name来区分是食物模型还是数据模型。

因为我们将食物和运动都写在了一个模型中,所以该模型我们要定义的变量不光要有食物,还要有运动的相关信息,来制作一个通用数据模型。cunfang

再viewModel中我们首先定义好了相关变量并且使用构造函数进行初始化。

export default class ItemCategory{ id:number name:ResourceStr constructor(id:number,name:ResourceStr) { this.id = id this.name = name } }

其次我们编写卡片对应的变量并且进行初始化

export default class RecordItem{ id:number name:ResourceStr image:ResourceStr categoryId:number calorie:number unit:ResourceStr carbon:number protein:number fat:number constructor(id:number,name:ResourceStr,image:ResourceStr,categoryId:number,unit:ResourceStr,calorie:number,carbon:number=0,protein:number = 0 ,fat:number = 0) { this.id = id this.name = name this.image =image this.categoryId = categoryId this.unit = unit this.calorie = calorie this.carbon = carbon this.protein = protein this.fat = fat } }

最后我们导入先前定义好的对列表的操作方法ItemModel和ItemCategoryModel

ItemModel

import RecordItem from '../viewmodel/RecordItem' import { FoodCategories, FoodCategoryEnum, WorkoutCategories, WorkoutCategoryEnum } from './ItemCategoryModel' const foods: RecordItem[] = [ new RecordItem(0, '米饭',$r('app.media.rice'),FoodCategoryEnum.STAPLE, '碗', 209, 46.6, 4.7, 0.5), new RecordItem(1, '馒头',$r('app.media.steamed_bun'),FoodCategoryEnum.STAPLE, '个', 114, 24.0, 3.6, 0.6), new RecordItem(2, '面包',$r('app.media.bun'),FoodCategoryEnum.STAPLE, '个', 188, 35.2, 5.0, 3.1), new RecordItem(3, '全麦吐司',$r('app.media.toast'),FoodCategoryEnum.STAPLE, '片', 91, 15.5, 4.4, 1.3), new RecordItem(4, '紫薯',$r('app.media.purple_potato'),FoodCategoryEnum.STAPLE, '个', 163, 42.0, 1.6, 0.4), new RecordItem(5, '煮玉米',$r('app.media.corn'),FoodCategoryEnum.STAPLE, '根', 111, 22.6, 4.0, 1.2), new RecordItem(6, '黄瓜',$r('app.media.cucumber'),FoodCategoryEnum.FRUIT, '根', 29, 5.3, 1.5, 0.4), new RecordItem(7, '蓝莓',$r('app.media.blueberry'),FoodCategoryEnum.FRUIT, '盒', 71, 18.1, 0.9, 0.4), new RecordItem(8, '草莓',$r('app.media.strawberry'),FoodCategoryEnum.FRUIT, '颗', 14, 3.1, 0.4, 0.1), new RecordItem(9, '火龙果',$r('app.media.pitaya'),FoodCategoryEnum.FRUIT, '个', 100, 24.6, 2.2, 0.5), new RecordItem(10, '奇异果',$r('app.media.kiwi'),FoodCategoryEnum.FRUIT, '个', 25, 8.4, 0.5, 0.3), new RecordItem(11, '煮鸡蛋',$r('app.media.egg'),FoodCategoryEnum.MEAT, '个', 74, 0.1, 6.2, 5.4), new RecordItem(12, '煮鸡胸肉',$r('app.media.chicken_breast'),FoodCategoryEnum.MEAT, '克', 1.15, 0.011, 0.236, 0.018), new RecordItem(13, '煮鸡腿肉',$r('app.media.chicken_leg'),FoodCategoryEnum.MEAT, '克', 1.87, 0.0, 0.243, 0.092), new RecordItem(14, '牛肉',$r('app.media.beef'),FoodCategoryEnum.MEAT, '克', 1.22, 0.0, 0.23, 0.033), new RecordItem(15, '鱼肉',$r("app.media.fish"),FoodCategoryEnum.MEAT, '克', 1.04, 0.0, 0.206, 0.024), new RecordItem(16, '牛奶',$r("app.media.milk"),FoodCategoryEnum.MEAT, '毫升', 0.66, 0.05, 0.03, 0.038), new RecordItem(17, '酸奶',$r("app.media.yogurt"),FoodCategoryEnum.MEAT, '毫升', 0.7, 0.10, 0.032, 0.019), new RecordItem(18, '核桃',$r("app.media.walnut"),FoodCategoryEnum.NUT, '颗', 42, 1.2, 1.0, 3.8), new RecordItem(19, '花生',$r("app.media.peanut"),FoodCategoryEnum.NUT, '克', 3.13, 0.13, 0.12, 0.254), new RecordItem(20, '腰果',$r("app.media.cashew"),FoodCategoryEnum.NUT, '克', 5.59, 0.416, 0.173, 0.367), new RecordItem(21, '无糖拿铁',$r("app.media.coffee"),FoodCategoryEnum.OTHER, '毫升', 0.43, 0.044, 0.028, 0.016), new RecordItem(22, '豆浆',$r("app.media.soybean_milk"),FoodCategoryEnum.OTHER, '毫升', 0.31, 0.012, 0.030, 0.016), ] const workouts: RecordItem[] = [ new RecordItem(10000, '散步',$r('app.media.ic_walk'), WorkoutCategoryEnum.WALKING, '小时', 111), new RecordItem(10001, '快走',$r('app.media.ic_walk'), WorkoutCategoryEnum.WALKING, '小时', 343), new RecordItem(10002, '慢跑',$r('app.media.ic_running'), WorkoutCategoryEnum.RUNNING, '小时', 472), new RecordItem(10003, '快跑',$r('app.media.ic_running'), WorkoutCategoryEnum.RUNNING, '小时', 652), new RecordItem(10004, '自行车',$r('app.media.ic_ridding'), WorkoutCategoryEnum.RIDING, '小时', 497), new RecordItem(10005, '动感单车',$r('app.media.ic_ridding'), WorkoutCategoryEnum.RIDING, '小时', 587), new RecordItem(10006, '瑜伽',$r('app.media.ic_aerobics'), WorkoutCategoryEnum.AEROBICS, '小时', 172), new RecordItem(10007, '健身操',$r('app.media.ic_aerobics'), WorkoutCategoryEnum.AEROBICS, '小时', 429), new RecordItem(10008, '游泳',$r('app.media.ic_swimming'), WorkoutCategoryEnum.SWIMMING, '小时', 472), new RecordItem(10009, '冲浪',$r('app.media.ic_swimming'), WorkoutCategoryEnum.SWIMMING, '小时', 429), new RecordItem(10010, '篮球',$r('app.media.ic_basketball'), WorkoutCategoryEnum.BALLGAME, '小时', 472), new RecordItem(10011, '足球',$r('app.media.ic_football'), WorkoutCategoryEnum.BALLGAME, '小时', 515), new RecordItem(10012, '排球',$r("app.media.ic_volleyball"), WorkoutCategoryEnum.BALLGAME, '小时', 403), new RecordItem(10013, '羽毛球',$r("app.media.ic_badminton"), WorkoutCategoryEnum.BALLGAME, '小时', 386), new RecordItem(10014, '乒乓球',$r("app.media.ic_table_tennis"), WorkoutCategoryEnum.BALLGAME, '小时', 257), new RecordItem(10015, '哑铃飞鸟',$r("app.media.ic_dumbbell"), WorkoutCategoryEnum.STRENGTH, '小时', 343), new RecordItem(10016, '哑铃卧推',$r("app.media.ic_dumbbell"), WorkoutCategoryEnum.STRENGTH, '小时', 429), new RecordItem(10017, '仰卧起坐',$r("app.media.ic_sit_up"), WorkoutCategoryEnum.STRENGTH, '小时', 515), ] class ItemModel{ getById(id: number, isFood: boolean = true){ return isFood ? foods[id] : workouts[id - 10000] } list(isFood: boolean = true): RecordItem[]{ return isFood ? foods : workouts } listItemGroupByCategory(isFood: boolean = true){ // 1.判断要处理的是食物还是运动 let categories = isFood ? FoodCategories : WorkoutCategories let items = isFood ? foods: workouts // 2.创建空的分组 let groups = categories.map(itemCategory => new GroupInfo(itemCategory, [])) // 3.遍历记录项列表,将食物添加到对应的分组 items.forEach(item => groups[item.categoryId].items.push(item)) // 4.返回结果 return groups } } let itemModel = new ItemModel() export default itemModel as ItemModel

ItemCategoryModel

import ItemCategory from '../viewmodel/ItemCategory' /** * 食物类型的枚举 */ enum FoodCategoryEnum{ /** * 主食 */ STAPLE, /** * 蔬果 */ FRUIT, /** * 肉蛋奶 */ MEAT, /** * 坚果 */ NUT, /** * 其它 */ OTHER, } /** * 食物类型数组 */ let FoodCategories = [ new ItemCategory(0, $r('app.string.staple')), new ItemCategory(1, $r('app.string.fruit')), new ItemCategory(2, $r('app.string.meat')), new ItemCategory(3, $r('app.string.nut')), new ItemCategory(4, $r('app.string.other_type')), ] /** * 运动类型枚举 */ enum WorkoutCategoryEnum { /** * 走路 */ WALKING, /** * 跑步 */ RUNNING, /** * 骑行 */ RIDING, /** * 跳操 */ AEROBICS, /** * 游泳 */ SWIMMING, /** * 打球 */ BALLGAME, /** * 力量训练 */ STRENGTH } /** * 运动类型数组 */ let WorkoutCategories = [ new ItemCategory(0, $r('app.string.walking_type')), new ItemCategory(1, $r('app.string.running')), new ItemCategory(2, $r('app.string.riding')), new ItemCategory(3, $r('app.string.aerobics')), new ItemCategory(4, $r('app.string.swimming')), new ItemCategory(5, $r('app.string.ballgame')), new ItemCategory(6, $r('app.string.strength')), ] export {FoodCategories , WorkoutCategories , FoodCategoryEnum, WorkoutCategoryEnum}

  • 你最想分享的亮点

1.响应式布局

通过使用 BreakpointSystem 类和 BreakpointType 对象,组件能够根据屏幕尺寸的变化动态调整布局和元素的显示方式,并且在BreakpointConstant文件中将不同类型的屏幕尺寸进行划分,并且分别用不同的代号进行代替(sm、md、lg)来区分小屏幕、折叠屏、平板。

2.国际化

提前定义好的CommonConstant文件可以将页面占比、字体粗细、颜色等提前定义好,在使用的时候直接$r调用相关的文件,这种方法首先美化了整体的页面布局,其次与国际化和本地化支持有关,允许应用根据不同语言和地区显示相应的资源。

3.代码的高可用

将每个组件根据页面进行划分,避免了冗长的代码,而且当页面多次调用该组件的时候直接调用组件的构造器的名称即可。

4.蒙版和背景色设置

设置 .backgroundMask($r('app.color.light_gray')) 和 .backgroundColor(Color.White) 为面板提供了蒙版颜色和背景色。

5.使用延时跳转

通过使用setTimeout函数,在用户同意隐私协议后延时一定时间后跳转到主页。这样可以给用户一定的等待时间,增强用户体验。

6.使用自定义对话框

通过调用UserPrivacyDialog对话框组件,实现了用户隐私协议的展示和确认功能。该对话框在用户未同意隐私协议时弹出,以便用户确认。

7.使用状态管理

通过使用@State注解,将message变量声明为状态变量,使其能够在页面更新时自动更新。这可以用于跟踪和控制页面状态的变化。

  • 小结

  1. UI布局和样式定义:我使用 Column、Row、Image 和 Text 等UI组件来构建界面布局,并使用 .width、.height、.backgroundColor 等样式属性来设置组件的大小和外观。我还定义了 toumingWhiteFont 方法来统一设置文字的透明度、字号和颜色,以保持界面风格的一致性。
  2. 响应式设计:我利用 BreakpointSystem 类来监听屏幕尺寸的变化,并根据当前的屏幕尺寸断点动态调整UI布局。例如,在 StatsCard 组件中,我使用了 BreakpointType 对象来获取当前断点的值,并据此设置 Swiper 组件的展示数量和指示器样式。
  3. 学会了使用Stock层叠器和Grid表格布局的使用,通过Grid表格来创建数字键盘。
  • 使用资源

别只知道Keep了!这11款健身APP,助你一个月瘦10斤不是梦!_手机软件_什么值得买 (smzdm.com)

一文看懂 iPhone 自带 App《健康》各项指标

华为运动健康

运动健康app可以带来什么好处 运动健康app的功能介绍

鸿蒙HarmonyOS实战-ArkUI组件(Tabs)

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Tabs)

【愚公系列】2022年01月 华为鸿蒙OS-04-容器组件(badge、dialog、div)(JS开发版)

【鸿蒙软件开发】ArkTS容器组件之Badge

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Badge组件

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Search组件

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Swiper容器组件

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Swiper)

媒体查询(mediaquery)

媒体类型(media-type)

媒体逻辑操作(media-logic-operations)

媒体特征(media-feature)

鸿蒙开发中,判断一个数字是否为数字的方法

C++ 中的 NaN:产生原因、特性及处理方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

害羞的白菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值