赞
踩
饮食记录应用中的统计卡片系统是该应用的核心功能之一。这个统计卡片系统旨在为用户提供一个直观、清晰且全面的饮食数据概览。通过精心设计的界面和智能的数据分析算法,用户可以快速了解自己的饮食规律、营养摄入情况以及与健康目标的差距。
可以通过日期选择对话框选择一个特定的日期,默认为当前日期的开始时间。选定的日期将用于统计和展示该日的热量和营养素摄入情况。
1.日期信息:在日期信息这里设置了点击时打开弹窗
- Row(){
- Text(DateUtil.formatDate(this.selectedDate))
- .fontColor($r('app.color.secondary_color'))
- Image($r('app.media.ic_public_spinner'))
- .width(20)
- .fillColor($r('app.color.secondary_color'))
- }
- .padding(CommonConstants.SPACE_8)
- .onClick(()=>this.controller.open())
2.统计信息:使用到了Swiper滑块视图容器,提供了子组件滑动轮播显示的能力。
2.1热量统计:创建新组件进行调用
2.2营养素统计:创建新组件进行调用
- Swiper(){
- //2.1.热量统计
- CalorieStats()
- //2.2.营养素统计
- NutrientStats()
- }
- .width('100%')
- .backgroundColor(Color.White)
- .borderRadius(CommonConstants.DEFAULT_18)
- .indicatorStyle({selectedColor: $r('app.color.primary_color')})
对话框的创建
1.日期选择器:使用了DatePicker日期选择器组件,用于根据指定日期范围创建日期滑动选择器。
- DatePicker({
- start: new Date('2020-01-01'),
- end: new Date(),
- selected: this.selectedDate
- })
- .onChange((value: DatePickerResult) => {
- this.selectedDate.setFullYear(value.year, value.month, value.day)
- })
2.按钮:有取消和确定两个按钮,确定选中的信息,确定时保存日期到全局存储,然后关闭窗口
- Row({space:CommonConstants.SPACE_12}){
- Button('取消')
- .width(120)
- .backgroundColor($r('app.color.light_gray'))
- .onClick(()=>this.controller.close()) //关闭窗口
- Button('确定')
- .width(120)
- .backgroundColor($r('app.color.primary_color'))
- .onClick(()=>{
- //1.保存日期到全局存储
- AppStorage.SetOrCreate('selectedDate',this.selectedDate.getTime())
- //2.关闭窗口
- this.controller.close()
- })
- }
热量统计的实现,展示用户的饮食摄入、运动消耗和推荐摄入量等信息,计算剩余卡路里(推荐摄入量减去饮食摄入加上运动消耗)
1.饮食摄入
this.StatsBuilder('饮食摄入', this.intake)
2.还可以吃:使用stack堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。实现层叠关系
2.1.进度条:实现的是一个环形进度条的效果
2.2.统计数据:推荐摄入量减去饮食摄入加上运动消耗
- Stack(){
- // 2.1.进度条
- Progress({
- value: this.intake,
- total: this.recommend,
- type: ProgressType.Ring
- })
- .width(120)
- .style({strokeWidth: CommonConstants.DEFAULT_10})
- .color($r('app.color.primary_color'))
- // 2.2.统计数据
- this.StatsBuilder('还可以吃',this.remainCalorie(),`推荐摄入${this.recommend}`)
- }
3.运动消耗
this.StatsBuilder('运动消耗',this.expend)
展示用户摄入的营养成分(碳水化合物、蛋白质和脂肪)以及推荐的摄入量。
1.碳水化合物;2.蛋白质;3.脂肪
- this.StatsBuilder('碳水化合物', this.carbon,this.recommendCarbon,$r('app.color.carbon_color'))
- this.StatsBuilder('蛋白质', this.protein,this.recommendProtein,$r('app.color.protein_color'))
- this.StatsBuilder('脂肪', this.fat,this.recommendFat,$r('app.color.fat_color'))
- import { CommonConstants } from '../../common/constants/CommonConstants'
- import DateUtil from '../../common/utils/DateUtil'
- import CalorieStats from './CalorieStats'
- import DatePickDialog from './DatePickDialog'
- import NutrientStats from './NutrientStats'
- @Component
- export default struct StatsCard {
-
- @StorageProp('selectedDate') selectedDate: number = DateUtil.beginTimeOfDay(new Date())
-
- controller:CustomDialogController = new CustomDialogController({
- builder:DatePickDialog({selectedDate: new Date(this.selectedDate)})
- })
-
- build() {
- Column(){
- //1.日期信息
- Row(){
- Text(DateUtil.formatDate(this.selectedDate)) //将毫秒值转换成日期
- .fontColor($r('app.color.secondary_color'))
- Image($r('app.media.ic_public_spinner'))
- .width(20)
- .fillColor($r('app.color.secondary_color'))
- }
- .padding(CommonConstants.SPACE_8)
- .onClick(()=>this.controller.open()) //打开弹窗
- //2.统计信息
- Swiper(){ //Swiper滑动组件
- //2.1.热量统计
- CalorieStats()
- //2.2.营养素统计
- NutrientStats()
- }
- .width('100%')
- .backgroundColor(Color.White)
- .borderRadius(CommonConstants.DEFAULT_18)
- .indicatorStyle({selectedColor: $r('app.color.primary_color')}) //穿梭框样式
- }
- .width(CommonConstants.THOUSANDTH_940)
- .backgroundColor($r('app.color.stats_title_bgc'))
- .borderRadius(CommonConstants.DEFAULT_18)
- }
- }
- import { CommonConstants } from '../../common/constants/CommonConstants'
- @CustomDialog
- export default struct DatePickDialog {
- controller: CustomDialogController
- selectedDate:Date = new Date()
- build() {
- Column({space:CommonConstants.SPACE_12}){
- //1.日期选择器
- DatePicker({
- start: new Date('2020-01-01'),
- end: new Date(),
- selected: this.selectedDate
- })
- .onChange((value: DatePickerResult) => {
- this.selectedDate.setFullYear(value.year, value.month, value.day)
- })
- //2.按钮
- Row({space:CommonConstants.SPACE_12}){
- Button('取消')
- .width(120)
- .backgroundColor($r('app.color.light_gray'))
- .onClick(()=>this.controller.close()) //关闭窗口
- Button('确定')
- .width(120)
- .backgroundColor($r('app.color.primary_color'))
- .onClick(()=>{
- //1.保存日期到全局存储
- AppStorage.SetOrCreate('selectedDate',this.selectedDate.getTime()) //内部存储,存储的是毫秒值
- //2.关闭窗口
- this.controller.close()
- })
- }
- }
- .padding(CommonConstants.SPACE_12)
- }
- }
- import { CommonConstants } from '../../common/constants/CommonConstants'
- @Component
- export default struct CalorieStats {
- intake: number = 192 //摄入
- expend: number = 150 //运动消耗
- recommend: number = CommonConstants.RECOMMEND_CALORIE //推荐的
-
- remainCalorie(){
- return this.recommend - this.intake + this.expend
- }
-
- build() {
- Row({space: CommonConstants.SPACE_6}){
- // 1.饮食摄入
- this.StatsBuilder('饮食摄入', this.intake)
- // 2.还可以吃
- Stack(){ //实现层叠关系
- // 2.1.进度条
- Progress({
- value: this.intake,
- total: this.recommend, //最大值为推荐值
- type: ProgressType.Ring //环形
- })
- .width(120)
- .style({strokeWidth: CommonConstants.DEFAULT_10})
- .color($r('app.color.primary_color'))
- // 2.2.统计数据
- this.StatsBuilder('还可以吃',this.remainCalorie(),`推荐摄入${this.recommend}`)
- }
- // 3.运动消耗
- this.StatsBuilder('运动消耗',this.expend)
- }
- .width('100%')
- .justifyContent(FlexAlign.SpaceEvenly) //均匀分配
- .padding({top: 30, bottom: 35}) //内边距
- }
-
- @Builder StatsBuilder(label: string, value: number, tips?: string){ //文字说明,数字记录,补充说明
- Column({space: CommonConstants.SPACE_6}){
- Text(label)
- .fontColor($r('app.color.gray'))
- .fontWeight(CommonConstants.FONT_WEIGHT_600)
- Text(value.toFixed(0)) //转成整型字符串
- .fontSize(20)
- .fontWeight(CommonConstants.FONT_WEIGHT_700)
- if(tips){
- Text(tips)
- .fontSize(12)
- .fontColor($r('app.color.light_gray'))
- }
- }
- }
- }
- import { CommonConstants } from '../../common/constants/CommonConstants'
- @Component
- export default struct NutrientStats{
-
- carbon: number = 23 //碳水化合物
- protein: number = 9 //蛋白质
- fat:number= 7 //脂肪
-
- recommendCarbon: number = CommonConstants.RECOMMEND_CARBON
- recommendProtein: number = CommonConstants.RECOMMEND_PROTEIN
- recommendFat: number = CommonConstants.RECOMMEND_FAT
-
-
- build() {
- Row({space: CommonConstants.SPACE_6}){
- // 1.碳水化合物
- this.StatsBuilder('碳水化合物', this.carbon,this.recommendCarbon,$r('app.color.carbon_color'))
- // 2.蛋白质
- this.StatsBuilder('蛋白质', this.protein,this.recommendProtein,$r('app.color.protein_color'))
- // 3.脂肪
- this.StatsBuilder('脂肪', this.fat,this.recommendFat,$r('app.color.fat_color'))
- }
- .width('100%')
- .justifyContent(FlexAlign.SpaceEvenly) //均匀分配
- .padding({top: 30, bottom: 35}) //内边距
- }
-
- @Builder StatsBuilder(label: string, value: number,recommend:number,color:ResourceStr){
- Column({space: CommonConstants.SPACE_6}){
- Stack(){
- Progress({
- value: value,
- total: recommend, //最大值为推荐值
- type: ProgressType.Ring //环形
- })
- .width(95)
- .style({strokeWidth: CommonConstants.DEFAULT_6})
- .color(color)
- Column({space:CommonConstants.SPACE_6}){
- Text('摄入推荐')
- .fontSize(12)
- .fontColor($r('app.color.gray'))
- Text(`${value.toFixed(0)}/${recommend.toFixed(0)}`) //摄入多少,推荐多少都需要传入
- .fontSize(18)
- .fontWeight(CommonConstants.FONT_WEIGHT_600)
- }
- }
- Text(`${label} (克)`)
- .fontSize(12)
- .fontColor($r('app.color.light_gray'))
- }
- }
- }
该统计卡片包括日期选择、热量统计和营养素统计等功能。StatsCard主要包含了三个组件:DatePickDialog,CalorieStats和NutrientStats。StatsCard为统计卡片的主组件,包含日期选择、热量统计和营养素统计;DatePickDialog组件用于对话框的创建,包含日期选择器和按钮的功能;NutrientStats组件展示用户摄入的营养成分(碳水化合物、蛋白质和脂肪)以及推荐的摄入量。
在设计此项目时也学习了很多新组件的用法。例如Swiper组件可以实现手机、平板等移动端设备上的图片轮播效果,支持无缝轮播、自动播放、响应式布局等功能。Swiper轮播图具有使用简单、样式可定制、功能丰富、兼容性好等优点,是很多网站和移动应用中常用的轮播图插件。Swiper是一个容器组件,如果自身尺寸没有被设置,它会根据子组件大小自动调整自身尺寸。如果开发者给Swiper设置了固定尺寸,那么在轮播过程中,Swiper的尺寸将一直保持设置的固定尺寸。如果未设置固定尺寸,Swiper会根据子组件大小自动调整自身尺寸。
层叠布局通过Stack容器组件实现位置的固定定位与层叠,容器中的子元素(子组件)依次入栈,后一个子元素覆盖前一个子元素,子元素可以叠加,也可以设置位置。层叠布局具有较强的页面层叠、位置定位能力,其使用场景有广告、卡片层叠效果等。Stack容器中兄弟组件显示层级关系可以通过Z序控制的zIndex属性改变。zIndex值越大,显示层级越高,即zIndex值大的组件会覆盖在zIndex值小的组件上方。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。