食物列表
前言
本期主要讲解食物列表的创建,主要分为底部Panel的创建和数字键盘的创建。
一、 底部面板的结构分析
如图所示:
二、 食物列表-底部Panel
2.1顶部日期
如图所示:
代码如下:
import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct ItemPanelHeader {
build() {
Row(){
Text('2024年1月25号 早餐')
.fontSize(18)
.fontWeight(CommonConstants.FONT_WEIGHT_600)
Image($r('app.media.ic_public_spinner'))
.width(20)
.fillColor(Color.Black)
}
}
}
2.2记录项卡片
如图所示:
代码如下:
import { CommonConstants } from '../../common/constants/CommonConstants'
import RecordItem from '../../viewmodel/RecordItem'
@Component
export default struct ItemCard {
@Prop amount: number//状态变量 Prop不能初始化
@Link item:RecordItem
build() {
Column({space:CommonConstants.SPACE_8}){
//1.图片
Image(this.item.image).width(150)
//2.名称
Row(){
Text(this.item.name) .fontWeight(CommonConstants.FONT_WEIGHT_700)//为了添加颜色 将其放入Row容器中
}
.backgroundColor($r('app.color.lightest_primary_color'))
.padding({top:5,bottom:5,left:12,right:12})
Divider()//下划线
.width(CommonConstants.THOUSANDTH_940)
.opacity(0.6)//透明度
//3.营养素
Row({space:CommonConstants.SPACE_8}){
this.NutrientInfo({label:'热量(千卡)',value:this.item.calorie})
if(this.item.id< 10000) {
this.NutrientInfo({label:'碳水(克)', value:this.item.carbon})
this.NutrientInfo({label:'蛋白质(克)', value:this.item.protein})
this.NutrientInfo({label:'脂肪(克)',value: this.item.fat})
}
}
Divider()//下划线
.width(CommonConstants.THOUSANDTH_940)
.opacity(0.6)//透明度
//4.数量
Row(){
Column({space:CommonConstants.SPACE_4}){
Text(this.amount.toFixed(1))//1位小数
.fontSize(50).fontColor($r('app.color.primary_color'))
.fontWeight(CommonConstants.FONT_WEIGHT_600)
Divider().color($r('app.color.primary_color'))
}
.width(150)
Text(this.item.unit)
.fontColor($r('app.color.primary_color'))
.fontWeight(CommonConstants.FONT_WEIGHT_600)
}
}
}
@Builder NutrientInfo($$:{label:string,value:number}){//其他传过来
Column({space:CommonConstants.SPACE_8}){
Text($$.label).fontSize(14).fontColor($r('app.color.light_gray'))
Text(($$.value+this.amount).toFixed(1))//一位小数
.fontSize(18).fontWeight(CommonConstants.FONT_WEIGHT_700)
}
}
}
三、食物列表-数字键盘
如图所示:
代码如下:
import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct NumberKeyboard {
numbers: string[]=['1','2','3','4','5','6','7','8','9','0','.']//why?
@Link amount:number//Link双向绑定
@Link value:string
@Styles keyBoxStyle(){
.backgroundColor(Color.White)
.borderRadius(8)//圆角
.height(60)
}
build() {
Grid(){
ForEach(this.numbers,num=>{
GridItem(){
Text(num).fontSize(20).fontWeight(CommonConstants.FONT_WEIGHT_900)
}
.keyBoxStyle()
.onClick(()=>this.clickNumber(num))
})
GridItem(){
Text('删除').fontSize(20).fontWeight(CommonConstants.FONT_WEIGHT_900)
}
.keyBoxStyle()
.onClick(()=>this.clickDelect())
}
.width('100%')
.height(280)
.backgroundColor($r('app.color.index_page_background'))
.columnsTemplate('1fr 1fr 1fr')//三列
.columnsGap(8)//列间距
.rowsGap(8)//行间距
.padding(8)//内边距
.margin({top:10})
}
//添加点击事件
clickNumber(num:string){
//1.拼接用户输入的内容
let val=this.value+num //旧的值加上新的值
//2.校验输入格式是否正确
let firstIndex =val.indexOf('.')//记录val里面的小数点 从前往后
let lastIndex =val.lastIndexOf('.')//从后往前
if(firstIndex !== lastIndex || (lastIndex!=-1 && lastIndex<val.length-2)){
//不相等(两个小数点); 有小数 小数点后面的位数不能超过两位
//非法输入
return
}
//3.将字符串转为数值
let amount=this.parseFloat(val)
//4.保存
if(amount>=999.9){
this.amount=999.0
this.value='999'
}else{
this.amount=amount
this.value=val
}
}
clickDelect(){
if(this.value.length<=0){
this.value=''
this.amount=0
return
}
this.value=this.value.substring(0,this.value.length-1)
this.amount=this.parseFloat(this.value)
}
//3.(1) 转换
parseFloat(str:string){
if(!str){
return 0;
}
if(str.endsWith('.')){//是否以'.'结尾
str=str.substring(0,str.length-1)//去除最后一位 从0开始去除 一直到长度减一
}
return parseFloat(str)
}
}
总结
- clickNumber方法处理用户点击数字或小数点的逻辑: 拼接用户输入的内容到value。
- 校验输入格式,确保只有一个小数点且小数点后不超过两位。
- 将字符串转换为数值,并保存到amount中。
- 如果输入超过999.9,则限制为999.0。
- clickDelect方法处理用户点击“删除”按钮的逻辑:
- 如果value为空,则重置value和amount为0。 否则,删除value的最后一个字符,并更新amount。