[HarmonyOS NEXT 实战案例:电商应用] 基础篇 - 垂直分割布局打造商品详情页
[HarmonyOS NEXT 实战案例:电商应用] 基础篇 - 垂直分割布局打造商品详情页
项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star
效果演示
引言
电商应用是移动应用开发中的重要场景之一,其中商品详情页是用户了解商品信息、做出购买决策的关键界面。一个设计良好的商品详情页需要清晰展示商品图片、价格、规格等信息,并提供便捷的购买操作。本教程将详细讲解如何使用HarmonyOS NEXT的ColumnSplit
组件构建一个电商商品详情页,通过垂直分割布局将界面分为商品图片区域和商品信息区域。
组件概述
在本案例中,我们将使用以下HarmonyOS NEXT组件:
组件名称 | 功能描述 |
---|---|
ColumnSplit |
垂直分割布局容器,将界面分为上下两部分 |
Column |
垂直布局容器,用于垂直排列子组件 |
Row |
水平布局容器,用于水平排列子组件 |
Swiper |
轮播图组件,用于展示商品的多张图片 |
Image |
图片组件,用于显示商品图片 |
Text |
文本组件,用于显示商品名称、价格等信息 |
Button |
按钮组件,用于收藏、加入购物车和购买操作 |
ForEach |
循环渲染组件,用于渲染商品规格选项和轮播图 |
Circle |
圆形组件,用于创建轮播图指示器 |
Scroll |
滚动容器,用于在有限空间内展示更多内容 |
Flex |
弹性布局容器,用于灵活排列子组件 |
代码实现
组件结构
首先,我们定义了一个名为ECommerceDetailExample
的自定义组件:
@Component
export struct ECommerceDetailExample {
@State currentImageIndex: number = 0
@State selectedSize: string = 'M'
@State quantity: number = 1
@State isFavorite: boolean = false
build() {
// 组件内容
}
}
在这个组件中,我们定义了四个状态变量:
currentImageIndex
:当前显示的商品图片索引selectedSize
:当前选中的商品尺码quantity
:商品数量isFavorite
:是否收藏商品
外层容器
我们使用ColumnSplit
组件作为最外层容器,将界面分为上下两部分:
ColumnSplit() {
// 商品图片展示区
Column() {
// 图片轮播和指示器
}
.height('40%')
// 商品信息区
Column() {
// 商品信息和操作按钮
}
}
.height(600)
ColumnSplit
设置了600的高度,确保整个界面有足够的显示空间。上部分的商品图片展示区占总高度的40%,下部分的商品信息区占剩余高度。
商品图片展示区
商品图片展示区包含一个轮播图组件和一个图片指示器:
Column() {
Swiper() {
ForEach([
$r('app.media.big19'),
$r('app.media.big18'),
$r('app.media.big17')
], (img: Resource, index: number) => {
Image(img)
.width('100%')
.height(300)
.objectFit(ImageFit.Cover)
})
}
.indicatorStyle({
color: '#ff4757',
selectedColor: '#ff4757'
})
.onChange((index: number) => {
this.currentImageIndex = index
})
// 图片指示器
Row() {
ForEach([0, 1, 2], (index: number) => {
Circle()
.width(8)
.height(8)
.margin(3)
.fill(index === this.currentImageIndex ? '#ff4757' : '#cccccc')
})
}
.margin({ top: 10 })
.justifyContent(FlexAlign.Center)
}
.height('40%')
在这个部分:
- 我们使用
Swiper
组件创建一个轮播图,通过ForEach
循环渲染三张商品图片。 - 每张图片都设置为100%宽度和300的高度,并使用
objectFit(ImageFit.Cover)
确保图片填充整个区域。 - 我们设置了轮播图的指示器样式,并通过
onChange
事件更新currentImageIndex
状态。 - 在轮播图下方,我们创建了一个自定义的图片指示器,使用
Circle
组件表示每张图片,当前显示的图片对应的圆点会高亮显示。
商品信息区
商品信息区包含商品标题、价格、规格选择、数量选择、商品详情和底部操作栏:
Column() {
Scroll() {
Column() {
// 商品标题和价格
Row() {
Column() {
Text('男士休闲衬衫')
.fontSize(20)
.fontWeight(FontWeight.Bold)
Text('夏季新款 透气舒适')
.fontSize(14)
.fontColor('#666666')
}
.layoutWeight(1)
Button(this.isFavorite ? $r('app.media.01') : $r('app.media.02'))
.width(24)
.height(24)
.backgroundColor(Color.Transparent)
.onClick(() => this.isFavorite = !this.isFavorite)
}
.margin({ bottom: 15 })
Text('¥189')
.fontSize(24)
.fontColor('#ff4757')
.margin({ bottom: 20 })
// 商品规格选择
Column() {
Text('尺码')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(['XS', 'S', 'M', 'L', 'XL'], (size: string) => {
Button(size)
.width(60)
.height(40)
.fontSize(14)
.backgroundColor(this.selectedSize === size ? '#ff4757' : '#f5f5f5')
.fontColor(this.selectedSize === size ? '#ffffff' : '#333333')
.margin({ right: 10, bottom: 10 })
.onClick(() => this.selectedSize = size)
})
}
}
.margin({ bottom: 20 })
// 商品数量选择
Column() {
Text('数量')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Row() {
Button('-')
.width(40)
.height(40)
.fontSize(18)
.onClick(() => {
if (this.quantity > 1) this.quantity--
})
Text(this.quantity.toString())
.fontSize(16)
.margin({ left: 15, right: 15 })
.width(40)
.textAlign(TextAlign.Center)
Button('+')
.width(40)
.height(40)
.fontSize(18)
.onClick(() => this.quantity++)
}
}
.margin({ bottom: 20 })
// 商品详情
Column() {
Text('商品详情')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Text('材质: 100%棉\n颜色: 浅蓝色\n款式: 休闲\n季节: 夏季\n洗涤说明: 建议手洗,不可漂白')
.fontSize(14)
.lineHeight(22)
}
.margin({ bottom: 20 })
}
.padding(20)
}
.layoutWeight(1)
// 底部操作栏
Row() {
Button('加入购物车')
.height(50)
.layoutWeight(1)
.backgroundColor('#ff9500')
.fontColor('#ffffff')
Button('立即购买')
.height(50)
.layoutWeight(1)
.backgroundColor('#ff4757')
.fontColor('#ffffff')
.margin({ left: 10 })
}
.padding(10)
.backgroundColor('#ffffff')
.border({
width:{top:1,bottom:0, left:0,right:0},
color:'#eee',
style:{
top:BorderStyle.Solid,
}
})
}
在这个部分:
- 我们使用
Scroll
组件创建一个可滚动的区域,确保在内容超出可视区域时用户可以滚动查看。 - 商品标题和价格部分使用
Row
和Column
组合布局,右侧添加了一个收藏按钮,点击可以切换收藏状态。 - 商品规格选择部分使用
Flex
组件创建一个弹性布局,通过ForEach
循环渲染尺码选项,当前选中的尺码会高亮显示。 - 商品数量选择部分使用
Row
组件水平排列减少按钮、数量文本和增加按钮,点击按钮可以调整商品数量。 - 商品详情部分使用
Text
组件显示商品的详细信息,通过\n
实现多行文本。 - 底部操作栏固定在底部,包含"加入购物车"和"立即购买"两个按钮,使用
layoutWeight
属性使两个按钮平分宽度。
布局技巧
1. 垂直分割布局
使用ColumnSplit
组件可以轻松实现上下分割的布局效果,适合商品详情页这种需要展示图片和详细信息的场景。通过设置子组件的高度比例,可以控制上下两部分的大小关系。
2. 嵌套布局
在本案例中,我们使用了多层嵌套的布局结构:
- 最外层是
ColumnSplit
,将界面分为上下两部分 - 上部分使用
Column
包含Swiper
和指示器 - 下部分使用
Column
包含Scroll
和底部操作栏 Scroll
内部使用Column
垂直排列各个信息区块- 每个信息区块内部又使用
Row
、Column
、Flex
等组件进行布局
这种嵌套布局的方式使得界面结构清晰,各个部分的职责明确。
3. 滚动与固定结合
在商品信息区,我们使用了Scroll
组件使内容可滚动,同时将底部操作栏固定在底部不随内容滚动。这种布局方式在移动应用中非常常见,可以在有限的屏幕空间内展示更多内容,同时保持关键操作按钮始终可见。
4. 弹性布局
在商品规格选择部分,我们使用了Flex
组件创建一个弹性布局,并设置wrap: FlexWrap.Wrap
使得当一行放不下所有选项时会自动换行。这种布局方式适合展示数量不确定的选项,可以根据屏幕宽度自动调整排列。
交互实现
1. 图片轮播
通过Swiper
组件实现图片轮播,并通过onChange
事件更新当前显示的图片索引:
Swiper()
// ...
.onChange((index: number) => {
this.currentImageIndex = index
})
2. 规格选择
通过Button
组件的onClick
事件实现规格选择,点击按钮时更新selectedSize
状态:
Button(size)
// ...
.onClick(() => this.selectedSize = size)
3. 数量调整
通过Button
组件的onClick
事件实现数量调整,点击"+"按钮增加数量,点击"-"按钮减少数量:
Button('-')
// ...
.onClick(() => {
if (this.quantity > 1) this.quantity--
})
Button('+')
// ...
.onClick(() => this.quantity++)
4. 收藏切换
通过Button
组件的onClick
事件实现收藏状态切换,点击按钮时切换isFavorite
状态:
Button(this.isFavorite ? $r('app.media.01') : $r('app.media.02'))
// ...
.onClick(() => this.isFavorite = !this.isFavorite)
样式设计
1. 颜色搭配
在本案例中,我们使用了以下颜色:
- 主色调:
#ff4757
(红色),用于价格、选中状态和"立即购买"按钮 - 次要色调:
#ff9500
(橙色),用于"加入购物车"按钮 - 背景色:
#f5f5f5
(浅灰色),用于未选中的规格按钮 - 文本颜色:
#333333
(深灰色)用于主要文本,#666666
(中灰色)用于次要文本
这种颜色搭配符合电商应用的视觉风格,突出重要信息和操作按钮。
2. 间距设置
在布局中,我们使用了一致的间距设置:
- 整体内容区域设置了20的内边距
- 各个区块之间设置了20的下边距
- 按钮之间设置了10的间距
这种一致的间距设置使得界面看起来整洁有序。
3. 字体大小
在本案例中,我们使用了不同的字体大小来区分不同层级的信息:
- 商品标题:20
- 价格:24
- 区块标题:16-18
- 正文内容:14
这种字体大小的层次设置使得用户可以快速识别重要信息。
总结
在本教程中,我们学习了如何使用HarmonyOS NEXT的ColumnSplit
组件构建一个电商商品详情页。通过垂直分割布局,我们将界面分为商品图片区域和商品信息区域,使得界面结构清晰,信息展示合理。
我们还学习了如何使用Swiper
组件实现图片轮播,如何使用Flex
组件创建弹性布局,如何使用Scroll
组件实现内容滚动,以及如何通过状态变量和事件处理实现各种交互功能。
通过本教程,你应该能够理解垂直分割布局在电商商品详情页中的应用,并能够根据自己的需求进行定制和扩展。
- 0回答
- 4粉丝
- 0关注
- [HarmonyOS NEXT 实战案例:电商应用] 基础篇 - 垂直分割布局打造商品详情页
- [HarmonyOS NEXT 实战案例:教育应用] 基础篇 - 垂直分割布局打造课程学习平台
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 垂直分割布局ColumnSplit详解
- 94.[HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 三栏垂直分割布局
- [HarmonyOS NEXT 实战案例二:SideBarContainer] 侧边栏容器实战:电商应用商品筛选侧边栏 基础篇
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 可调整分割比例的垂直布局
- [HarmonyOS NEXT 实战案例一] 电商首页商品网格布局(下)
- [HarmonyOS NEXT 实战案例一] 电商首页商品网格布局(上)
- [HarmonyOS NEXT 实战案例:聊天应用] 基础篇 - 垂直分割布局构建聊天界面
- [HarmonyOS NEXT 实战案例:旅行应用] 基础篇 - 水平分割布局打造旅行规划应用
- [HarmonyOS NEXT 实战案例:设置页面] 基础篇 - 垂直分割布局构建设置中心
- [HarmonyOS NEXT 实战案例二:SideBarContainer] 侧边栏容器实战:电商应用商品筛选侧边栏 进阶篇
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 邮件应用布局设计
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 打造现代化设置中心界面
- [HarmonyOS NEXT 实战案例:分割布局] 基础篇 - 水平分割布局RowSplit详解