鸿蒙HarmonyOS开发实战(3)

  根据黑马程序员(https://www.bilibili.com/video/BV1Sa4y1Z7B1?p=36&vd_source=756db0e287d884b2979ab5b54a59c305)编写

一、实战案例-食物列表设置

最终效果图:

食物列表主页(ItemIndex)设置

ItemIndex主页设置

效果图如上所示

需求:

需要展示所有食物信息(本次代码只写了全麦吐司),点击添加之后会弹出一个面板,在面板中显示食物的相应信息,还有一个输入框,用来输入吃了多少个该食物,以及两个按钮。

食物列表主代码实现(Index.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'
import NumberKeyboard from '../view/item/NumberKeyboard'
@Entry
@Component
struct ItemIndex {
  @State showPanel:boolean = false
  @State amount:number=1
  @State value: string = ''
  onPanelShow(){
    //控制面板展示
    this.showPanel=true
  }
  build() {
    Column() {
     //1.头部导航
      this.header()
      //2.列表
      ItemList({showPanel:this.onPanelShow.bind(this)})
        //设置列表高度,否则面板位置不确定点击按钮没有反应
        .layoutWeight(1)
      //3.底部面板
      Panel(this.showPanel){
        //3.1.顶部日期
        ItemPanelHeader()
        //3.2记录项卡片
        ItemCard({amount:this.amount})
        //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)
            .type(ButtonType.Normal)
            .borderRadius(6)
            .backgroundColor($r('app.color.primary_color'))
            .onClick(() => this.showPanel = false)
        }
        .margin({top: 10})


      }
      .mode(PanelMode.Full)
      .dragBar(false)
      .backgroundMask($r('app.color.light_gray'))
      .backgroundColor(Color.White)
    }
    .height('100%')
  }




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

1.头部设置(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)
    }

  }

}

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('肉蛋奶')

    }.width(CommonConstants.THOUSANDTH_940)
    .height('100%')

  }
  //提出卡片,减少代码冗余
  @Builder TabContentBuilder(){
    List({space:CommonConstants.SPACE_10}){
      //此处ForEach同上
      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.输入面板实现代码(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_600)
      }
      .backgroundColor($r('app.color.lightest_primary_color'))
        .padding({top:5,bottom:5,left:15,right:12})
      //水平线
      Divider().width(CommonConstants.THOUSANDTH_940).opacity(0.6)
      //3.营养素信息
      Row({space:CommonConstants.SPACE_8}){
        this.NutrientInfo('热量(千卡)',91.0)
        this.NutrientInfo('碳水(克)',91.0)
        this.NutrientInfo('蛋白质',4.4)
        this.NutrientInfo('脂肪(克)',1.3)
      }
      Divider().width(CommonConstants.THOUSANDTH_940).opacity(0.6)
      //4.数量信息
      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'))
      }
    }
  }
  @Builder NutrientInfo(label:string,value:number){

    Column({space:CommonConstants.SPACE_8}){
      Text(label).fontSize(14).fontColor($r('app.color.light_gray'))
      Text((value * this.amount).toFixed(1)).fontSize(18).fontWeight(CommonConstants.FONT_WEIGHT_700)
    }
  }
}

4.数字键盘代码(NumberKeyboard.ets)

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

  numbers: string[] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.']
  @Link amount: number
  @Link value: string

//设置样式
  @Styles keyBoxStyle(){
    .backgroundColor(Color.White)
    .borderRadius(8)
    .height(60)
  }
  build() {
//表格面板
    Grid(){
      ForEach(this.numbers, num => {
        GridItem(){
          Text(num).fontSize(20).fontWeight(CommonConstants.FONT_WEIGHT_900)
        }
        .keyBoxStyle()
        .onClick(() => this.clickNumber(num))
      })
      GridItem(){
        Text('删除').fontSize(20).fontWeight(CommonConstants.FONT_WEIGHT_900)
      }
      .keyBoxStyle()
      .onClick(() => this.clickDelete())
    }
    .width('100%')
    .height(280)
    .backgroundColor($r('app.color.index_page_background'))
    .columnsTemplate('1fr 1fr 1fr')
    .columnsGap(8)
    .rowsGap(8)
    .padding(8)
    .margin({top: 10})
  }

  clickNumber(num: string){
    // 1.拼接用户输入的内容
    let val = this.value + num
    // 2.校验输入格式是否正确
    let firstIndex = val.indexOf('.')
    let lastIndex = val.lastIndexOf('.')
    if(firstIndex !== lastIndex || (lastIndex != -1 && lastIndex < val.length - 2)){
      // 非法输入
      return
    }
    // 3.将字符串转为数值
    let amount = this.parseFloat(val)
    // 4.保存
    if(amount >= 999.9){
      this.amount = 999.0
      this.value = '999'
    }else{
      this.amount = amount
      this.value = val
    }
  }

  clickDelete(){
    if(this.value.length <= 0){
      this.value = ''
      this.amount = 0
      return
    }
    this.value = this.value.substring(0, this.value.length - 1)
    this.amount = this.parseFloat(this.value)
  }

  parseFloat(str: string){
//判断,如果字符为空,那么将其数置为0,否则会出现NAN
    if(!str){
      return 0
    }
    if(str.endsWith('.')){
      str = str.substring(0, str.length - 1)
    }
    return parseFloat(str)
  }
}

小结 

本次实现了食物列表的功能,在代码中使用了一些新的API如Grid用来实现数字输入的功能,但功能扔未完善,很多代码都是写死的,并没有完成达到最终效果。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值