鸿蒙实战案例——黑马健康(3)


前言

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

一、项目介绍

黑马健康App是一款功能全面的健康管理应用,黑马健康App通过提供个性化的饮食记录、健康评估等功能,帮助用户轻松管理健康,改善饮食和生活习惯。 还提供个性化的推荐服务,确保用户能够获得最适合自己的健康和运动建议。总的来说,黑马健康App是一款功能全面、注重个性化推荐的健康管理应用,旨在为用户提供一站式的健康和运动解决方案。

二、具体页面实现

1.饮食记录页面--统计卡片

1.整体页面分析

这里也是将统计卡片写成一个@Component自定义组件,统计卡片主要分为两个模块,一个是顶部的日期信息,另一个为下方的一个可滑动切换的页面,两者均用row行容器存放

首先顶部的日期是定义了一个@customdialog弹窗,通过点击事件来触发弹窗,在弹窗里面使用了一种新的组件--日期选择器组件DatePicker用于根据指定日期范围创建日期滑动选择器。

 DatePicker({
        start: new Date('2020-01-01'),
        end: new Date(),
        selected: this.selectedDate
      })

下方的可滑动页面也是一种之前未了解的组件Swiper:滑块视图容器,提供子组件滑动轮播显示的能力。这里将两个子页面都定义成自定义组件CalorieStats()与NutrientStats(),然后在Swiper组件中调用并将统计信息显示出来

 Swiper(){
       // 热量统计

       CalorieStats()
       // 营养素统计
       NutrientStats()

     }
 

这两个子页面的布局基本一致,都是在一个大的Row容器中放置几个column容器,进度圆环组件为progress组件

  Progress({
          value: this.intake,
          total: this.recommend,
          type: ProgressType.Ring
        })

这里要注意的是每一个进度圆环里面还有文字信息,这里需要用到Stack堆叠容器,将文字信息与圆环形成层叠关系。

  Stack(){    //层叠关系
          // 进度条
        Progress({
          value: this.intake,
          total: this.recommend,
          type: ProgressType.Ring
        })
          Text('文字')
      }

2.代码

NutrientStats.ets

import DateUtil from '../../common/utils/DateUtil'
import DatePickDialog from './DatePickDialog'
import CalorieStats from './CalorieStats'
import NutrientStats from './NutrientStats'
import BreakpointType from '../../common/bean/BreanpointType'
import BreakpointConstants from '../../common/constants/BreakpointConstants'
@Component

export default struct StatsCard {
  @StorageProp('currentBreakpoint') currentBreakpoint: string = BreakpointConstants.BREAKPOINT_SM
  @StorageProp('selectedDate') selectedDate:number= DateUtil.beginTimeOfDay(new Date())
    controller:CustomDialogController= new CustomDialogController({
    builder:DatePickDialog({selectedDate:new Date(this.selectedDate)})
  })
  build() {
    Column(){
  //日期信息
      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'))
      }
      .width('94%')
      .padding(8)
      .onClick(()=>this.controller.open())
//统计信息
     Swiper(){
       // 热量统计

       CalorieStats()
       // 营养素统计
       NutrientStats()

     }
      .width('100%')
     .backgroundColor(Color.White)
      .borderRadius(18)
      .indicatorStyle({selectedColor:$r('app.color.primary_color')})
     .displayCount(new BreakpointType({
       sm: 1,
       md: 1,
       lg: 2
     }).getValue(this.currentBreakpoint))



    }
      .width('94%')
  
      .backgroundColor($r('app.color.stats_title_bgc'))
      .borderRadius(18)

  }
}

DatePickDialog.ets

@CustomDialog
export default struct DatePickDialog {
  controller: CustomDialogController
  selectedDate: Date = new Date()

  build() {
    Column({space:12}) {
      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)

        })
       Row({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(()=>{
             //保存日期到全局存储
             AppStorage.SetOrCreate('selectedDate',this.selectedDate.getTime())
             //关闭
             this.controller.close()
           })
}
    }
    .padding(12)

  }
}

NutrientStats.ets

import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export  default struct NutrientStats {

  carbon :number=24
  protein:number=10
  fat:number=5

  recommendCarbon :number=CommonConstants.RECOMMEND_CARBON
  recommendProtein :number=CommonConstants.RECOMMEND_PROTEIN
  recommendFat :number=CommonConstants.RECOMMEND_FAT

  build() {
    Row({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.carbon,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:ResourceColor){
    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:6}){
          Text('摄入推荐')
            .fontColor($r('app.color.gray'))
            .fontSize(12)
          Text(`${value.toFixed(0)}/${recommend.toFixed(0)}`)
            .fontSize(18)
            .fontWeight(CommonConstants.FONT_WEIGHT_600)
        }

      }
     Text(`${label} (克)`)
       .fontSize(12)
       .fontColor($r('app.color.light_gray'))

    }
    }
  }

CalorieStats.ets

import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
 export  default struct CalorieStats {
  intake:number=222
  expend:number=323
  recommend:number= CommonConstants.RECOMMEND_CALORIE
  remainCalorie(){
    return this.recommend - this.intake + this.expend
  }
  build() {
    Row({space:6}){
           // 饮食摄入
          this.StatsBuilder('饮食摄入',this.intake)
         // 还可以吃
      Stack(){    //层叠关系
          // 进度条
        Progress({
          value: this.intake,
          total: this.recommend,
          type: ProgressType.Ring
        })

          .width(120)
          .style({strokeWidth: CommonConstants.DEFAULT_10})
          .color($r('app.color.primary_color'))
        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'))
      }
    }
  }

}

3.运行结果截图


总结

通过这次视频学习了DatePicker和Swiper两个新的组件,学会了对应用程序的一些统计信息进行展示。

  • 39
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下为B站黑马JavaScript的Ajax案例代码——图书管理案例搜索事件: ```javascript /** * 搜索事件 */ function searchBook() { // 获取搜索框内容 var searchInput = document.querySelector("#searchInput"); var keywords = searchInput.value.trim(); // 如果搜索框内容为空,提示用户 if (keywords == "") { alert("请输入关键字进行搜索!"); return; } // 发送Ajax请求 var xhr = new XMLHttpRequest(); // 创建XmlHttpRequest对象 xhr.open("GET", "/api/book/search?keywords=" + keywords, true); // 配置请求 xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { // 处理响应数据 var books = JSON.parse(xhr.responseText); // 将响应数据转成JavaScript对象 renderBooks(books); // 渲染图书列表 } }; xhr.send(null); // 发送请求 } /** * 渲染图书列表 * @param {*} books 图书列表数据 */ function renderBooks(books) { // 获取图书列表容器 var bookList = document.querySelector("#bookList"); var html = ""; if (books.length > 0) { // 遍历图书列表数据,生成HTML字符串 for (var i = 0; i < books.length; i++) { html += '<tr>'; html += '<td>' + books[i].title + '</td>'; html += '<td>' + books[i].author + '</td>'; html += '<td>' + books[i].category + '</td>'; html += '<td>' + books[i].price + '</td>'; html += '<td>' + books[i].publisher + '</td>'; html += '</tr>'; } } else { // 如果没有搜索到任何图书,提示用户 html = '<tr><td colspan="5">没有搜索到任何图书!</td></tr>'; } // 将生成的HTML字符串添加进图书列表容器 bookList.innerHTML = html; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值