目录
前言
综合运用本学期所学内容及个人自学知识,使用HarmonyOS 4.0及以上版本开发一款具有实用性和创新 性的移动应用软件。
一、项目目标
综合运用本学期所学内容及个人自学知识,使用HarmonyOS 4.0及以上版本开发一款具有实用性和创新 性的移动应用软件。
二、项目介绍
黑马健康是一款功能全面的健康管理应用,它通过提供个性化的饮食记录、健康评估等功能,帮助用户轻松管理健康,改善饮食和生活习惯。无论是需要减肥塑形,还是关注日常营养摄入,黑马健康都能为用户提供定制化的服务,让健康管理变得简单而有效。
三、具体页面实现
1.首页Tabs
(1)页面分析:
整个首页是使用一个Tabs组件进行构建,Tabs组件可以实现页面内试图内容快速切换,包含TabBar和Tabcontent两个部分。
Tabs组件可以实现页面内视图内容快速切换,包含TabBar和TabContent两部分。
该app共有三个页面,分别为饮食记录页面,发现页面和我的页面,所以需要在Tabs组件中设置三个Tabcontent与TabBar(主要介绍饮食记录页面)
(2)页面实现代码:
import BreakpointType from '../common/bean/BreanpointType'
import { CommonConstants } from '../common/constants/CommonConstants'
import BreakpointSystem from '../common/utils/BreakpointSystem'
import RecordIndex from '../view/record/RecordIndex'
@Entry
@Component
struct Index {
@State currentIndex:number = 0
private breakpointSystem:BreakpointSystem = new BreakpointSystem()
@StorageProp('currentBreakpoint') currentBreakpoint:string= 'sm'
@Builder TabBarBuilder(title:ResourceStr, image:ResourceStr,index:number){
Column({space:CommonConstants.SPACE_8}){
Image(image)
.width(22)
.fillColor(this.selectColor(index))
Text(title)
.fontSize(14)
.fontColor(this.selectColor(index))
}
}
aboutToAppear(){
this.breakpointSystem.register()
}
aboutToDisappear(){
this.breakpointSystem.unregister()
}
selectColor(index:number){
return this.currentIndex === index ? $r('app.color.primary_color') : $r('app.color.gray')
}
chooseBarPosition(){
let p = {
sm:BarPosition.End,
md:BarPosition.Start,
lg:BarPosition.Start
}
return p[this.currentBreakpoint]
}
build() {
Tabs({barPosition:this.chooseBarPosition()}) {
TabContent(){
RecordIndex()
}
.tabBar(this.TabBarBuilder($r('app.string.tab_record'),$r('app.media.ic_calendar'),0))
TabContent(){
Text('发现页面')
}
.tabBar(this.TabBarBuilder($r('app.string.tab_discover'),$r('app.media.discover'),1))
TabContent(){
Text('我的页面')
}
.tabBar(this.TabBarBuilder($r('app.string.tab_user'),$r('app.media.ic_user_portrait'),2))
}
.width('100%')
.height('100%')
.onChange(index => this.currentIndex = index)
.vertical(new BreakpointType({
sm:false,
md:true,
lg:true
}).getValue(this.currentBreakpoint))
}
}
(3)运行效果:
2.饮食部分UI设计-顶部导航栏
(1)页面分析:
该页面顶部是一个搜索栏,创建单独组件SearchHeader,表示头部搜索栏。
(2)页面实现代码:
import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct SearchHeader {
build() {
Row({space:CommonConstants.SPACE_6}){
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)
}
}
(3)运行效果:
3.统计卡片设计
(1)页面分析:
统计卡片分为两部分,包括日期、统计卡路里卡片,用row容器存储
卡片使用DatePicker日期选择组件,用于根据指定日期范围创建日期滑动选择器;使用Swiper滑块视图容器,提供子组件滑动轮播显示的能力。
(2)页面实现代码:
NutrientStats.ets
import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct NutrientStats {
carbon:number= 20
protein:number= 30
fat:number = 40
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(90)
.style({strokeWidth:CommonConstants.DEFAULT_6})
.color(color)
Column({space:CommonConstants.SPACE_4}){
Text('摄入推荐')
.fontSize(14)
.fontColor($r('app.color.gray'))
Text(`${value.toFixed(0)}/${recommend.toFixed(0)}`)
.fontSize(18)
.fontWeight(CommonConstants.FONT_WEIGHT_700)
}
}
Text(`${label} (克) `)
.fontSize(12)
.fontColor($r('app.color.light_gray'))
}
}
}
DatePickDialog.ets
import { CommonConstants } from '../../common/constants/CommonConstants'
@Preview
@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)
})
// 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)
}
}
CalorieStats.ets
import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct CalorieStats {
intake:number = 192
expend:number = 120
recommend:number = CommonConstants.RECOMMEND_CALORIE
remainCalorie(){
return this.recommend-this.intake+this.expend
}
build() {
Row({space:CommonConstants.SPACE_6}){
//饮食摄入
this.statsBuilder('饮食摄入',this.intake)
//还能吃
Stack(){
//进度条
Progress({
value:this.recommend-this.remainCalorie(),
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两个新的组件进行信息展示