(二)鸿蒙实战案例 - 黑马健康生活应用

第二天

前言

综合运用本学期所学内容及个人自学知识,使用HarmonyOS 4.0及以上版本开发一款具有实用性和创新性的移动应用软件。


项目要求

  1. 技术栈:HarmonyOS 4.0,DevEco Studio。
  2. 实用性与创意:软件需解决具体问题,具备用户友好界面,创新性需体现在功能或用户体验上。
  3. 代码质量:遵守HarmonyOS编码规范,代码需模块化,易于维护。

统计卡片

代码: 

import BreakpointType from '../../common/bean/BreanpointType'
import RecordPO from '../../common/bean/RecordPO'
import BreakpointConstants from '../../common/constants/BreakpointConstants'
import { CommonConstants } from '../../common/constants/CommonConstants'
import DateUtil from '../../common/utils/DateUtil'
import RecordService from '../../service/RecordService'
import RecordVO from '../../viewmodel/RecordVO'
import StatsInfo from '../../viewmodel/StatsInfo'
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())//单向传输

  @StorageProp('currentBreakpoint') currentBreakpoint:string = BreakpointConstants.BREAKPOINT_SM

  @Consume @Watch('onRecordsChange') record:RecordVO[]

  @State info:StatsInfo = new StatsInfo()

  onRecordsChange(){
    this.info = RecordService.calculateStatsInfo(this.record)
  }

  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_10)
      .onClick(()=>this.controller.open())


      //2、统计
      Swiper(){
        //热量统计
        CalorieStats({ intake:this.info.intake,expend:this.info.expend })

        //营养素

        NutrientStats({carbon:this.info.carbon,protein:this.info.protein,fat:this.info.fat})

      }
      .width('100%')
      .backgroundColor(Color.White)
      .borderRadius(CommonConstants.DEFAULT_18)
      .indicatorStyle({selectedColor:$r('app.color.primary_color')})//切换点的样式
      .displayCount(new BreakpointType({
        sm:1,
        md:1,
        lg:2
      }).getValue(this.currentBreakpoint))//平铺
    }
    .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(){
      //1、日期选择
      DatePicker({
        start: new Date('2022-04-14'),
        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.primary_color'))
          .onClick(()=>{
            //保存到全局
            AppStorage.SetOrCreate('selectedDate',this.selectedDate.getTime())//全局保存


            this.controller.close()
          })
        Button('取消')
          .width(120)
          .backgroundColor($r('app.color.light_gray'))
          .onClick(()=>this.controller.close())
      }
    }
    .padding(CommonConstants.SPACE_12)
  }
}

 该代码实现了统计卡片的布局和样式,日期选择,滑动容器

热量统计 

代码:

import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct CalorieStats{
  @Prop intake:number
  @Prop expend:number //消耗
  recommend:number = CommonConstants.RECOMMEND_CALORIE//推荐

  remainCalorie(){
    return this.recommend-this.intake + this.expend
  }

  build(){
    Row({space:CommonConstants.SPACE_6}){

      this.StatsBuilder({ label:'饮食摄入', value:this.intake })
      Stack(){
        Progress({
          value:this.intake,
          total:this.recommend,
          type:ProgressType.Ring
        })//进度条
          .width(125)
          .style({strokeWidth:CommonConstants.DEFAULT_8})//环粗细
          .color($r('app.color.primary_color'))
        this.StatsBuilder({
          label:'还可以吃',
          value:this.remainCalorie(),
          tips:`推荐${this.recommend}`
        })
      }

      this.StatsBuilder({ label:'运动消耗', value:this.expend })

    }
    .width('100%')
    .justifyContent(FlexAlign.SpaceEvenly)
    .padding({top:30,bottom:45})
  }


  @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{

  recommendCarbon:number = CommonConstants.RECOMMEND_CARBON//推荐

  recommendProtein:number = CommonConstants.RECOMMEND_PROTEIN

  recommendFat:number = CommonConstants.RECOMMEND_FAT

  @Prop carbon:number

  @Prop protein:number

  @Prop fat:number


  build(){
    Row({space:CommonConstants.SPACE_6}){

      this.StatsBuilder({
        label:'碳水化合物',
        value:this.carbon,
        recommend:this.recommendCarbon,
        color:$r('app.color.carbon_color')
      })

      this.StatsBuilder({
        label:'蛋白质',
        value:this.protein,
        recommend:this.recommendProtein,
        color:$r('app.color.protein_color')
      })


      this.StatsBuilder({
        label:'脂肪',
        value:this.fat,
        recommend:this.recommendFat,
        color:$r('app.color.fat_color')
      })

    }
    .width('100%')
    .justifyContent(FlexAlign.SpaceEvenly)
    .padding({top:30,bottom:45})
  }


  @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(90)
          .style({strokeWidth:CommonConstants.DEFAULT_6})//环粗细
          .color($$.color)
        Column({space:CommonConstants.SPACE_6}){
          Text('摄入推荐')
            .fontSize(12)
            .fontColor($r('app.color.light_gray'))
          Text(`${$$.value.toFixed(0)}/${$$.recommend.toFixed(0)}`)//转整型字符串
            .fontSize(20)
            .fontWeight(CommonConstants.FONT_WEIGHT_700)
        }
      }
      Text(`${ $$.label }(克)` )
        .fontSize(12)
        .fontColor($r('app.color.light_gray'))
    }
}
}

 

 

总结

我了解并学会了如何使用swiper滑动容器,Stack()进度条,在统计卡片日期弹窗中学会使用DatePicker日期选择 selectedDate = new Date()为当前日期,使用AppStorage.SetOrCreate进行全局保存。

使用@StorageProp('selectedDate') selectedDate:number = DateUtil.beginTimeOfDay(new Date())将日期加载

在StatsCard中调用控制选择器,将日期参数传入,在日期行添加点击触发事件,打开日期弹窗

注意弹窗组件@CustomDialog必须有,否则页面不显示

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值