HarmonyOS 鸿蒙Next中实现菜单凹陷效果
HarmonyOS 鸿蒙Next中实现菜单凹陷效果 一、需求:
一级分类模块,菜单tab点击效果要求UI实现如下效果:

选中的模块左边两个圆角,右边相邻两个模块分别上一个模块右下角圆角、下一个右上角圆角,做成一个凹陷的效果,想必这样描述很多同学就已经有思路了,可是一开始需求是说做一个凹槽,这样的描述,容易引起开发进入误区,我就是这样,进了死胡同,后来是借鉴了ios的实现方案,才明白描述的重要性,网上的方案是要使用canvas进行路径绘制,太过于麻烦,而且效果不佳,在此我就直接说鸿蒙的实现了,so easy:
二、实现
1.一个列表肯定少不了
build() {
Row() {
List({ scroller: this.scroller }) {
LazyForEach(this.topCategories, (item: HomeCategoryModel, index: number) => {
ListItem() {
this.tabBuilder(index, item)
}
.backgroundColor(this.currentSelectedClassify !== index ? '#FFFFFF' :
'#F6F6F6')
}, (item: HomeCategoryModel, index: number) => JSON.stringify(item) + index)
}
.height('100%')
.width('27.8%')
.scrollBar(BarState.Off)
.margin({ top: 10, bottom: this.bottomSafeHeight})
- 重点来了
/**
* 左边侧边栏分类菜单
* @param index
* @param name
*/
@Builder
tabBuilder(index: number, item: HomeCategoryModel) {
RelativeContainer() {
Text(item.seoTitle)
.borderRadius({
topLeft: this.currentSelectedClassify == index && index != 0 ? 8 : 0,
bottomLeft: this.currentSelectedClassify == index ? 8 : 0,
topRight: this.currentSelectedClassify + 1 == index ? 8 : 0,
bottomRight: this.currentSelectedClassify - 1 == index ? 8 : 0
})
.width('100%')
.height(56)
.fontSize(this.currentSelectedClassify == index ? 16 : 14)
.fontWeight(this.currentSelectedClassify == index ? FontWeight.Bold : FontWeight.Regular)
.fontColor('#232323')
.textAlign(TextAlign.Center)
.backgroundColor(this.currentSelectedClassify === index ? '#FFFFFF' :
'#F6F6F6')
.onClick(() => {
// TODO:知识点: 3.点击一级列表后,通过一级列表索引获取二级列表索引,分别操作不同的Scroller对象使列表滚动到指定位置
this.currentSelectedClassify = index;
this.selectedCategoryId = item.id + ''
// 请求二级分类接口数据
this.getSubCategories()
// 左侧滑动到最后一组时,不需要显示加载更多
if (this.topCategories.totalCount() - 1 == index) {
this.isLoadingMore = false
} else {
this.isLoadingMore = true
}
})
.id('text')
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
Text()
.width(5)
.height(16)
.backgroundColor('#FE2332')
.borderRadius({ topRight: 5, bottomRight: 5 })
.id('red')
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
left: { anchor: '__container__', align: HorizontalAlign.Start }
})
.visibility(this.currentSelectedClassify === index ? Visibility.Visible : Visibility.None)
}
.height(56)
}
重要的地方格外注意:
.borderRadius({
topLeft: this.currentSelectedClassify == index && index != 0 ? 8 : 0,
bottomLeft: this.currentSelectedClassify == index ? 8 : 0,
topRight: this.currentSelectedClassify + 1 == index ? 8 : 0,
bottomRight: this.currentSelectedClassify - 1 == index ? 8 : 0
})
- 一个很容易忽视的地方,视觉误差,需要提一点:
ListItem() {
this.tabBuilder(index, item)
}
.backgroundColor(this.currentSelectedClassify !== index ? '#FFFFFF' :
'#F6F6F6')
结论:这样的思路是不是又简单,代码又清爽呢
更多关于HarmonyOS 鸿蒙Next中实现菜单凹陷效果的实战教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中,菜单凹陷效果可通过ArkUI的组件样式与状态管理实现。使用@State装饰器管理菜单项的选中状态,结合条件渲染与样式绑定,为选中项应用特定的视觉样式。例如,通过if或条件样式设置背景色、阴影或边框,以模拟凹陷感。关键是在状态变化时更新样式,确保交互反馈的即时性。
更多关于HarmonyOS 鸿蒙Next中实现菜单凹陷效果的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中实现菜单凹陷效果,你的思路非常清晰且高效。通过动态设置borderRadius的四个角,配合相邻项的圆角处理,确实能简洁地实现这种视觉效果。
你的实现有几个关键点值得肯定:
-
条件化圆角设置:通过判断当前选中项索引(
currentSelectedClassify)与相邻项的关系,动态设置每个菜单项的四个圆角半径。选中项左侧两个圆角,相邻的上下项分别设置右下角和右上角圆角,形成了自然的凹陷过渡。 -
背景色对比:通过为选中项设置白色背景(
#FFFFFF),非选中项设置浅灰色背景(#F6F6F6),增强了视觉层次感,使凹陷效果更加明显。 -
视觉细节处理:添加了红色指示条(宽度5,高度16,右侧圆角),仅在选中项显示,进一步强化了选中状态。
-
性能考虑:使用
LazyForEach进行列表渲染,优化了长列表性能。
这种实现方式相比使用Canvas绘制路径更加简洁高效,充分利用了ArkUI的声明式特性和组件化能力。代码逻辑清晰,维护性好,是典型的HarmonyOS Next最佳实践。
对于其他开发者来说,这种思路可以扩展到类似的选项卡、侧边栏导航等场景,通过灵活控制圆角和背景色,实现各种视觉设计效果。

