文章目录
一、目标
二、开撸
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布局