期末项目黑马健康4

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

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


提示:以下是本篇文章正文内容,下面案例可供参考

一、项目名称:黑马健康运动

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、应用运行过程4

1.一次开发多端部署

运行截图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码如下:
BreakpointConstants.ets

import BreakpointType from '../bean/BreanpointType';
export default class BreakpointConstants {
  /**
   * 小屏幕设备的 Breakpoints 标记.
   */
  static readonly BREAKPOINT_SM: string = 'sm';

  /**
   * 中等屏幕设备的 Breakpoints 标记.
   */
  static readonly BREAKPOINT_MD: string = 'md';

  /**
   * 大屏幕设备的 Breakpoints 标记.
   */
  static readonly BREAKPOINT_LG: string = 'lg';

  /**
   * 当前设备的 breakpoints 存储key
   */
  static readonly CURRENT_BREAKPOINT: string = 'currentBreakpoint';

  /**
   * 小屏幕设备宽度范围.
   */
  static readonly RANGE_SM: string = '(320vp<=width<600vp)';

  /**
   * 中屏幕设备宽度范围.
   */
  static readonly RANGE_MD: string = '(600vp<=width<840vp)';

  /**
   * 大屏幕设备宽度范围.
   */
  static readonly RANGE_LG: string = '(840vp<=width)';

  static readonly BAR_POSITION: BreakpointType<BarPosition> = new BreakpointType({
    sm: BarPosition.End,
    md: BarPosition.Start,
    lg: BarPosition.Start,
  })
}

BreakpointSystem.ets
代码如下:

import mediaQuery from '@ohos.mediaquery'
import BreakpointConstants from '../constants/BreakpointConstants'

export default class BreakpointSystem{

  private smListener: mediaQuery.MediaQueryListener = mediaQuery.matchMediaSync(BreakpointConstants.RANGE_SM)
  private mdListener: mediaQuery.MediaQueryListener = mediaQuery.matchMediaSync(BreakpointConstants.RANGE_MD)
  private lgListener: mediaQuery.MediaQueryListener = mediaQuery.matchMediaSync(BreakpointConstants.RANGE_LG)

  smListenerCallback(result: mediaQuery.MediaQueryResult){//给监听器绑定回调函数
    if(result.matches){//是否匹配
      this.updateCurrentBreakpoint(BreakpointConstants.BREAKPOINT_SM)
    }
  }

  mdListenerCallback(result: mediaQuery.MediaQueryResult){
    if(result.matches){
      this.updateCurrentBreakpoint(BreakpointConstants.BREAKPOINT_MD)
    }
  }

  lgListenerCallback(result: mediaQuery.MediaQueryResult){
    if(result.matches){
      this.updateCurrentBreakpoint(BreakpointConstants.BREAKPOINT_LG)
    }
  }

  updateCurrentBreakpoint(breakpoint: string){
    AppStorage.SetOrCreate(BreakpointConstants.CURRENT_BREAKPOINT, breakpoint)
  }

  register(){//注册回调函数
    this.smListener.on('change', this.smListenerCallback.bind(this))
    this.mdListener.on('change', this.mdListenerCallback.bind(this))
    this.lgListener.on('change', this.lgListenerCallback.bind(this))
  }

  unregister(){//取消监听
    this.smListener.off('change', this.smListenerCallback.bind(this))
    this.mdListener.off('change', this.mdListenerCallback.bind(this))
    this.lgListener.off('change', this.lgListenerCallback.bind(this))
  }
}

2.数据模型记录项

记录项 饮食或运动
记录项类型:类型id,类型名称
饮食记录中的记录项,可以是食物或运动:id;名称name;图片image;分类id categoryId;单位unit;包含的卡路里;碳水含量;蛋白质含量;脂肪含量

运行截图:
在这里插入图片描述
ItemModel.ets
代码如下:


import GroupInfo from '../viewmodel/GroupInfo'
import RecordItem from '../viewmodel/RecordItem'
import { FoodCategories, FoodCategoryEnum, WorkoutCategories, WorkoutCategoryEnum } from './ItemCategoryModel'
const foods: RecordItem[] = [
  new RecordItem(0,'米饭',$r('app.media.rice'),FoodCategoryEnum.STAPLE,'碗',209,46.6,4.7,0.5),
  new RecordItem(1,'馒头',$r('app.media.steamed_bun'),FoodCategoryEnum.STAPLE,'个',114,24.0,3.6,0.6),
  new RecordItem(2,'面包',$r('app.media.bun'),FoodCategoryEnum.STAPLE,'个',188,35.2,5.0,3.1),
  new RecordItem(3,'全麦吐司',$r('app.media.toast'),FoodCategoryEnum.STAPLE,'片',91,15.5,4.4,1.3),
  new RecordItem(4,'紫薯',$r('app.media.purple_potato'),FoodCategoryEnum.STAPLE,'个',163,42.0,1.6,0.4),
  new RecordItem(5,'煮玉米',$r('app.media.corn'),FoodCategoryEnum.STAPLE,'根',111,22.6,4.0,1.2),
  new RecordItem(6,'黄瓜',$r('app.media.cucumber'),FoodCategoryEnum.FRUIT,'根',29,5.3,1.5,0.4),
  new RecordItem(7,'蓝莓',$r('app.media.blueberry'),FoodCategoryEnum.FRUIT,'盒',71,18.1,0.9,0.4),
  new RecordItem(8,'草莓',$r('app.media.strawberry'),FoodCategoryEnum.FRUIT,'颗',14,3.1,0.4,0.1),
  new RecordItem(9,'奇异果',$r('app.media.kiwi'),FoodCategoryEnum.FRUIT,'个',25,8.4,0.5,0.3),
  new RecordItem(10,'煮鸡蛋',$r('app.media.egg'),FoodCategoryEnum.MEAT,'个',74,0.1,6.2,5.4),
  new RecordItem(11,'煮鸡胸肉',$r('app.media.chicken_breast'),FoodCategoryEnum.MEAT,'克',1.15,0.011,0.236,0.092),
  new RecordItem(12,'煮鸡腿肉',$r('app.media.chicken_leg'),FoodCategoryEnum.MEAT,'克',1.87,0.0,0.243,0.092),
  new RecordItem(13,'牛肉',$r('app.media.beef'),FoodCategoryEnum.MEAT,'克',1.22,0.0,0.23,0.033),
  new RecordItem(14,'鱼肉',$r('app.media.fish'),FoodCategoryEnum.MEAT,'克',1.04,0.0,0.206,0.024),
  new RecordItem(15,'牛奶',$r('app.media.milk'),FoodCategoryEnum.MEAT,'毫升',0.66,0.05,0.03,0.038),
  new RecordItem(16,'酸奶',$r('app.media.yogurt'),FoodCategoryEnum.MEAT,'毫升',0.7,0.10,0.032,0.019),
  new RecordItem(17,'核桃',$r('app.media.walnut'),FoodCategoryEnum.NUT,'颗',42,1.2,1.0,3.8),
  new RecordItem(18,'花生',$r('app.media.peanut'),FoodCategoryEnum.NUT,'克',3.13,0.13,0.12,0.254),
  new RecordItem(19,'腰果',$r('app.media.cashew'),FoodCategoryEnum.NUT,'克',5.59,0.416,0.173,0.367),
  new RecordItem(20,'无糖拿铁',$r('app.media.coffee'),FoodCategoryEnum.OTHER,'毫升',0.43,0.044,0.013,0.01),
  new RecordItem(21,'豆浆',$r('app.media.soybean_milk'),FoodCategoryEnum.OTHER,'毫升',0.31,0.01,0.013,0.01),
]

const workouts: RecordItem[] = [
  new RecordItem(10000,'散步',$r('app.media.ic_walk'),WorkoutCategoryEnum.WALKING,'小时',111),
  new RecordItem(10001,'快走',$r('app.media.ic_walk'),WorkoutCategoryEnum.WALKING,'小时',343),
  new RecordItem(10002,'慢跑',$r('app.media.ic_running'),WorkoutCategoryEnum.RUNNING,'小时',472),
  new RecordItem(10003,'快跑',$r('app.media.ic_running'),WorkoutCategoryEnum.RUNNING,'小时',652),
  new RecordItem(10004,'自行车',$r('app.media.ic_ridding'),WorkoutCategoryEnum.RIDING,'小时',497),
  new RecordItem(10005,'动感单车',$r('app.media.ic_ridding'),WorkoutCategoryEnum.RIDING,'小时',587),
  new RecordItem(10006,'瑜伽',$r('app.media.ic_aerobics'),WorkoutCategoryEnum.AEROBICS,'小时',172),
  new RecordItem(10007,'健身操',$r('app.media.ic_aerobics'),WorkoutCategoryEnum.AEROBICS,'小时',429),
  new RecordItem(10008,'游泳',$r('app.media.ic_swimming'),WorkoutCategoryEnum.SWIMMING,'小时',472),
  new RecordItem(10009,'冲浪',$r('app.media.ic_swimming'),WorkoutCategoryEnum.SWIMMING,'小时',429),
  new RecordItem(10010,'篮球',$r('app.media.ic_basketball'),WorkoutCategoryEnum.BALLGAME,'小时',473),
  new RecordItem(10011,'足球',$r('app.media.ic_football'),WorkoutCategoryEnum.BALLGAME,'小时',515),
  new RecordItem(10012,'排球',$r('app.media.ic_volleyball'),WorkoutCategoryEnum.BALLGAME,'小时',403),
  new RecordItem(10013,'羽毛球',$r('app.media.ic_badminton'),WorkoutCategoryEnum.BALLGAME,'小时',385),
  new RecordItem(10014,'乒乓球',$r('app.media.ic_table_tennis'),WorkoutCategoryEnum.BALLGAME,'小时',366),
  new RecordItem(10015,'哑铃飞鸟',$r('app.media.ic_dumbbell'),WorkoutCategoryEnum.STRENGTH,'小时',388),
  new RecordItem(10016,'哑铃卧推',$r('app.media.ic_dumbbell'),WorkoutCategoryEnum.STRENGTH,'小时',422),
  new RecordItem(10017,'仰卧起坐',$r('app.media.ic_sit_up'),WorkoutCategoryEnum.STRENGTH,'小时',515),
]

class ItemModel{

  getById(id: number, isFood: boolean = true){
    return isFood ? foods[id] :workouts[id - 10000]
  }

  list(isFood: boolean = true): RecordItem[]{
    return isFood ? foods:workouts
  }
  listItemGroupByCategory(isFood: boolean = true){
    //1.判断要处理的是食物还是运动
    let categories = isFood ? FoodCategories : WorkoutCategories
    let items = isFood ? foods: workouts
    //2.创建空的分组
    let groups = categories.map(itemCategory => new GroupInfo(itemCategory,[]))//映射,遍历前面数组的每一个元素,把当前元素转换成另一种元素
    //3.遍历食记录项列表,将食物添加到对应的分组
    items.forEach(item => groups[item.categoryId].items.push(item))
    //4.返回结果
    return groups

  }
}

let itemModel = new ItemModel()

export default itemModel as ItemModel

ItemList.ets
代码如下:

import { CommonConstants } from '../../common/constants/CommonConstants'
import ItemModel from '../../model/ItemModel'
import GroupInfo from '../../viewmodel/GroupInfo'
import ItemCategory from '../../viewmodel/ItemCategory'
import RecordItem from '../../viewmodel/RecordItem'
@Component
export default struct ItemList {

  showPanel:(item: RecordItem) => void
  @Prop isFood: boolean

  build() {
    Tabs(){
      TabContent(){
        this.TabContentBuilder(ItemModel.list(this.isFood))
      }
      .tabBar('全部')

      ForEach(
        ItemModel.listItemGroupByCategory(this.isFood),
        (group:GroupInfo<ItemCategory, RecordItem>) =>{
          TabContent(){
            this.TabContentBuilder(group.items)
          }
          .tabBar(group.type.name)
        })
    }
    .width(CommonConstants.THOUSANDTH_940)
    .height('100%')
    .barMode(BarMode.Scrollable)
  }

  @Builder TabContentBuilder(items: RecordItem[]){
    List({space:CommonConstants.SPACE_10}){
      ForEach(items,(item: RecordItem) => {
        ListItem(){
          Row({space:CommonConstants.SPACE_6}){
            Image(item.image).width(50)
            Column({space:CommonConstants.SPACE_4}){
              Text(item.name).fontWeight(CommonConstants.FONT_WEIGHT_500)
              Text(`${item.calorie}千卡/${item.unit}`).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(item))

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

3.数据模型—饮食记录

RecordModel.ets
代码如下:


import relationalStore from '@ohos.data.relationalStore'
import { ColumnInfo, ColumnType } from '../common/bean/ColumnInfo'
import RecordPO from '../common/bean/RecordPO'
import DbUtil from '../common/utils/DbUtil'
/**
 * 数据库建表语句
 */
const CREATE_TABLE_SQL: string = `
  CREATE TABLE IF NOT EXISTS record (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    type_id INTEGER NOT NULL,
    item_id INTEGER NOT NULL,
    amount DOUBLE NOT NULL,
    create_time INTEGER NOT NULL
  )
`
const COLUMNS: ColumnInfo[] = [
  {name: 'id', columnName: 'id', type: ColumnType.LONG},
  {name: 'typeId', columnName: 'type_id', type: ColumnType.LONG},
  {name: 'itemId', columnName: 'item_id', type: ColumnType.LONG},
  {name: 'amount', columnName: 'amount', type: ColumnType.DOUBLE},
  {name: 'createTime', columnName: 'create_time', type: ColumnType.LONG},
]

const TABLE_NAME = 'record'
const ID_COLUMN = 'id'
const DATE_COLUMN = 'create_time'

class RecordModel {
  getCreateTableSql(): string {
    return CREATE_TABLE_SQL
  }

  insert(record: RecordPO){
    return DbUtil.insert(TABLE_NAME, record, COLUMNS)
  }

  deleteById(id: number){
    //1.删除条件
    let predicates = new relationalStore.RdbPredicates(TABLE_NAME)
    predicates.equalTo(ID_COLUMN, id)
    //2.删除
    return DbUtil.delete(predicates)
  }

  listByDate(date: number){
    //1.查询条件
    let predicates = new relationalStore.RdbPredicates(TABLE_NAME)
    predicates.equalTo(DATE_COLUMN, date)
    //2.查询
    return DbUtil.queryForList(predicates, COLUMNS)
  }
}

let  recordModel = new RecordModel()

export default recordModel as RecordModel

总结

1.一次性开发多端部署

多设备响应式布局,在渲染页面时,利用媒体查询技术动态判断当前屏幕设备大小,根据屏幕大 小不同,来渲染出不同的布局效果。

媒体查询技术:1.导入媒体查询模块 import mediaQuery from ‘@ohos.mediaquery’
2.设置媒体查询条件,并且获取对应的listener
let listener = mediaQuery.matchMediaSync(‘(320vp<=width<600vp)’)
调用方法matchMediaSync,传入媒体查询条件
媒体查询语法规则:媒体类型(screen)、媒体逻辑操作和媒体特征(宽度、高度、屏幕方向…)
3.给listener设置回调函数,当设备状态变化时会执行回调函数
//设置监听回调函数
listener.on(‘change’, result =>{
//判断是否满足媒体查询条件
if(result.matches){
//记录当前设备状态
}
})
4.将设备状态记录到全局状态中
//全局存储
AppStorage.SetOrCreate(‘currentBreakpoint’, ‘SM’)//断点
@StorageProp(‘currentBreakpoint’) currentBreakpoint: String = ‘SM’//用装饰器获取值,所以可以判断。

2.数据模型—记录项

ItemCategory.ets
代码如下:

/**
 * 记录项类型
 */
export default class ItemCategory{
  /**
   * 类型id
   */
  id: number
  /**
   * 类型名称
   */
  name: ResourceStr

  constructor(id: number, name: ResourceStr) {
    this.id = id
    this.name = name
  }
}

RecordItem.ets
代码如下:

/**
 * 饮食记录中的记录项,可以是食物或运动
 */
export default class RecordItem{
  /**
   * id
   */
  id: number
  /**
   * 名称
   */
  name: ResourceStr
  /**
   * 图片
   */
  image: ResourceStr
  /**
   * 分类id
   */
  categoryId: number
  /**
   * 包含的卡路里
   */
  calorie: number
  /**
   * 单位
   */
  unit: ResourceStr
  /**
   * 碳水含量,单位(克)
   */
  carbon: number
  /**
   * 蛋白质含量,单位(克)
   */
  protein: number
  /**
   * 脂肪含量,单位(克)
   */
  fat: number

  constructor(id: number, name: ResourceStr, image: ResourceStr,
              categoryId: number, unit: ResourceStr, calorie: number,
              carbon: number = 0, protein: number = 0, fat: number = 0) {
    this.id = id
    this.name = name
    this.image = image
    this.categoryId = categoryId
    this.unit = unit
    this.calorie = calorie
    this.protein = protein
    this.fat = fat
    this.carbon = carbon
  }
}

3.数据模型—饮食记录

数据模型代码:

export default class RecordType{
  /**
   * 类型id
   */
  id: number
  /**
   * 类型名称
   */
  name: ResourceStr
  /**
   * 类型图标
   */
  icon: ResourceStr
  /**
   * 类型推荐最小卡路里
   */
  min: number
  /**
   * 类型推荐最大卡路里
   */
  max: number

  constructor(id: number, name: ResourceStr, icon: ResourceStr, min: number = 0, max: number = 0) {
    this.id = id
    this.name = name
    this.icon = icon
    this.min = min
    this.max = max
  }
}

在这里插入图片描述
RecordVO.ets
代码如下:

import RecordItem from './RecordItem'
/**
 * 饮食记录的页面数据模型
 */
export default class RecordVO {
  /**
   * 记录id
   */
  id: number
  /**
   * 饮食记录类型
   */
  typeId: number
  /**
   * 卡路里总数
   */
  calorie: number
  /**
   * 记录中的食物或运动信息
   */
  recordItem: RecordItem
  /**
   * 食物数量或运动时长,如果是运动信息则无
   */
  amount: number = 0
}

RecordTypeModel.ets

import RecordType from '../viewmodel/RecordType'
enum RecordTypeEnum {
  /**
   * 早餐
   */
  BREAKFAST,
  /**
   * 午餐
   */
  LUNCH,
  /**
   * 晚餐
   */
  DINNER,
  /**
   * 加餐
   */
  EXTRA_MEAL,
  /**
   * 运动
   */
  WORKOUT
}

/**
 * 记录类型常量
 */
const RecordTypes: RecordType[] = [
  new RecordType(0,$r("app.string.breakfast"),$r("app.media.ic_breakfast"), 423, 592),
  new RecordType(1,$r("app.string.lunch"),$r("app.media.ic_lunch"), 592, 761),
  new RecordType(2,$r("app.string.dinner"),$r("app.media.ic_dinner"), 423, 592),
  new RecordType(3,$r("app.string.extra_meal"),$r("app.media.ic_extra_m"), 0, 169),
  new RecordType(4,$r("app.string.workout"),$r("app.media.ic_workout")),
]

export {RecordTypes,RecordTypeEnum}
  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值