[HarmonyOS NEXT 实战案例二:SideBarContainer] 侧边栏容器实战:电商应用商品筛选侧边栏 基础篇
[HarmonyOS NEXT 实战案例二:SideBarContainer] 侧边栏容器实战:电商应用商品筛选侧边栏 基础篇
项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star
效果演示
一、电商应用侧边栏概述
在现代电商应用中,商品筛选功能是提升用户购物体验的关键元素。HarmonyOS NEXT提供的SideBarContainer
组件非常适合实现这类功能,它可以创建一个可显示和隐藏的侧边栏,用于放置各种筛选条件,帮助用户快速找到心仪的商品。
1.1 电商筛选侧边栏的特点
电商应用的筛选侧边栏通常具有以下特点:
- 悬浮式布局:筛选侧边栏通常采用悬浮在内容区上方的方式显示,不占用主内容区的空间
- 丰富的筛选条件:包括价格范围、商品分类、品牌、评分等多种筛选条件
- 实时反馈:用户调整筛选条件时,可以实时看到筛选结果或预览筛选效果
- 灵活的显示控制:用户可以通过按钮或手势来显示和隐藏筛选侧边栏
1.2 SideBarContainer组件回顾
在开始实现电商筛选侧边栏之前,让我们简要回顾一下SideBarContainer
组件的关键特性:
特性 | 说明 |
---|---|
显示模式 | 支持Embed (嵌入式)、Overlay (悬浮式)和Auto (自适应)三种模式 |
侧边栏位置 | 可以设置为Start (左侧)或End (右侧) |
控制按钮 | 可以自定义控制按钮的位置、大小和图标 |
宽度控制 | 可以设置侧边栏的默认宽度、最小宽度和最大宽度 |
自动隐藏 | 可以设置当侧边栏拖拽到小于最小宽度后是否自动隐藏 |
对于电商应用的筛选侧边栏,我们通常选择Overlay
模式,并将侧边栏位置设置为End
(右侧),这样可以提供更好的用户体验。
二、电商筛选侧边栏实战
接下来,我们将通过一个电商应用的实例,详细讲解如何使用SideBarContainer
组件实现商品筛选侧边栏。
2.1 需求分析
我们的电商应用筛选侧边栏需要实现以下功能:
- 价格范围筛选:使用滑块控制最低价和最高价
- 商品分类筛选:使用复选框选择多个商品分类
- 确认按钮:应用筛选条件并关闭侧边栏
- 主内容区显示商品列表,并提供筛选按钮打开侧边栏
2.2 代码实现
首先,我们来看完整的代码实现:
// 电商应用的商品筛选侧边栏
@Component
export struct ShoppingApp {
@State isSideBarShow: boolean = false
@State priceRange: number[] = [0, 1000]
@State selectedCategories: string[] = []
build() {
SideBarContainer(SideBarContainerType.Overlay) {
// 侧边栏内容 - 筛选条件
Column() {
Text('商品筛选').fontSize(20).margin(10)
Text('价格范围').fontSize(16).margin({ top: 15, left: 10 })
Slider({
min: 0,
max: 1000,
step: 50,
value: this.priceRange[0],
style: SliderStyle.OutSet
})
.blockColor('#ff4500')
.onChange((value: number) => {
this.priceRange[0] = value
})
Slider({
min: 0,
max: 1000,
step: 50,
value: this.priceRange[1],
style: SliderStyle.OutSet
})
.blockColor('#ff4500')
.onChange((value: number) => {
this.priceRange[1] = value
})
Text(`¥${this.priceRange[0]} - ¥${this.priceRange[1]}`).fontSize(14).margin({ bottom: 20 })
Text('商品分类').fontSize(16).margin({ top: 10, left: 10 })
Column() {
ForEach(['手机', '电脑', '家电', '服饰', '食品'], (item: string) => {
Row() {
Checkbox()
.onChange((isChecked: boolean) => {
if (isChecked) {
this.selectedCategories.push(item)
} else {
this.selectedCategories = this.selectedCategories.filter(cat => cat !== item)
}
})
Text(item).fontSize(14).margin({ left: 5 })
}
.margin({ top: 5, left: 10 })
})
}
Button('确定', { type: ButtonType.Capsule })
.width('80%')
.margin(20)
.backgroundColor('#ff4500')
.onClick(() => {
this.isSideBarShow = false
console.log('应用筛选条件:', this.priceRange, this.selectedCategories)
})
}
.width('80%')
.padding(10)
.backgroundColor(Color.White)
// 主内容区 - 商品列表
Column() {
Row() {
Button('筛选', { type: ButtonType.Capsule })
.width(80)
.onClick(() => {
this.isSideBarShow = true
})
Text('全部商品').fontSize(20).margin({ left: 10 })
}
.width('100%')
.padding(10)
Grid() {
ForEach(['手机', '笔记本', '耳机', '手表', '平板', '充电器'], (item: string) => {
GridItem() {
Column() {
Image($r(`app.media.phone`))
.width(80)
.height(80)
Text(item).fontSize(14).margin({ top: 5 })
Text('¥999').fontSize(16).fontColor('#ff4500')
}
.padding(10)
.borderRadius(8)
.backgroundColor(Color.White)
.shadow({ radius: 2, color: '#999', offsetX: 1, offsetY: 1 })
}
})
}
.columnsTemplate('1fr 1fr')
.columnsGap(10)
.rowsGap(10)
.width('100%')
.height('100%')
.padding(10)
}
}
.sideBarPosition(SideBarPosition.End)
.autoHide(false)
.onChange((value: boolean) => {
this.isSideBarShow = value
})
}
}
2.3 代码详解
2.3.1 组件结构
我们使用@Component
装饰器定义了一个名为ShoppingApp
的自定义组件,并使用@State
装饰器定义了三个状态变量:
@Component
export struct ShoppingApp {
@State isSideBarShow: boolean = false // 控制侧边栏显示状态
@State priceRange: number[] = [0, 1000] // 存储价格范围
@State selectedCategories: string[] = [] // 存储选中的商品分类
// ...
}
2.3.2 SideBarContainer配置
在build
方法中,我们使用SideBarContainer
组件作为根容器,并设置其显示模式为Overlay
,即侧边栏浮在内容区上面。
SideBarContainer(SideBarContainerType.Overlay) {
// 侧边栏内容 - 筛选条件
// 主内容区 - 商品列表
}
.sideBarPosition(SideBarPosition.End) // 侧边栏位于右侧
.autoHide(false) // 禁用自动隐藏
.onChange((value: boolean) => {
this.isSideBarShow = value // 更新侧边栏显示状态
})
我们通过链式调用设置了以下属性:
sideBarPosition(SideBarPosition.End)
:设置侧边栏显示在右侧autoHide(false)
:禁用自动隐藏功能,确保用户可以完全控制侧边栏的显示和隐藏onChange((value: boolean) => { ... })
:监听侧边栏显示状态的变化
2.3.3 侧边栏内容 - 筛选条件
侧边栏内容是SideBarContainer
的第一个子组件,我们使用Column
组件作为容器,包含价格范围筛选、商品分类筛选和确定按钮。
Column() {
Text('商品筛选').fontSize(20).margin(10)
// 价格范围筛选
Text('价格范围').fontSize(16).margin({ top: 15, left: 10 })
Slider({
min: 0,
max: 1000,
step: 50,
value: this.priceRange[0],
style: SliderStyle.OutSet
})
.blockColor('#ff4500')
.onChange((value: number) => {
this.priceRange[0] = value
})
// 第二个滑块...
Text(`¥${this.priceRange[0]} - ¥${this.priceRange[1]}`).fontSize(14).margin({ bottom: 20 })
// 商品分类筛选
Text('商品分类').fontSize(16).margin({ top: 10, left: 10 })
Column() {
ForEach(['手机', '电脑', '家电', '服饰', '食品'], (item: string) => {
Row() {
Checkbox()
.onChange((isChecked: boolean) => {
if (isChecked) {
this.selectedCategories.push(item)
} else {
this.selectedCategories = this.selectedCategories.filter(cat => cat !== item)
}
})
Text(item).fontSize(14).margin({ left: 5 })
}
.margin({ top: 5, left: 10 })
})
}
// 确定按钮
Button('确定', { type: ButtonType.Capsule })
.width('80%')
.margin(20)
.backgroundColor('#ff4500')
.onClick(() => {
this.isSideBarShow = false
console.log('应用筛选条件:', this.priceRange, this.selectedCategories)
})
}
.width('80%')
.padding(10)
.backgroundColor(Color.White)
这里我们使用了以下组件和技术:
-
价格范围筛选:
- 使用两个
Slider
组件分别控制最低价和最高价 - 通过
onChange
事件更新priceRange
状态变量 - 使用
Text
组件显示当前选择的价格范围
- 使用两个
-
商品分类筛选:
- 使用
ForEach
遍历商品分类数组 - 为每个分类创建一个包含
Checkbox
和Text
的Row
- 通过
onChange
事件更新selectedCategories
状态变量
- 使用
-
确定按钮:
- 使用
Button
组件创建一个胶囊型按钮 - 通过
onClick
事件处理函数关闭侧边栏并应用筛选条件
- 使用
2.3.4 主内容区 - 商品列表
主内容区是SideBarContainer
的第二个子组件,我们使用Column
组件作为容器,包含一个顶部栏和一个商品网格。
Column() {
Row() {
Button('筛选', { type: ButtonType.Capsule })
.width(80)
.onClick(() => {
this.isSideBarShow = true
})
Text('全部商品').fontSize(20).margin({ left: 10 })
}
.width('100%')
.padding(10)
Grid() {
ForEach(['手机', '笔记本', '耳机', '手表', '平板', '充电器'], (item: string) => {
GridItem() {
Column() {
Image($r(`app.media.phone`))
.width(80)
.height(80)
Text(item).fontSize(14).margin({ top: 5 })
Text('¥999').fontSize(16).fontColor('#ff4500')
}
.padding(10)
.borderRadius(8)
.backgroundColor(Color.White)
.shadow({ radius: 2, color: '#999', offsetX: 1, offsetY: 1 })
}
})
}
.columnsTemplate('1fr 1fr')
.columnsGap(10)
.rowsGap(10)
.width('100%')
.height('100%')
.padding(10)
}
这里我们使用了以下组件和技术:
-
顶部栏:
- 使用
Row
组件创建水平布局 - 包含一个「筛选」按钮和一个标题文本
- 通过按钮的
onClick
事件显示侧边栏
- 使用
-
商品网格:
- 使用
Grid
组件创建网格布局 - 通过
columnsTemplate
属性设置为两列等宽布局 - 使用
ForEach
遍历商品数组,为每个商品创建一个GridItem
- 每个
GridItem
包含商品图片、名称和价格 - 添加圆角、背景色和阴影效果,提升视觉体验
- 使用
三、布局技巧与最佳实践
3.1 侧边栏宽度设置
在示例中,我们将侧边栏的宽度设置为80%
,这是相对于SideBarContainer
默认分配给侧边栏的宽度(200vp)的百分比。在实际应用中,可以根据需要调整这个值,或者使用sideBarWidth
属性直接设置侧边栏的宽度。
// 方式1:设置侧边栏子组件的宽度
Column() {
// 侧边栏内容
}
.width('80%')
// 方式2:设置SideBarContainer的sideBarWidth属性
SideBarContainer(SideBarContainerType.Overlay) {
// 侧边栏内容
// 主内容区
}
.sideBarWidth(300)
3.2 响应式布局
为了适应不同屏幕尺寸,我们可以结合媒体查询来实现响应式布局。
// 使用媒体查询调整布局
@Media({ minWidth: 600 }) {
// 大屏幕布局
.sideBarWidth(400)
.columnsTemplate('1fr 1fr 1fr') // 三列布局
}
@Media({ maxWidth: 599 }) {
// 小屏幕布局
.sideBarWidth(300)
.columnsTemplate('1fr 1fr') // 两列布局
}
3.3 筛选条件的初始化和重置
在实际应用中,我们可能需要提供重置筛选条件的功能,或者根据用户之前的选择初始化筛选条件。
// 重置筛选条件
private resetFilters(): void {
this.priceRange = [0, 1000]
this.selectedCategories = []
}
// 初始化筛选条件
private initFilters(): void {
// 从持久化存储或网络请求获取初始值
const savedPriceRange = AppStorage.Get<number[]>('priceRange')
if (savedPriceRange) {
this.priceRange = savedPriceRange
}
const savedCategories = AppStorage.Get<string[]>('selectedCategories')
if (savedCategories) {
this.selectedCategories = savedCategories
}
}
3.4 筛选条件的保存
为了提升用户体验,我们可以保存用户的筛选条件,以便在下次打开应用时恢复。
// 保存筛选条件
private saveFilters(): void {
AppStorage.SetOrCreate<number[]>('priceRange', this.priceRange)
AppStorage.SetOrCreate<string[]>('selectedCategories', this.selectedCategories)
}
四、交互优化
4.1 价格范围验证
在实际应用中,我们需要确保最低价不高于最高价,可以添加验证逻辑:
// 第一个滑块(最低价)
Slider({
min: 0,
max: 1000,
step: 50,
value: this.priceRange[0],
style: SliderStyle.OutSet
})
.blockColor('#ff4500')
.onChange((value: number) => {
// 确保最低价不高于最高价
if (value <= this.priceRange[1]) {
this.priceRange[0] = value
} else {
this.priceRange[0] = this.priceRange[1]
}
})
// 第二个滑块(最高价)
Slider({
min: 0,
max: 1000,
step: 50,
value: this.priceRange[1],
style: SliderStyle.OutSet
})
.blockColor('#ff4500')
.onChange((value: number) => {
// 确保最高价不低于最低价
if (value >= this.priceRange[0]) {
this.priceRange[1] = value
} else {
this.priceRange[1] = this.priceRange[0]
}
})
4.2 筛选条件预览
为了提供更好的用户体验,我们可以在侧边栏中显示当前选中的筛选条件数量:
Button('筛选', { type: ButtonType.Capsule })
.width(80)
.onClick(() => {
this.isSideBarShow = true
})
// 如果有筛选条件,显示数量
if (this.selectedCategories.length > 0 || this.priceRange[0] > 0 || this.priceRange[1] < 1000) {
Badge({
count: this.getFilterCount(),
position: BadgePosition.Right,
style: { color: '#fff', fontSize: 10, badgeSize: 16, badgeColor: '#ff4500' }
})
}
// 获取筛选条件数量
private getFilterCount(): number {
let count = 0
if (this.priceRange[0] > 0 || this.priceRange[1] < 1000) {
count += 1 // 价格筛选算一个条件
}
count += this.selectedCategories.length // 每个选中的分类算一个条件
return count
}
4.3 添加重置按钮
在侧边栏中添加重置按钮,方便用户快速清除所有筛选条件:
Row() {
Button('重置', { type: ButtonType.Normal })
.width('40%')
.backgroundColor('#f5f5f5')
.fontColor('#333')
.onClick(() => {
this.resetFilters()
})
Button('确定', { type: ButtonType.Capsule })
.width('40%')
.backgroundColor('#ff4500')
.onClick(() => {
this.isSideBarShow = false
console.log('应用筛选条件:', this.priceRange, this.selectedCategories)
})
}
.width('100%')
.justifyContent(FlexAlign.SpaceAround)
.margin({ top: 20, bottom: 20 })
五、总结
本教程详细介绍了如何使用HarmonyOS NEXT的SideBarContainer
组件实现电商应用的商品筛选侧边栏。 SideBarContainer
组件为电商应用提供了一种简单而强大的方式来实现商品筛选功能,通过合理使用这个组件,可以创建出用户体验良好的电商应用界面。 在下一篇教程中,我们将深入探讨如何为电商应用添加更多交互功能和状态管理,例如筛选结果的实时预览、多级筛选、排序功能等,敬请期待!
- 0回答
- 4粉丝
- 0关注
- [HarmonyOS NEXT 实战案例二:SideBarContainer] 侧边栏容器实战:电商应用商品筛选侧边栏 进阶篇
- [HarmonyOS NEXT 实战案例一:SideBarContainer] 侧边栏容器实战:新闻阅读应用侧边栏布局 基础篇
- [HarmonyOS NEXT 实战案例一:SideBarContainer] 侧边栏容器实战:新闻阅读应用侧边栏布局 进阶篇
- [HarmonyOS NEXT 实战案例三:SideBarContainer] 侧边栏容器实战:社交应用联系人列表 基础篇
- [HarmonyOS NEXT 实战案例四:SideBarContainer] 侧边栏容器实战:音乐播放器侧边栏 - 播放列表与歌单管理 基础篇
- [HarmonyOS NEXT 实战案例三:SideBarContainer] 侧边栏容器实战:社交应用联系人列表 进阶篇
- [HarmonyOS NEXT 实战案例:电商应用] 基础篇 - 垂直分割布局打造商品详情页
- [HarmonyOS NEXT 实战案例:电商应用] 基础篇 - 垂直分割布局打造商品详情页
- [HarmonyOS NEXT 实战案例四:SideBarContainer] 侧边栏容器实战:音乐播放器侧边栏 - 播放列表与歌单管理 进阶篇
- [HarmonyOS NEXT 实战案例一] 电商首页商品网格布局(下)
- [HarmonyOS NEXT 实战案例一] 电商首页商品网格布局(上)
- [HarmonyOS NEXT 实战案例:电商应用] 进阶篇 - 交互功能与状态管理
- [HarmonyOS NEXT 实战案例:电商应用] 进阶篇 - 交互功能与状态管理
- HarmonyOS NEXT 头像制作项目系列教程之 --- 侧边栏容器实现与应用
- [HarmonyOS NEXT 实战案例十五] 电商分类导航网格布局(进阶篇)