鸿蒙案例-食物列表页和底部Panel的实现

前言

    食物列表页是健康和饮食管理应用中的一个关键功能,它允许用户浏览、搜索和选择不同的食物项来记录他们的饮食习惯。食物列表以列表形式展示食物名称、图片和简要信息。点击食物项后,展示详细的营养信息,包括热量、脂肪、碳水化合物、蛋白质等。

    食物列表页是用户与饮食管理应用交互的主要入口之一,它的设计和功能对于提供流畅的用户体验至关重要。通过这些功能,用户可以轻松地记录和分析他们的饮食习惯,从而更好地管理自己的健康和营养摄入。


列表UI设计

实现过程

1.ItemIndex组件

1.头部导航:首先是一个返回图片,设置好返回图片的宽,然后设置back实现点击返回的效果。空格处用Blank组件。

@Builder Header(){
    Row(){
      Image($r('app.media.ic_public_back'))
        .width(24)
        .onClick(()=>router.back()) //返回
      Blank()
      Text('早餐').fontWeight(CommonConstants.FONT_WEIGHT_600).fontSize(18)
    }
    .width(CommonConstants.THOUSANDTH_940)
    .height(32)
  }

2.列表:因为列表内容过多,所以需创建Item组件目录,在创建ItemList组件,并进行调用

 ItemList({showPanel:this.onPanelShow.bind(this)})
      .layoutWeight(1)

3.底部面板:使用了Panel可滑动面板,提供一种轻量的内容展示窗口,方便在不同尺寸中进行切换。设置时展示全部,设置成不可调整高度

 Panel(this.showPanel){
}.mode(PanelMode.Full)
      .dragBar(false)  
      .backgroundMask($r('app.color.light_gray')) 
      .backgroundColor(Color.White)

3.1.顶部日期:创建ItemPanelHeader组件并进行调用

 ItemPanelHeader()

3.2.记录项卡片:创建ItemCard组件并进行调用

ItemCard({amount:this.amount})

2.ItemList组件

1.利用Tabs容器创建多个项

 Tabs(){
      TabContent(){
        this.TabContentBuilder()
      }
      .tabBar('全部')

      TabContent(){
        this.TabContentBuilder()
      }
      .tabBar('主食')

      TabContent(){
        this.TabContentBuilder()
      }
      .tabBar('果蔬')

      TabContent(){
        this.TabContentBuilder()
      }
      .tabBar('肉蛋奶')

      TabContent(){
        this.TabContentBuilder()
      }
      .tabBar('其它')
    }

2.然后利用list列表实现列循环

List({space:CommonConstants.SPACE_6}){
      ForEach([1,2,3,4,5,6],(item)=>{
        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())
      })
    }

3.ItemPanelHeader组件

顶部日期主要是文字和图片

 Row(){
      Text('2024年1月25日 早餐')
        .fontSize(18).fontWeight(CommonConstants.FONT_WEIGHT_600)
      Image($r('app.media.ic_public_spinner'))
        .width(20)
        .fillColor(Color.Black)
    }

4.ItemCard组件

1.图片

Image($r('app.media.toast')).width(150)

2.名称:其中Divider分割组件,实现下划线效果

 Row(){
        Text('全麦吐司').fontWeight(CommonConstants.FONT_WEIGHT_700)
      }
      .backgroundColor($r('app.color.lightest_primary_color'))
      .padding({top:5,bottom:5,left:12,right:12})
      Divider().width(CommonConstants.THOUSANDTH_940).opacity(0.6)

3.营养素:创建Builder记录营养素的信息

 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)
        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'))
          }
          .width(150)
          Text('片')
            .fontColor($r('app.color.light_gray'))
            .fontWeight(CommonConstants.FONT_WEIGHT_600)
        }

代码实现

1.ItemIndex.ets

import router from '@ohos.router'
import { CommonConstants } from '../common/constants/CommonConstants'
import ItemCard from '../view/item/ItemCard'
import ItemList from '../view/item/ItemList'
import ItemPanelHeader from '../view/item/ItemPanelHeader'
@Entry
@Component
struct ItemIndex {
  @State amount: number=1
  @State showPanel:boolean = false

  onPanelShow(){
    this.showPanel=true
  }

  build() {
    Column() {
      //1.头部导航
      this.Header()
      //2.列表
      ItemList({showPanel:this.onPanelShow.bind(this)})
      .layoutWeight(1)
      //3.底部面板
      Panel(this.showPanel){//Panel可滑动面板
        //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)
    }
    .width('100%')
    .height('100%')
  }

  @Builder Header(){
    Row(){
      Image($r('app.media.ic_public_back'))
        .width(24)
        .onClick(()=>router.back()) //返回
      Blank()
      Text('早餐').fontWeight(CommonConstants.FONT_WEIGHT_600).fontSize(18)
    }
    .width(CommonConstants.THOUSANDTH_940)
    .height(32)
  }
}

2.ItemList.ets

import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct ItemList {

  showPanel:()=>void

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

      TabContent(){
        this.TabContentBuilder()
      }
      .tabBar('主食')

      TabContent(){
        this.TabContentBuilder()
      }
      .tabBar('果蔬')

      TabContent(){
        this.TabContentBuilder()
      }
      .tabBar('肉蛋奶')

      TabContent(){
        this.TabContentBuilder()
      }
      .tabBar('其它')
    }
    .width(CommonConstants.THOUSANDTH_940)
    .height('100%')
  }

  @Builder TabContentBuilder(){
    List({space:CommonConstants.SPACE_6}){
      ForEach([1,2,3,4,5,6],(item)=>{
        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())
      })
    }
    .width('100%')
    .height('100%')
  }
}

3.ItemPanelHeader.ets

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)
    }
  }
}

4.ItemCard.ets

import { CommonConstants } from '../../common/constants/CommonConstants'
@Component
export default struct ItemCard {

  @Prop amount:number

  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})
      Divider().width(CommonConstants.THOUSANDTH_940).opacity(0.6) //Divider分割组件,实现下划线效果
      //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)
        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'))
          }
          .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)
    }
  }
}

页面效果

总结

    食物列表页它的设计和功能对于提供流畅的用户体验至关重要。通过这些功能,用户可以轻松地记录和分析他们的饮食习惯,从而更好地管理自己的健康和营养摄入。

    其中学习到Panel可滑动面板,提供的是一种轻量的内容展示窗口,方便在不同尺寸中进行切换。但是有时候会出现不生效的问题。Panel本身不占文档流的,类似于前端的浮动,要求Panel所在的容器,以及容器内的子元素高度全都固定,如果有不固定的高度可能导致无法正常展示。Divider分割组件,可以实现下划线效果

  • 19
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值