系列文章目录
鸿蒙开发案例:健康App(1)欢迎页面Ul实现
前言
案例来源于黑马程序员的课程
案例介绍
饮食记录-统计卡片
一、整体思路
二、实现步骤
1.日期信息
日期信息样式
颜色比主色调更深一点
记得在DatePickDialog.ets中使用
弹窗组件:日期选择器,按钮
日期选择器:在API中查找,复制并修改
按钮:取消灰色,确定主色调(绿色)按钮之间加一点距离
点击取消:close
点击确定:
1)存毫秒值(全局存储)
2)关闭窗口
在StatsCard中运用:
beginTimeOfDay获取今天的开始日期
读取,回显,产生联动效果
修改日期信息
添加点击事件:打开弹窗
2.统计信息
可滑动对话框Swiper(API)
现在背景还是蓝色,将文字背景色去掉即可
3.热量组件
现在代码重复率很高,参照“还可以吃”进行抽取(Builder函数)
进度条(Stack)
4.营养素组件
和热量组件类似
总结
// src/main/ets/view/record/StatsCard.ets
import DateUtil from '../../common/utils/DateUtil'
import DatePickDialog from './DatePickDialog'
import { CommonConstants } from '../../common/constants/CommonConstants'
import CalorieStats from './CalorieStats'
import NutrientStats from './NutrientStats'
@Component
export default struct StatsCard {
// 把selectedDate从AppStorage里出去来,这里需要用到 @StorageProp这个注解,同时我们要对取出来的日期处理,因为我们存的是日期毫秒数,这里自己写了个工具类
@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(){
// 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)
}
}
// src/main/ets/view/record/DatePickDialog.ets
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官方组件
DatePicker({
start: new Date('2020-01-01'),
end: new Date(),
selected: this.selectedDate
})
.onChange((value: DatePickerResult) => {
// 注意这里,选择的结果是年月日,没有时分秒,默认是当日的0时,0分,0秒
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是一个全局的存储空间,getTime()获取的是日期毫秒数,以为存一个日期对象,会不好处理
AppStorage.SetOrCreate('selectedDate', this.selectedDate.getTime())
// 2.关闭窗口
this.controller.close()
})
}
}
.padding(CommonConstants.SPACE_12)
}
}
// src/main/ets/view/record/CalorieStats.ets
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'))
}
}
}
}
// src/main/ets/view/record/NutrientStats.ets
import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct NutrientStats {
// 碳水化合物
carbon: number = 10
// 蛋白质
protein: number = 20
// 脂肪
fat: number = 20
// 推荐摄入的碳水化合物,蛋白质,脂肪
recommendCarbon: number = CommonConstants.RECOMMEND_CARBON
recommendProtein: number = CommonConstants.RECOMMEND_PROTEIN
recommendFat: number = CommonConstants.RECOMMEND_FAT
build() {
Row({space: CommonConstants.SPACE_6}){
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')
)
}
.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'))
}
}
}