目录
项目介绍:
黑马健康软件是一款基于全民健康的软件,主要有三个页面组成,分别是欢迎页面,统计记录页面,食物列表页面。
分析:
利用mediaQuery设置媒体的查询条件,设置对屏幕宽度做查询,根据屏幕的不同宽度的不同范围,划分大值的区分范围来区别设备,每个范围指定一个对应的字符串状态,分别是:sm、md、lg。之后给设备查询的监听器设置回调函数,当媒体状态发生变更时,三个设备的监听器便会被触发,通过回调函数改变状态,作为设备标记保存在AppStorage中。之后页面变回利用@StorageProp读取当前设备标记,之后页面组件的属性中就可以通过设备标记来实现不同设备的渲染,达到响应式布局的效果。
页面实现效果:
手机设备的实现效果:
折叠手机的实现效果
平板的实现效果:
重点实现:
1.为了优雅的去传值,不用下面所述的这种声明对象方式
//根据设备选择导航的布局
// chooseBarPosition(){
// //定义对象,根据对象名key来返回值
// return new BreakpointType({
// sm:BarPosition.End,
// md:BarPosition.Start,
// lg:BarPosition.Start
// }).getValue(this.currentBreakpoint)
// // let p = {
// // sm: BarPosition.End,
// // md:BarPosition.Start,
// // lg:BarPosition.Start
// // }
// // return p[this.currentBreakpoint]
//
// }
定义一个封装接口,这个接口的类型和里面参数的类型都是泛型,因为后续的属性中的定义有的是传递这个属性中的对象的属性,有的是传递的布尔类型的值等等,并且防止有的不用传值的情况,这里的参数是可传可不传的泛型类型。
2.仿照上述页面渲染的方法,将平板的Swiper组件的穿梭框样式隐藏:
效果展示:
阶段项目代码:
/**
* 首页开发
*/
import BreakpointType from '../common/bean/BreanpointType'
import BreakpointConstants from '../common/constants/BreakpointConstants'
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()
//TODO 这个装饰器是啥 定义当前的设备并初始化
@StorageProp('currentBreakpoint') currentBreakpoint:string = BreakpointConstants.BREAKPOINT_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(){
//在build函数加载前就注册设备监听
this.breakpointSystem.register()
}
aboutToDisappear(){
//在退出应用时取消注册
this.breakpointSystem.unregister()
}
//封装颜色选择
selectColor(index){
return this.currentIndex === index ? $r('app.color.primary_color'):$r('app.color.gray')
}
//根据设备选择导航的布局
// chooseBarPosition(){
// //定义对象,根据对象名key来返回值
// return new BreakpointType({
// sm:BarPosition.End,
// md:BarPosition.Start,
// lg:BarPosition.Start
// }).getValue(this.currentBreakpoint)
// // let p = {
// // sm: BarPosition.End,
// // md:BarPosition.Start,
// // lg:BarPosition.Start
// // }
// // return p[this.currentBreakpoint]
//
// }
build() {
//让导航栏位于页面底部
//根据设备选择导航的布局
Tabs({barPosition: BreakpointConstants.BAR_POSITION.getValue(this.currentBreakpoint)}){
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%')
.vertical(new BreakpointType({
//传参
sm:false,
md:true,
lg:true
}).getValue(this.currentBreakpoint))
.onChange(index => this.currentIndex = index)//也可以直接对TabBarBuilder加点击事件
}
}
import BreakpointType from '../../common/bean/BreanpointType'
import BreakpointConstants from '../../common/constants/BreakpointConstants'
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())
// 定义当前的设备并初始化
@StorageProp('currentBreakpoint') currentBreakpoint:string = BreakpointConstants.BREAKPOINT_SM
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')})// 设置穿梭框的样式
.indicator(new BreakpointType({
//为平板设备隐藏穿梭框
sm:true,
md:true,
lg:false
}).getValue(this.currentBreakpoint))
.displayCount(new BreakpointType({
sm:1,
md:1,
lg:2
}).getValue(this.currentBreakpoint))
}.width(CommonConstants.THOUSANDTH_940)
.backgroundColor($r('app.color.stats_title_bgc'))
.borderRadius(CommonConstants.DEFAULT_18)
}
}
参考黑马课堂老师的讲解,欢迎大家的批评和指正。