首页 > 其他分享 >期末实战——黑马健康3

期末实战——黑马健康3

时间:2024-06-20 13:32:19浏览次数:10  
标签:实战 color app CommonConstants value width amount 期末 黑马


文章目录


前言

综合运用本学期所学内容及个人自学知识,使用HarmonyOS 4.0及以上版本开发一款具有实用性和创新性的移动应用软件。


一、项目介绍

黑马健康是一款功能全面的健康管理应用,它通过提供个性化的饮食记录、健康评估等功能,帮助用户轻松管理健康,改善饮食和生活习惯。无论是需要减肥塑形,还是关注日常营养摄入,黑马健康都能为用户提供定制化的服务,让健康管理变得简单而有效。

二、应用运行

1.食物列表页

(1)页面整体分析

在这里插入图片描述

(2)代码如下(示例)

ItemIndex.ets

import router from '@ohos.router'
import { CommonConstants } from '../common/constants/CommonConstants'
import ItemCard from '../view/item/ItemCard'
import ItemList from '../view/item/ItemList'
import ItemPanelHeader from '../view/item/ItemPanelHeader'
import NumberKeyboard from '../view/item/NumberKeyboard'
@Entry
@Component
struct ItemIndex {
  @State amount:number=1//状态变量
  @State value:string=''//用户按键的内容记录在value内 amount最终结果
  @State showPanel:boolean=false//默认不展示

  onPanelShow(){
    this.amount=1//每次弹出,需要初始化为原始状态
    this.value=''//每次弹出,初始化为原始状态
    this.showPanel=true
  }

  build() {
    Column() {
      //1.头部导航
      this.Header()
      //2.列表
      ItemList({showPanel:this.onPanelShow.bind(this)})
      .layoutWeight(1)//除头部外 剩下都被列表占用 这样高度固定
      //3.底部面板
      /*Panel 可滑动面板,提供一种轻量的内容展示窗口,方便在不同尺寸中切换。
       需要传入布尔类型的参数 上方有一个状态变量*/
      Panel(this.showPanel){
        //3.1.顶部日期
        ItemPanelHeader()
        //3.2.记录顶卡片
        ItemCard({amount:this.amount})
        //3.3.数字键盘
        NumberKeyboard({amount:$amount,value:$value})

        //3.4.按钮
        Row({space:CommonConstants.SPACE_6}){
          Button('取消')
            .width(120)
            .backgroundColor($r('app.color.light_gray'))
            .type(ButtonType.Normal)
            .borderRadius(6)
            .onClick(()=>this.showPanel=false)//先关闭窗口
          Button('提交')
            .width(120)
            .backgroundColor($r('app.color.primary_color'))
            .type(ButtonType.Normal)
            .borderRadius(6)
            .onClick(()=>this.showPanel=false)//先关闭窗口
        }
        .margin({top:10})
      }
      .mode(PanelMode.Full)//mode是一个枚举 Full默认展现全部
      .dragBar(false)//不能调整高度
      .backgroundMask($r('app.color.light_gray'))//背后颜色
      .backgroundColor(Color.White)
    }
    .width('100%')
    .height('100%')
  }
  @Builder Header(){
    Row(){
        Image($r('app.media.ic_public_back'))
          .width(24)
          .onClick(() => router.back())
      Blank()
      Text('早餐').fontWeight(CommonConstants.FONT_WEIGHT_500)
    }
    .width(CommonConstants.THOUSANDTH_940)
    .height(32)
  }
}

ItemList .ets

import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct ItemList {//导出
  //函数 先无参无返回值 将来点击传入
  showPanel:()=>void

  build() {
    Tabs(){//Tabs本身就是个容器 Tab组件可以实现页面内视图内容快速切换,包含Tabar和TabContent两个部分
      TabContent() {
        this.TabContentBuilder()
      }
      .tabBar('全部')

      TabContent() {
        this.TabContentBuilder()
      }
      .tabBar('主食')

      TabContent() {
        this.TabContentBuilder()
      }
      .tabBar('肉蛋奶')
     }
    .width(CommonConstants.THOUSANDTH_940)
    .height('100%')
  }

  @Builder TabContentBuilder(){
    List({space:CommonConstants.SPACE_10}) {
      ForEach([1, 2, 3, 4, 5, 6], (item) => {
        ListItem() {
          Row({ space: CommonConstants.SPACE_4 }) {
            Image($r('app.media.toast')).width(50)
            Column({ space: CommonConstants.SPACE_4 }) {
              Text('全麦吐司').fontWeight(CommonConstants.FONT_WEIGHT_500)
              Text('91千卡/片').fontSize(14).fontColor($r('app.color.light_gray'))
            }

            Blank()
            Image($r('app.media.ic_public_add_norm_filled'))
              .width(18)
              .fillColor($r('app.color.primary_color'))
          }
          .width('100%')
          .padding(CommonConstants.SPACE_6)//内边距
        } //饮食不需要删除按钮
        .onClick(()=>this.showPanel())

      })
    }

    .width('100%')
    .height('100%')

  }
}

(3)运行效果截图

在这里插入图片描述

2.食物列表-底部Panel

(1)页面整体分析

在这里插入图片描述

(2)代码如下(示例)

ItemPanelHeader .ets

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)

    }
  }
}

ItemCard.ets

import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct ItemCard {
  @Prop amount: number//状态变量 Prop不能初始化

  build() {
    Column({space:CommonConstants.SPACE_8}){
      //1.图片
      Image($r('app.media.toast')).width(150)
      //2.名称
      Row(){
        Text('全麦吐司') .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('热量(千卡)',91.0)
        this.NutrientInfo('碳水(克)',15.5)
        this.NutrientInfo('蛋白质(克)',4.4)
        this.NutrientInfo('脂肪(克)',1.3)

      }
      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('片')
          .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)
    }
  }
}

(3)运行效果截图

在这里插入图片描述

3.食物列表-数字键盘

(1)页面整体分析

主要实现键盘部分
在这里插入图片描述

(2)代码如下(示例)

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)
  }
}

(3)运行效果截图

在这里插入图片描述


总结

知识补充

1.Panel

Panel: 可滑动面板,提供一种轻量的内容展示窗口,方便在不同尺寸中切 换。需要传入布尔类型的参数,控制Panel显示或隐藏。
说明:如果设置为false时,则不占位隐藏。Visible.None或者show之间有一个生效时,都会生效不占位隐藏。

2.Grid容器

Grid:网格容器,由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。
包含GridItem子组件。
olumnsTemplate ‘1fr 1fr 2fr’ 是将父组件分3列,将父组件允许的宽分为4等份,第一列占1份,第二列占1份,第三列占2份。
说明:设置为’0fr’时,该列的列宽为0,不显示GridItem。设置为其他非法值时,GridItem显示为固定1列。

问题优化

1.在ItemCard.ets中设置状态变量:@Prop amount:number
用Prop类型原因:
数量是一个动态值,所以定义为状态变量。并且此组件是用来渲染的组件,与键盘不在一个组件里,键盘负责修改,此处负责显示,因而用Prop接收。
2.食物列表页中TabContent代码优化,可将List封装到@Builder中

@Builder TabContentBuilder(){
    List({space:CommonConstants.SPACE_10}) {
      ForEach([1, 2, 3, 4, 5, 6], (item) => {
        ListItem() {
          Row({ space: CommonConstants.SPACE_4 }) {
            Image($r('app.media.toast')).width(50)
            Column({ space: CommonConstants.SPACE_4 }) {
              Text('全麦吐司').fontWeight(CommonConstants.FONT_WEIGHT_500)
              Text('1片').fontSize(14).fontColor($r('app.color.light_gray'))
            }

            Blank()
            Image($r('app.media.ic_public_add_norm_filled'))
              .width(18)
              .fillColor($r('app.color.primary_color'))
          }
          .width('100%')
          .padding(CommonConstants.SPACE_6)
        } //饮食不需要删除按钮


      })
    }

    .width('100%')
    .height('100%')

  }
}

3.数字键盘页面中,全部删除后显示NaN
在这里插入图片描述
将下面代码
在这里插入图片描述
修改为
在这里插入图片描述

标签:实战,color,app,CommonConstants,value,width,amount,期末,黑马
From: https://blog.csdn.net/2301_78375949/article/details/139765955

相关文章

  • 期末实战——黑马健康4
    黑马健康4——一次开发多端部署文章目录黑马健康4——一次开发多端部署前言一、项目介绍二、应用运行——一次开发多端部署1.页面整体分析——多设备响应式布局2.代码如下(示例)3.运行效果截图总结1.知识补充2.代码优化前言综合运用本学期所学内容及个人自......
  • HarmonyOS期末项目——作业清单(四)通用工具类
    系列文章目录HarmonyOS期末项目——作业清单(一)项目介绍和应用主页面设计https://blog.csdn.net/Ababx/article/details/139802283?spm=1001.2014.3001.5501HarmonyOS期末项目——作业清单(二)任务创建与编辑https://blog.csdn.net/Ababx/article/details/139807656?spm=1001.20......
  • 【算法与设计】期末总结
    文章目录第一章概述算法与程序时间复杂性求上界第二章递归与分治双递归函数——Ackerman函数分治策略大整数乘法两位×两位四位x四位三位x三位两位x六位第三章动态规划矩阵连乘基本要素最优子结构子问题重叠备忘录第四章贪心算法活动安排问题基本要素贪心选......
  • 用Automa做的抖音博主视频批量采集器升级版-实战原创
    文章目录前言一、抖音博主视频批量采集器升级版是什么?二、抖音博主视频批量采集器工作流流程图三、流程拆解1.第一步2.第二步3.第三步4.第四步5.第五步6.第六步总结前言Automa开发2年时间,开发应用100多款,分享开发记录市面上的抖音批量下载的工具非常多,用Automa......
  • Automa实现的Gmail个人邮箱批量发邮件-带定时功能-实战原创
    文章目录前言一、Gmail个人邮箱批量发邮件是什么?二、操作演示1.工作流全貌2.数据读取3.创建空文件4.写入数据5.切换标签页6.定时功能总结高效办公新技能:使用Automa和Gmail实现定时邮件发送,提升效率!前言Gmail个人邮箱批量发邮件-自定义内容,这个插件之前做的是安......
  • 电路分析期末总结笔记上
    电流,电压定义及单位电流(Current)的定义是单位时间内通过导体横截面的电荷量。电压(Voltage),又称作电势差或电位差,是衡量单位电荷在静电场中由于电势不同而产生的能量差的物理量。 参考方向,关联参考概念U,I采用相同的参考方向,为正U,I采用不相同的参考方向,为负功率的计算......
  • C语言期末复习笔记
    目录一,基础介绍。二,标识符起名规范。三,数据类型。四,变量。五,运算符和表达式1,加减乘除​编辑  /为整除,%为余数,*为乘号2,关系运算符3,逻辑运算符4,运算符优先级5,前自增,后自增6,三目运算符。7,符合运算符。六,控制语句。1,if判断2,多重判断。3,for循环4,while循环5,d......
  • python金融实战教程pdf 目录
    python金融实战教程pdf目录:http://literalink.top/resource/detail/7186336410574524416第1章Python简介及安装11.1Python简介 11.2如何安装Python 31.3Python的不同版本 31.4运行Python的3种方式 41.4.1用GUI启动Python 41.4.2从Python命令行......
  • 【第19章】Vue实战篇之主页面
    文章目录前言一、代码1.主界面代码2.App.vue二、展示总结前言登录完成之后,应该自动跳转到主页面,接下来我们搭建主界面。一、代码1.主界面代码<scriptsetup>import{Management,Promotion,UserFilled,User,Crop,EditPen,......
  • 【第20章】Vue实战篇之Vue Router(路由)
    文章目录前言一、使用Vue-Router1.安装2.创建路由器实例3.注册路由器插件4.根组件二、访问路由器1.理论2.使用3.展示三、嵌套路由(子路由)1.准备文件2.配置路由3.菜单配置4.展示总结前言VueRouter是Vue.js的官方路由。它与Vue.js核心深度集成,让用......