目录
前言
本文参考黑马移动开发技术(HarmonyOS)的实战案例:健康生活案例,记录自己在做这个案例时遇到的问题,和想要分享的要点。
一、分析饮食记录模块的布局设计
如下图所示:右图是我们想要实现的饮食记录模块,根据该UI样式我们可以抽象出如左图所示的结构,我们接下来做的就是添加这些组件,填充并丰富组件的样式及内容。
饮食记录页总共可分为三部分顶部搜索栏,统计卡片,记录列表。 由于都写到饮食记录页过于冗杂,所以我们抽取这三个组件放到各自的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.组件构成
由上图可见:整体呈列式布局。日期那一行由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的地方。
总结
以上就是今天的内容,本文实现了饮食记录模块的顶部搜索栏和统计卡片日期部分的实现,一定要注意全局存储AppStorage.SetOrCreate()的使用和不要直接new Date()来初始化为当前日期,而是调用函数beginTimeOfDay()来对当前日期进行处理。下篇文章将完善统计卡牌组件并且完成饮食记录模块。