HarmonyOS NEXT星河版之美团外卖点餐功能实战(上)

一、目标

在这里插入图片描述
在这里插入图片描述

二、开撸

2.1 目录结构

在这里插入图片描述

2.2 页面模块拆分

将页面主体拆为三部分,如图所示:
在这里插入图片描述

2.3 主体拆分布局

顶部view:

@Component
export struct MTTopView {
  build() {
    Row() {
      Text('top')
        .width('100%')
        .textAlign(TextAlign.Center)
    }
    .height(52)
    .width('100%')
    .backgroundColor(Color.White)
  }
}

主内容区view:

@Component
export struct MTContentView {
  build() {
    Row() {
      Text('content')
        .width('100%')
        .textAlign(TextAlign.Center)
    }
    .height('100%')
    .width('100%')
    .backgroundColor(Color.Gray)
  }
}

底部view:

@Component
export struct MTBottomView {
  build() {
    Column() {
      Text('bottom')
        .width('100%')
        .height('100%')
        .textAlign(TextAlign.Center)
    }
    .height(52)
    .width('80%')
    .margin({ bottom: 20 })
    .backgroundColor(Color.Red)
  }
}

预览如下:
在这里插入图片描述

2.4 底部购物车布局

在这里插入图片描述

@Component
export struct MTBottomView {
  build() {
    Row() {
      // 小哥+角标
      Badge({ value: '0', style: { badgeSize: 18 }, position: BadgePosition.Right }) {
        Image($r('app.media.ic_public_cart'))
          .height(69)
          .width(47)
          .position({
            y: -20
          })
      }
      .margin({ left: 28, right: 12 })

      // 金额+描述
      Column() {
        Text() {
          Span('¥')
            .fontColor(Color.White)
            .fontSize(12)
          Span('0.00')
            .fontColor(Color.White)
            .fontSize(25)
        }

        Text('预估另需配送费¥5')
          .fontColor($r('app.color.search_font_color'))
          .fontSize(12)
      }
      .alignItems(HorizontalAlign.Start)
      .layoutWeight(1)

      // 去结算
      Text('去结算')
        .width(80)
        .height(50)
        .fontSize(16)
        .backgroundColor($r('app.color.main_color'))
        .textAlign(TextAlign.Center)
        .borderRadius({
          topRight: 25,
          bottomRight: 25
        })
    }
    .height(50)
    .width('88%')
    .margin({ bottom: 20 })
    .backgroundColor(Color.Black)
    .borderRadius(26)
  }
}

2.5 顶部布局

在这里插入图片描述


@Component
export struct MTTopView {
  @Builder
  NavItem(active: boolean, title: string, subTitle?: string) {
    Column() {
      Text() {
        Span(title)
        if (subTitle) {
          Span(' ' + subTitle)
            .fontSize(10)
            .fontColor(active ? $r("app.color.black") : $r("app.color.un_select_color"))
        }
      }.layoutWeight(1)
      .fontColor(active ? $r("app.color.black") : $r("app.color.un_select_color"))
      .fontWeight(active ? FontWeight.Bold : FontWeight.Normal)

      Text()
        .height(2)
        .width(20)
        .margin({ left: 6 })
        .backgroundColor(active ? $r("app.color.select_border_color") : 'transparent')
    }
    .width(73)
    .alignItems(HorizontalAlign.Start)
    .padding({ top: 3 })
  }

  build() {
    Row() {
      this.NavItem(true, '点菜')
      this.NavItem(false, '评价', '1796')
      this.NavItem(false, '商家')
      Row() {
        Image($r('app.media.ic_public_search'))
          .width(14)
          .aspectRatio(1)
          .fillColor($r("app.color.search_font_color"))
        TextInput({ placeholder: '请输入' })
          .fontSize(12)
          .placeholderFont({ size: 12 })
          .fontColor($r("app.color.search_back_color"))
          .backgroundColor(Color.Transparent)
      }
      .backgroundColor($r("app.color.search_back_color"))
      .height(28)
      .borderRadius(13)
      .padding({ left: 5, right: 5 })
      .layoutWeight(1)
    }
    .padding({ left: 15, right: 15 })
    .height(40)
    .border({ width: { bottom: 0.5 }, color: $r("app.color.top_border_color") })
  }
}

2.6 点菜布局—左

在这里插入图片描述

@Component
export struct MTContentView {
  categoryList: string[] = ['一人套餐', '特色烧烤', '杂粮主食']
  @State categoryIndex: number = 0

  build() {
    Row() {
      // 左侧分类
      Column() {
        ForEach(this.categoryList, (item: string, index: number) => {
          Text(item)
            .height(50)
            .width('100%')
            .textAlign(TextAlign.Center)
            .backgroundColor(this.categoryIndex === index ? Color.White : '#F6F6F6')
            .onClick(() => {
              this.categoryIndex = index
            })
        })
      }
      .width(100)
      .backgroundColor('#F6F6F6')
      .height('100%')

      // 右侧食品列表

  }
}

2.7 菜品Item封装

在这里插入图片描述

@Preview
@Component
export struct MTFoodItem {
  build() {
    Row() {
      Image('https://images.tmtpost.com/uploads/images/2022/09/c0de0f8e1051beb409d189a7283a3ccd_1664523457.jpeg?imageMogr2/auto-orient/strip/interlace/1/quality/85/thumbnail/1400x933/gravity/center/crop/!1400x933&ext=.jpeg')
        .width(90)
        .aspectRatio(1)
      Column({ space: 5 }) {
        Text('小份酸汤莜面鱼鱼+肉夹馍套餐')
          .textOverflow({
            overflow: TextOverflow.Ellipsis,
          })
          .maxLines(2)
          .fontWeight(600)
        Text('酸汤莜面鱼鱼,主料:酸汤、莜面 肉夹馍,主料:白皮饼、猪肉')
          .textOverflow({
            overflow: TextOverflow.Ellipsis,
          })
          .maxLines(1)
          .fontSize(12)
          .fontColor($r("app.color.food_item_second_color"))
        Text('点评网友推荐')
          .fontSize(10)
          .backgroundColor($r("app.color.food_item_label_color"))
          .fontColor($r("app.color.font_main_color"))
          .padding({ top: 2, bottom: 2, right: 5, left: 5 })
          .borderRadius(2)
        Text() {
          Span('月销售40')
          Span(' ')
          Span('好评度100%')
        }
        .fontSize(12)
        .fontColor($r("app.color.black"))

        Row() {
          Text() {
            Span('¥ ')
              .fontColor($r("app.color.font_main_color"))
              .fontSize(10)
            Span('34.23')
              .fontColor($r("app.color.font_main_color"))
              .fontWeight(FontWeight.Bold)
          }
        }
        .justifyContent(FlexAlign.SpaceBetween)
        .width('100%')
      }
      .layoutWeight(1)
      .alignItems(HorizontalAlign.Start)
      .padding({ left: 10, right: 10 })
    }
    .padding(10)
    .alignItems(VerticalAlign.Top)
    .backgroundColor(Color.White)
  }
}

2.7 点菜布局—右

在这里插入图片描述

import { MTFoodItem } from './MTFoodItem'

@Component
export struct MTContentView {
  categoryList: string[] = ['一人套餐', '特色烧烤', '杂粮主食']
  @State categoryIndex: number = 0

  build() {
    Row() {
      // 左侧分类
      ...
      // 右侧食品列表
      List() {
        ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], (item: number) => {
          ListItem() {
            MTFoodItem()
          }
        })
      }
      .layoutWeight(1)
    }
    .height('100%')
    .width('100%')
  }
}

2.8 主页面整体布局

在这里插入图片描述

import { MTBottomView } from './components/MTBottomView'
import { MTContentView } from './components/MTContentView'
import { MTTopView } from './components/MTTopView'

@Entry
@Component
struct MeiTuanPage {
  build() {
    Column() {
      Stack({ alignContent: Alignment.Bottom }) {
        Column() {
          MTTopView()
          MTContentView()
        }
        .width('100%')
        .height('100%')
        .padding({bottom:120})
        MTBottomView()
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F6F6F6')
  }
}

三、小结

  • 组件拆分
  • UI布局
  • 11
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值