列表页UI设计——底部面板
在上次任务中我们完成了如上图所示的效果,在这次课中,我们需要完成当点击每个列表项后的加号按钮时,打开底部面板,查看营养素和通过数字键盘添加食物数量得功能,效果图如下:
Panel
可滑动面板,提供一种轻量的内容展示窗口,方便在不同尺寸中切换。
接口
Panel(show: boolean)
参数:
参数名 | 参数类型 | 必填 | 参数描述 |
---|---|---|---|
show | boolean | 是 | 控制Panel显示或隐藏。**说明:**如果设置为false时,则不占位隐藏。Visible.None或者show之间有一个生效时,都会生效不占位隐藏。 |
属性
除支持通用属性外,还支持以下属性:
名称 | 参数类型 | 描述 |
---|---|---|
type | PanelType | 设置可滑动面板的类型。默认值:PanelType.Foldable |
mode | PanelMode | 设置可滑动面板的初始状态。Minibar类型默认值:PanelMode.Mini;其余类型默认值:PanelMode.Half |
dragBar | boolean | 设置是否存在dragbar,true表示存在,false表示不存在。默认值:true |
fullHeight | string | number | 指定PanelMode.Full状态下的高度。默认值:当前组件主轴大小减去8vp空白区**说明:**不支持设置百分比。 |
halfHeight | string | number | 指定PanelMode.Half状态下的高度。默认值:当前组件主轴大小的一半。**说明:**不支持设置百分比。 |
miniHeight | string | number | 指定PanelMode.Mini状态下的高度。默认值:48单位:vp**说明:**不支持设置百分比。 |
show | boolean | 当滑动面板弹出时调用。 |
backgroundMask9+ | ResourceColor | 指定Panel的背景蒙层。 |
结构分析
通过效果图,可以看出该面板由顶部日期、记录项卡片、数字键盘三部分组成,本节课我们先完成顶部日期、记录项卡片部分。将顶部日期、记录项卡片部分封装成组件,在食物列表界面调用。底部面板属性设置如注释所示。
//3.底部面板
Panel(this.showPanel){
//3.1.顶部日期
ItemPanelHeader()
//3.2.记录项卡片
ItemCard({amount:this.amount})
//3.3. 数字键盘
//3.4. 按钮
}.mode(PanelMode.Full) //设置底部面板显示模式展示占全部
.dragBar(false) //是否存在调节高度滑钮
.backgroundMask($r('app.color.light_gray')) //背景蒙版颜色
.backgroundColor(Color.White)
想要点击每个列表项后的加号按钮时,打开底部面板,还需做如下设计:
-
设置状态变量,表示底部面板显示状态
@State showPanel:boolean =false; //底部面板的显示状态
-
将显示状态封装,传递给列表组件
onPanelShow(){ this.showPanel=true; }
//2.列表
ItemList({showPanel:this.onPanelShow.bind(this)})
.layoutWeight(1)
ListItem(){
Row({space:CommonConstants.SPACE_6}){
Image($r('app.media.toast')).width(50)
Column({space:CommonConstants.SPACE_4}){
Text('全麦吐司').fontWeight(CommonConstants.FONT_WEIGHT_500)
Text('91千卡/片').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()) //点击时父页面的底部面板显示
顶部日期设计
在这里,我们将顶部日期暂时用文本代替,在之后使用日期选择器等进行优化
import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct ItemPanelHeader {
build() {
Row(){
Text('2024年1月25日 早餐')
.fontSize(18).fontWeight(CommonConstants.FONT_WEIGHT_600)
Image($r('app.media.ic_public_spinner'))
.width(20)
.fillColor(Color.Black)
}
}
}
记录项卡片设计
如图所示,记录项卡牌是一个列式布局,在这个列式布局中,第一行是一个图片,第二行是一个带背景颜色的文字,然后是一条下划线,接着是在一行里格式相同的四列,将这相同的结构封装起来,传入不同的参数,构成内容不同的四列,再次加入一个下划线。
最后一行里包括一个包含数字和下划线的一列,和一个单位文字。
import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct ItemCard {
@Prop amount :number //数字键盘输入,amount接收,需要同步
build() {
Column({space:CommonConstants.SPACE_8}){
//1.图片信息
Image($r('app.media.toast')).width(150)
//2.名称信息
Row(){
Text('全麦吐司').fontWeight(CommonConstants.FONT_WEIGHT_700)
}.backgroundColor($r('app.color.lightest_primary_color'))
.padding({top:5,bottom:5,left:12,right:12})
// .margin({bottom:10})
Divider().width(CommonConstants.THOUSANDTH_940).opacity(0.6) //下划线加透明度
//3.营养素信息
Row({space:CommonConstants.SPACE_8}){
this.NutrientInfo('热量(千卡)',91.0)
this.NutrientInfo('碳水(克)',15.5)
this.NutrientInfo('蛋白质(克)',4.4)
this.NutrientInfo('脂肪(克)',1.3)
}
Divider().width(CommonConstants.THOUSANDTH_940).opacity(0.6) //下划线加透明度
//4.数量部分
Row(){
Column({space:CommonConstants.SPACE_4}){
Text(this.amount.toFixed(1))
.fontSize(50)
.fontColor($r('app.color.primary_color'))
.fontWeight(CommonConstants.FONT_WEIGHT_600)
Divider().color($r('app.color.primary_color')).height(2)
}.width(150)
Text('片').fontColor($r('app.color.light_gray'))
.fontWeight(CommonConstants.FONT_WEIGHT_600)
}
}
}
@Builder NutrientInfo(label:string,value:number){
Column({space:CommonConstants.SPACE_8}){
Text(label).fontSize(14).fontColor($r('app.color.light_gray'))
Text(value.toFixed(1)).fontSize(18).fontWeight(CommonConstants.FONT_WEIGHT_700)
}
}
}