当前位置: 代码网 > it编程>App开发>Android > 鸿蒙期末个人项目“黑马健康”——项目阶段三:饮食记录

鸿蒙期末个人项目“黑马健康”——项目阶段三:饮食记录

2024年08月03日 Android 我要评论
黑马健康软件是一款基于全民健康的软件,主要有三个页面组成,分别是欢迎页面,统计记录页面,食物列表页面。

目录

项目介绍:

页面布局:

分析:

步骤:

               饮食记录-顶部搜索栏:饮食记录ui设计

               饮食记录-统计卡片:饮食记录ui设计

                 饮食记录-记录列表:饮食记录ui设计

页面实现效果:

出现的问题与解决:

问题1:

问题2:

问题3:

阶段项目代码:

 饮食记录-顶部搜索栏代码:饮食记录

   饮食记录-统计卡片代码:饮食记录

   饮食记录-记录列表代码:饮食记录


项目介绍:

        黑马健康软件是一款基于全民健康的软件,主要有三个页面组成,分别是欢迎页面,统计记录页面,食物列表页面。

页面布局:

分析:

  •                 总体是列式布局,内部是行式布局;
  •                 最上面的文本输入框是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)
  }
}

参考黑马课堂老师的讲解,欢迎批评和指正。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com