食物列表页
前言
本期主要讲解食物列表页结构的分析及其完善。
一、食物列表页面结构分析
该结构是分为两部分,上部分由一个Row容器承载着两个组件,下面是一个Tabs组件。
二、食物列表页面的创建
2.1头部导航的创建
如图所示:
2.2食物列表的创建
如图所示:
TabContentBuilder函数的创建:
ItemList代码如下(示例):
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() { //Tabs本身就是个容器 Tab组件可以实现页面内视图内容快速切换,包含Tabar和TabContent两个部分
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_4 }) {
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%')
}
}
ItemIndex代码如下(示例):
import router from '@ohos.router'
import { CommonConstants } from '../common/constants/CommonConstants'
import { RecordTypeEnum, RecordTypes } from '../model/RecordTypeModel'
import RecordService from '../service/RecordService'
import ItemCard from '../view/item/ItemCard'
import ItemList from '../view/item/ItemList'
import ItemPanelHeader from '../view/item/ItemPanelHeader'
import NumberKeyboard from '../view/item/NumberKeyboard'
import RecordItem from '../viewmodel/RecordItem'
import RecordType from '../viewmodel/RecordType'
@Entry
@Component
struct ItemIndex {
@State amount:number=1//状态变量
@State value:string=''//用户按键的内容记录在value内 amount最终结果
@State showPanel:boolean=false//默认不展示
@State item:RecordItem=null
@State type:RecordType=RecordTypes[0]
@State isFood:boolean=true
onPanelShow(item:RecordItem){
this.amount=1//每次弹出,需要初始化为原始状态
this.value=''//每次弹出,初始化为原始状态
this.item = item//底部面板一弹出 就赋值
this.showPanel=true
}
onPageShow(){
//1.获取跳转时的参数
let params:any=router.getParams()
//2.获取点击的饮食记录类型
this.type=params.type
this.isFood=this.type.id !== RecordTypeEnum.WORKOUT
}
build() {
Column() {
//1.头部导航
this.Header()
//2.列表
ItemList({showPanel:this.onPanelShow.bind(this),isFood:this.isFood})
.layoutWeight(1)//除头部外 剩下都被列表占用 这样高度固定
//3.底部面板
/*Panel 可滑动面板,提供一种轻量的内容展示窗口,方便在不同尺寸中切换。
需要传入布尔类型的参数 上方有一个状态变量*/
Panel(this.showPanel){
//3.1.顶部日期
ItemPanelHeader()
//3.2.记录顶卡片
if(this.item){
ItemCard({amount:this.amount,item:$item})//item必须用Link传 因为是对象
}
//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(()=>{
//1.持久化保存
RecordService.insert(this.type.id,this.item.id,this.amount)
.then(()=>{
//2.关闭弹窗
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(this.type.name).fontWeight(CommonConstants.FONT_WEIGHT_500)
}
.width(CommonConstants.THOUSANDTH_940)
.height(32)
}
}
总结
- 使用Column组件作为根容器,其中包含了头部导航、记录项列表和底部面板。
- 头部导航通过@Builder Header()装饰器定义,包含返回按钮和当前记录类型的名称。
- 记录项列表ItemList组件接受showPanel和isFood作为属性,用于控制底部面板的显示以及列表的显示内容。
- 底部面板Panel组件在showPanel为true时显示,包含顶部日期、记录项卡片、数字键盘和两个按钮(取消和提交)。
- 点击“取消”按钮会关闭底部面板。 点击“提交”按钮会调用RecordService.insert()方法保存记录,并在成功后关闭底部面板。