黑马健康生活案例HarmonyOS---饮食记录模块

 

目录

前言

一、分析饮食记录模块的布局设计                     

二、顶部搜索栏

1.组件构成

2.代码实现

 

二、统计卡片

1.组件构成

2.代码实现

2.1 弹窗组件实现

2.2 统计卡片组件(日期部分)

3. UI效果展示

 

总结


 

 

 

 

 

 


 

前言

本文参考黑马移动开发技术(HarmonyOS)的实战案例:健康生活案例,记录自己在做这个案例时遇到的问题,和想要分享的要点。

 

一、分析饮食记录模块的布局设计                

 如下图所示:右图是我们想要实现的饮食记录模块,根据该UI样式我们可以抽象出如左图所示的结构,我们接下来做的就是添加这些组件,填充并丰富组件的样式及内容。

                     80cc1c62f0b64677a07445dfc33e1660.png           715dd87ba0e44d22b5c7a2ee2b5226bb.png   

饮食记录页总共可分为三部分顶部搜索栏,统计卡片,记录列表。   由于都写到饮食记录页过于冗杂,所以我们抽取这三个组件放到各自的est文件中,我们只负责在饮食记录页调用就好了。下面我将详细说明这三个组件的设计。                                 

 

二、顶部搜索栏

 

1.组件构成

由上面的分析的布局图片可知:顶部搜索栏左边是个带搜索图标的输入框(Search组件),右边是一个邮件图片,图片右上角有提示未读信息的小红标记,它们呈行式布局。

 

2.代码实现

 代码如下:

import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export struct SearchHeader {
  build() {
    Row({space:CommonConstants.SPACE_6}){
       Search({placeholder:'搜索饮食或运动信息'})
         .textFont({size:18})
         .layoutWeight(1)
      //badge包裹组件用来显示右上角的提示未读信息
      Badge({count:1,position: BadgePosition.RightTop ,style:{fontSize:12}}){
        Image($r('app.media.ic_public_email'))
          .width(24)
      }

    }
    .width(CommonConstants.THOUSANDTH_940)
  }
}

 

注意:这里提示的小红圈是鸿蒙自带的Badge组件,我们只需要根据API手册使用就好了。

 

二、统计卡片

 

1.组件构成

e4b439db084941b091d7740d46b5d516.png

由上图可见:整体呈列式布局。日期那一行由tex和倒三角的image图片组成。下一行是个swiper组件(里面装热量统计组件和营养统计组件),swiper里面的装的东西可以切换实现轮播切换的效果,最下面是一个list列表。

 

2.代码实现

2.1 弹窗组件实现

要求点击日期后面的倒三角图片会弹出日期弹框。

import { CommonConstants } from '../../common/constants/CommonConstants'
@CustomDialog
export 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)
          console.info('select current date is: ' + JSON.stringify(value))
        })
      //2.按钮

      Row({space:CommonConstants.SPACE_12}){
        Button('取消')
          .backgroundColor($r('app.color.light_gray'))
          .width(120)
          .onClick(()=>{
            this.controller.close()
          })
        Button('确定')
          .backgroundColor($r('app.color.primary_color'))
          .width(120)
          .onClick(()=>{
            //1.保存日期到全局存储(使应用内的页面都能用)
              AppStorage.SetOrCreate('selectedDate',this.selectedDate.getTime())
            //注意:这个地方不直接把data对象存进去,因为它将来在做状态变量监控的时候会出现问题(prop link state),
            // 所以这里存储它所对应的毫秒值(基础类型可以状态监控)
            this.controller.close()

            //2.关闭窗口
          })
      }
    }
    .padding(12)
  }
}

注意:点击确定按钮后除了要关闭弹窗还要将日期值保存下来,这个地方不直接把data对象存进去,因为它将来在做状态变量监控的时候会出现问题(prop link state)。详细可见状态管理那一节。

 

2.2 统计卡片组件(日期部分)

在统计卡片组件中完善日期部分,到此已经实现了统计卡片日期信息组件功能的实现,当我们点击日期后的倒三角图标后会弹出日期选择弹窗,我们可以滑动选择时间,点击确定后该日期会同步到其它使用该日期的地方。

import { CommonConstants } from '../../common/constants/CommonConstants'
import DateUtil from '../../common/utils/DateUtil'
import { CalorieStats } from './CalorieStats'
import { DatePickDialog } from './DatePickDIalog'
@Component
export struct StatsCard {
  //new Date()默认今天日期但是有时分秒,而而我们需要存储的不需要这个
  @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_10)
      .onClick(()=>this.controller.open())

      //2.统计信息
      Swiper(){
        //2.1.热量统计
        CalorieStats()
        //2.2营养统计

      }
      .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)

  }
}

 

 

beginTimeOfDay方法的代码如下所示:

 该方法是用来将一个带有时分秒的日期的年月日转成毫秒并返回

  beginTimeOfDay(date: Date){
    let d = new Date(date.getFullYear(), date.getMonth(), date.getDate())
    return d.getTime()
  }

 

注意:

@StorageProp('selectedDate') selectedDate:number =DateUtil.beginTimeOfDay(new Date()) 这个地方没有直接new Date()来初始化为当前日期,而是调用函数beginTimeOfDay()来对当前日期进行处理,只获取年月日部分,丢掉时分秒。因为我们在存储全局变量的时候就只存储的年月日。这样使我们日期前后一致,防止影响我们后续的操作。

 

三、UI效果展示

点击倒三角后即可进行日期选择,确定日期后下次点开仍是当前日期(全局变量selectedDate回显)并且选择的日期会同步到其他@StorageProp('selectedDate') selectedDate的地方。

 

54cc328c45604c9db7f092975798c2f9.png

 


 

总结

以上就是今天的内容,本文实现了饮食记录模块的顶部搜索栏和统计卡片日期部分的实现,一定要注意全局存储AppStorage.SetOrCreate()的使用和不要直接new Date()来初始化为当前日期,而是调用函数beginTimeOfDay()来对当前日期进行处理。下篇文章将完善统计卡牌组件并且完成饮食记录模块。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值