目录
项目介绍:
黑马健康软件是一款基于全民健康的软件,主要有三个页面组成,分别是欢迎页面,统计记录页面,食物列表页面。
页面布局:
分析:
- 总体是列式布局,内部是行式布局;
- 最上面的文本输入框是search组件,右边是一个image组件,
- 第二行是最上面是一个text文本(点击会有弹窗效果,进行日期选择,用到的新组件是datepicker)最下面是一个swiper组件。
- 最后一行是一个list列表;
步骤:
饮食记录-顶部搜索栏:饮食记录ui设计
- 首先在view文件夹下面新建一个record文件夹,在该文件夹下建立recordindex.ets文件,然后在该文件中进行页面的组织。
- 该页面的第一部分——头部搜索栏在该目录下新建searchheader.ets文件,在该文件中组织该部分内容。
饮食记录-统计卡片:饮食记录ui设计
- 在record文件夹下新建一个statscard.ets文件,用于组织统计卡片;新建一个datepickdialog.ets文件,用于组织点击日期的弹窗;新建一个caloriestats.ets文件,在统计信息部分的swiper()组件中调用,用于热量的统计;新建一个nutrientstats.ets文件,在统计信息部分的swiper()组件中调用,用于营养素的统计;
饮食记录-记录列表:饮食记录ui设计
- 在record文件夹下新建一个recordlist.ets文件,用于加载记录的列表。
页面实现效果:
出现的问题与解决:
问题1:
搜索框所在的一行设置完成之后,邮箱图片会被挤没,是因为没有设置宽高比例
改后效果和代码:
问题2:
当在日期选择对话框里选择相应的日期后,上面的显示的日期并不改变,所做出的更改日期的操作无效:
出现原因:
这里的键值对的键定义的名字和后面用到时的名字对不上,所以值无法传递
修改之后的运行效果:
问题3:
再点击事件中定义了组件的重新渲染,对早餐图片进行重新渲染,怎么该都不会变色,但是用过打印日志发现,事件已经被触发,追根溯源,图片的格式是png形式,不是svg形式,不能进行图片颜色的填充。
解决方式:重新下载一个svg图片来代替,点击后的效果
阶段项目代码:
/**
* 首页饮食记录页面
*/
import recordlist from './recordlist';
import searchheader from './searchheader'
import statscard from './statscard';
@component
export default struct recordindex{
build(){
column(){
// 1.头部搜索栏
searchheader()
// 2.统计卡片
statscard();
// 3.记录列表
recordlist()
.layoutweight(1)//占据剩余所有高度
}
.width('100%')
.height('100%')
.backgroundcolor($r('app.color.index_page_background'))
}
}
饮食记录-顶部搜索栏代码:饮食记录
/**
* 饮食健康页面——头部搜索栏
*/
import { commonconstants } from '../../common/constants/commonconstants'
@component
export default struct searchheader{
build(){
row({space:commonconstants.space_6}) {
// 1.输入框
search({ placeholder: '搜索饮食或运动信息' })
.textfont({ size: 18 })
.layoutweight(1)//占剩下的所有部分
//必须传够所有参数,不然报错
badge({count:1,position:badgeposition.righttop,style:{fontsize:12}}){
image($r('app.media.ic_public_email'))
.width(24)//写死的宽度,刚好显示出来
}
}
.width(commonconstants.thousandth_940)//让这一行宽度占屏幕宽度的94%
}
}
饮食记录-统计卡片代码:饮食记录
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(){
// 2.1 热量统计
caloriestats()
// 2.2 营养素统计
nutrientstats()
}.width('100%')
.backgroundcolor(color.white)
.borderradius(commonconstants.default_18)
.indicatorstyle({selectedcolor:$r('app.color.primary_color')})// todo 设置穿梭框的样式
}.width(commonconstants.thousandth_940)
.backgroundcolor($r('app.color.stats_title_bgc'))
.borderradius(commonconstants.default_18)
}
}
import { commonconstants } from '../../common/constants/commonconstants'
/**
* 热量统计
*/
@component
export default struct caloriestats {
intake:number = 192
expend:number = 268
recommend:number =commonconstants.recommend_calorie
//将计算还可以吃多少的过程封装成函数
remaincalorie(){
return this.recommend-this.intake+this.expend
}
build() {
row({space:commonconstants.space_6}){
//第一部分
this.statsbuilder('饮食摄入',this.intake)
//第二部分
stack(){
//2.1 进度条,默认样式是线性的
progress({
value:this.intake,
total:this.recommend,
type:progresstype.ring
}).width(127)
.style({strokewidth:commonconstants.default_10})
.color($r('app.color.primary_color'))
//2.2 统计数据
this.statsbuilder('还可以吃',this.remaincalorie(), `推荐${this.recommend}`)
}
//第三部分
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}){
//第一部分
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('摄入推荐')
.fontcolor($r('app.color.gray'))
.fontsize(12)
text(`${value.tofixed(0)}/${recommend.tofixed(0)}`)//数字为不带小数的字符串
.fontsize(18)
.fontweight(commonconstants.font_weight_700)
}
}
text(`${label} (克)`)
.fontsize(12)
.fontcolor($r('app.color.light_gray'))
}
}
}
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)
// console.info('select current date is: ' + json.stringify(value))
})
//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'
/**
* 记录列表
*/
@extend(text) function graytext(){
.fontsize(14)
.fontcolor($r('app.color.light_gray'))
}
@component
export default struct recordlist {
@state flag:number = 0;
@state fillcolor:color = color.black
build() {
list({space:commonconstants.space_12}){
foreach([1,2,3,4,5],(item,index)=>{
listitem(){
column(){
// 1.分组的标题
row({space:commonconstants.space_4}){
image($r('app.media.ic_breakfast')).width(27)
.fillcolor(this.fillcolor)
text('早餐').fontweight(commonconstants.font_weight_700).fontsize(18)
text('建议423-529千卡').graytext()
blank()
text('190').fontcolor($r('app.color.primary_color')).fontsize(14)
text('千卡').graytext()
image($r('app.media.ic_public_add_norm_filled')).width(20).fillcolor($r('app.color.primary_color'))
}.width('100%')
.onclick(()=>{
console.log('变色')
//当点击后,该图标的图像就会发生变化
if(this.fillcolor==color.black){
this.fillcolor = color.green
}
})
// 2.组内记录列表
list(){
foreach([1,2],(item)=>{
listitem(){
row({space:commonconstants.space_6}){
image($r('app.media.toast')).width(50)
column(){
text('全麦吐司').fontweight(commonconstants.font_weight_500)
text('1片').graytext()
}
blank()
text('91千卡').graytext()
}.width('100%')
.padding(commonconstants.space_6)
}.swipeaction({end:this.deletebutton.bind(this)})// todo 学习
})
}
}
.backgroundcolor(color.white)
.width('100%')
.borderradius(commonconstants.default_18)
.padding(commonconstants.space_12)
}
})
}.width(commonconstants.thousandth_940)
.margin({top:10})
}
@builder deletebutton(){
image($r('app.media.ic_public_delete_filled'))
.fillcolor(color.red)
.width(25)
.margin(5)
}
}
参考黑马课堂老师的讲解,欢迎批评和指正。
发表评论