# 45号应用:菜单演示 — 可展开手风琴菜单的设计与实现
一、应用概述菜单演示Accordion Menu Demo是一个可展开/收起的手风琴菜单应用。四个主菜单美食、娱乐、运动、学习各自包含 4 个子项点击主菜单展开子项列表再次点击收起。菜单项带有展开指示箭头▶/▼和投影阴影子项以圆角列表形式展示。手风琴菜单Accordion是移动应用中最常用的导航模式之一广泛用于设置页面、分类浏览、FAQ 等场景。在 HarmonyOS 中这个应用展示了List 组件的嵌套渲染、条件展开动画和阴影样式的典型用法。二、技术架构2.1 应用结构┌─────────────────────────────────────┐ │ ‹ 返回 菜单演示 │ ├─────────────────────────────────────┤ │ ┌─ 美食 ▶ ─┐│ ← 主菜单 │ └────────────────────────────────┘│ │ ┌─ 娱乐 ▼ ─┐│ ← 展开状态 │ │ • 电影 ││ │ │ • 音乐 ││ ← 子菜单 │ │ • 游戏 ││ │ │ • 阅读 ││ │ └────────────────────────────────┘│ │ ┌─ 运动 ▶ ─┐│ │ ├─ 学习 ▶ ─┤│ ├─────────────────────────────────────┤ │ 点击主菜单展开/收起子项 │ └─────────────────────────────────────┘2.2 数据模型interface MenuItem { id: number; name: string; // 主菜单名称含 emoji sub: string[]; // 子项名称数组 expanded: boolean; // 是否展开 }2.3 状态变量变量类型用途menusMenuItem[]4 个菜单项目驱动列表渲染三、核心代码深度解析3.1 手风琴展开/收起逻辑toggleMenu(id: number): void { const newMenus: MenuItem[] this.menus.concat(); for (let i 0; i newMenus.length; i) { if (newMenus[i].id id) { newMenus[i] { id: newMenus[i].id, name: newMenus[i].name, sub: newMenus[i].sub, expanded: !newMenus[i].expanded }; } } this.menus newMenus; }手风琴 vs 普通展开当前实现是独立展开模式——每个菜单项独立切换互不影响。如果要实现经典手风琴模式展开一个时自动收起其他只需稍作修改toggleMenuAccordion(id: number): void { this.menus this.menus.map(menu ({ ...menu, expanded: menu.id id ? !menu.expanded : false })); }经典手风琴模式使用map将所有非目标菜单的expanded设为false实现「最多一个展开」的效果。3.2 List ForEach 嵌套渲染菜单的整体结构是 List 中嵌套多层 ColumnList() { ForEach(this.menus, (menu: MenuItem) { ListItem() { Column() { // 主菜单行 Row() { Text(menu.name).fontSize(18).fontWeight(FontWeight.Medium).layoutWeight(1) Text(menu.expanded ? ▼ : ▶).fontSize(16).fontColor(#aaa) } .padding(16).backgroundColor(#fff).borderRadius(12) .shadow({ radius: 2, color: #20000000, offsetY: 1 }) .onClick(() this.toggleMenu(menu.id)) // 子菜单区域条件渲染 if (menu.expanded) { Column() { ForEach(menu.sub, (s: string) { Row() { Text(•).fontSize(16).fontColor(#0077FF).margin({ left: 20, right: 8 }) Text(s).fontSize(15).fontColor(#555) } .padding({ top: 10, bottom: 10, left: 16 }).width(90%) .backgroundColor(#f5f5f5).borderRadius(8).margin({ bottom: 4 }) .alignSelf(ItemAlign.Center) }) } .margin({ top: 4 }).padding(4).backgroundColor(#fafafa).borderRadius(8) } } } }, (menu: MenuItem) menu.id.toString()) } .layoutWeight(1).width(92%).padding({ top: 8 })嵌套渲染的关键结构List └── ForEach (menus) └── ListItem └── Column ├── Row (主菜单: emoji 名称 箭头) └── if (expanded) └── Column └── ForEach (sub) └── Row (子项: • 名称)为什么用 Column 而非直接展开主菜单使用 Row子菜单使用 Column 嵌套这是因为Row 让 emoji、名称、箭头在同一行水平排列Column 让子项垂直排列在主菜单下方Column 将主菜单和子菜单组合成一个逻辑单元便于 ListItem 管理3.3 展开指示箭头Text(menu.expanded ? ▼ : ▶).fontSize(16).fontColor(#aaa)这是最直观的展开指示器设计▶右三角表示「可展开点击展开」▼下三角表示「已展开点击收起」用户可以通过箭头的方向直观判断当前菜单的状态无需阅读文字说明。3.4 阴影与样式.shadow({ radius: 2, color: #20000000, offsetY: 1 })shadow 属性详解参数值说明radius2阴影模糊半径越大阴影越柔和扩散color#20000000阴影颜色前两位 20 是透明度约 12%后六位 000000 是黑色offsetX未设置默认 0水平偏移量offsetY1垂直向下偏移 1vp产生微微下沉的效果这种阴影效果模拟了 Material Design 的 elevation海拔高度理念——卡片海拔越高阴影越明显。这里的radius: 2, offsetY: 1营造了轻微的「浮起」效果让主菜单看起来是可以点击的交互元素。四、HarmonyOS 特色功能深度解析4.1 条件渲染与展开动画if (menu.expanded) { Column() { ForEach(menu.sub, (s: string) { // 子项内容 }) } .margin({ top: 4 }).padding(4).backgroundColor(#fafafa).borderRadius(8) }ArkUI 的if条件渲染是声明式的——当menu.expanded变化时框架自动处理子组件的创建和销毁expanded行为false→true创建 Column 及其子组件插入到 UI 树true→false销毁 Column 及其子组件从 UI 树移除当前局限这个实现是「显示/隐藏」而非「动画展开/收起」。子菜单是突然出现的没有过渡动画。添加展开动画的改进方案// 方法一使用 animation 属性 Column() .height(menu.expanded ? subHeight : 0) .opacity(menu.expanded ? 1 : 0) .animation({ duration: 300, curve: Curve.FastOutSlowIn }) // 方法二使用 animateTo 显式动画 animateTo({ duration: 300 }, () { this.menus[idx].expanded !this.menus[idx].expanded; })4.2 List 组件与滚动List是 ArkUI 中用于垂直滚动的容器组件List() .layoutWeight(1) // 充满父容器剩余空间 .width(92%) .padding({ top: 8 })layoutWeight(1)的作用让 List 占据 Column 中除导航栏和底部提示文字外的所有垂直空间当菜单展开超过一屏时List 自动变为可滚动无需手动设置scrollable属性List 默认支持滚动4.3 alignSelf 与子项居中.alignSelf(ItemAlign.Center)这个属性让子项在交叉轴上居中对齐。在Column容器中alignSelf覆盖了父容器的alignItems设置。这里子项宽度设为90%通过alignSelf(ItemAlign.Center)在父容器中水平居中。五、UI/UX 设计分析5.1 视觉层级第一层主菜单白色背景 阴影 18pt 字体 第二层子菜单容器浅灰背景 #fafafa 圆角 第三层子项更浅的背景 #f5f5f5 8px 圆角三层背景色递减主菜单#fff纯白子菜单容器#fafafa最浅灰子项#f5f5f5浅灰这种嵌套灰度的视觉语言帮助用户理解层级关系。5.2 底部提示Text(点击主菜单展开/收起子项).fontSize(13).fontColor(#aaa).margin({ bottom: 12 })底部的提示文字是 UX 中的引导性文案帮助用户理解交互方式。对于菜单这种直觉性较强的交互模式提示文字可以较小13pt且颜色较淡#aaa不占据视觉焦点但在需要时提供指引。5.3 emoji 图标系统四个主菜单均使用 emoji 作为图标 美食 — 食物 emoji直觉关联 娱乐 — 游戏手柄代表娱乐 运动 — 跑步的人代表运动 学习 — 书本代表学习Emoji 作为图标的好处是无需导入图标库、国际化友好、跨平台兼容。HarmonyOS 对 emoji 的渲染支持良好显示效果一致。六、最佳实践与优化建议6.1 当前代码亮点简洁的数据模型MenuItem接口清晰子项使用字符串数组而非对象数组简化数据结构不可变更新模式toggleMenu创建新对象新数组确保 State 响应视觉层级分明三层背景色递进层次感强箭头方向反馈▶/▼ 直观指示展开状态6.2 可优化方向// 优化建议 1添加展开/收起动画 // 使用 animateTo 实现平滑展开 toggleMenuWithAnim(id: number): void { animateTo({ duration: 250, curve: Curve.FastOutSlowIn }, () { const newMenus this.menus.map(m m.id id ? { ...m, expanded: !m.expanded } : m ); this.menus newMenus; }); } // 优化建议 2经典手风琴模式只展开一个 toggleMenuAccordion(id: number): void { this.menus this.menus.map(menu ({ ...menu, expanded: menu.id id ? !menu.expanded : false })); } // 优化建议 3添加图标/角标 // 子项右侧显示数字角标 Row() { Text(s).fontSize(15).fontColor(#555).layoutWeight(1) Text(3).fontSize(12).fontColor(#fff).padding(4) .backgroundColor(#F44336).borderRadius(10) } // 优化建议 4支持多级菜单 interface MultiLevelMenu { id: number; name: string; children?: MultiLevelMenu[]; // 递归定义 expanded: boolean; } // 优化建议 5自定义展开图标 // 使用旋转动画的箭头 Image(this.menu.expanded ? $r(app.media.arrow_down) : $r(app.media.arrow_right)) .rotate({ angle: this.menu.expanded ? 180 : 0 }) .animation({ duration: 200 })6.3 性能优化List 虚拟化当前 4 个菜单项远未达到性能瓶颈。如果扩展到 100 菜单List 的虚拟化特性会自动优化渲染性能避免深层嵌套目前主菜单→子菜单只有两层渲染开销极低。如果实现多级菜单3 层应考虑使用递归组件或树形控件子项复用同一级别的子项结构相同HarmonyOS 的组件复用机制会自动优化七、总结与扩展菜单演示应用展示了 ArkUI 中实现手风琴菜单的完整模式知识点应用位置重要程度List ForEach 列表渲染主菜单列表★★★★★条件渲染 if/else子菜单展开/收起★★★★★不可变对象更新toggleMenu★★★★☆shadow 阴影样式主菜单卡片★★★☆☆alignSelf 对齐子项居中★★★☆☆展开箭头指示交互反馈★★★☆☆扩展思路嵌套多级菜单支持三级及以上菜单层级用于复杂的设置页面图标系统为每个菜单项添加 Material Design 图标使用 HarmonyOS 的图标资源展开动画使用animateTo或transition属性添加平滑展开/收起动画搜索过滤添加搜索框实时过滤匹配的菜单项状态保持使用StorageProp或AppStorage在页面切换时保持展开状态自定义主题支持主菜单颜色、字体、圆角等样式自定义手风琴菜单是移动应用中最经典的导航模式之一。通过这个案例你可以掌握 List 嵌套渲染、条件展开和交互状态管理的基本模式这些模式可以复用到任何需要「分类展开」的场景中。

相关新闻

红黑树规则

红黑树规则

红黑树 性质 根节点都是黑色红色节点的子节点必然是黑色每个节点不是红色就是黑色叶子节点都是黑色 旋转 旋转与颜色变换规则 所有插入的节点默认是红色 颜色变换 当前节点的父节点是红色 且 其祖父节点的另一个子节点(叔叔节点)也是红色 将父节点和叔叔节点变成黑色 祖父节点变…

2026/9/18 23:09:12 阅读更多 →
木箱采购全攻略:从选型到验收的实用指南

木箱采购全攻略:从选型到验收的实用指南

这类木箱、配件箱、木托盘和胶合板木箱的采购问题,最实际的不是看广告词,而是先搞清楚你的具体用途、承重要求和运输环境。很多第一次采购的人容易只看价格或规格表,结果收到货后发现尺寸不对、承重不够或运输途中损坏。下面按实际采购决策顺…

2026/9/6 17:25:21 阅读更多 →
粒子群优化算法(PSO)原理、实现与应用全解析

粒子群优化算法(PSO)原理、实现与应用全解析

1. 从鸟群觅食到算法核心:粒子群算法的直觉理解如果你曾经观察过鸟群在空中协同飞行,或者鱼群在水里灵活转向,你可能会惊叹于这种看似没有指挥官的群体,却能展现出如此高效、统一的集体智慧。它们是如何做到的呢?这个源…

2026/9/21 16:30:56 阅读更多 →

最新新闻

Codex 跑 Trae+Docker+SSH 插件恢复脚本:Key 用 TaoToken

Codex 跑 Trae+Docker+SSH 插件恢复脚本:Key 用 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 18:34:30 阅读更多 →
xbar 技术架构深度解析:用 Go + Wails + Svelte 重写 BitBar 的完整方案

xbar 技术架构深度解析:用 Go + Wails + Svelte 重写 BitBar 的完整方案

xbar 技术架构深度解析:用 Go Wails Svelte 重写 BitBar 的完整方案 【免费下载链接】xbar Put the output from any script or program into your macOS Menu Bar (the BitBar reboot) 项目地址: https://gitcode.com/gh_mirrors/xb/xbar 本文基于 xbar 仓…

2026/9/21 18:34:30 阅读更多 →
GSY Github App Flutter 的 Author Handoff 交接规范:构建中立、最小、可验证的 Review Bundle

GSY Github App Flutter 的 Author Handoff 交接规范:构建中立、最小、可验证的 Review Bundle

GSY Github App Flutter 的 Author Handoff 交接规范:构建中立、最小、可验证的 Review Bundle 【免费下载链接】gsy_github_app_flutter Flutter 超完整的开源项目,功能丰富,适合学习和日常使用。GSYGithubApp 系列的优势:我们目…

2026/9/21 18:34:30 阅读更多 →
HarmonyOS无线调试全流程指南:从配对原理到故障排查

HarmonyOS无线调试全流程指南:从配对原理到故障排查

1. 摆脱数据线的执念:无线调试到底改变了什么先聊个最实际的问题:你上一次因为USB线材问题浪费了多少时间?我做鸿蒙应用开发这几年,前前后后用过不下十条数据线。原装的、第三方的、支持快充的、编织网包的,看起来差别…

2026/9/21 18:34:30 阅读更多 →
在 Vercel 上部署 Hono:从本地开发到云端发布的完整工作流

在 Vercel 上部署 Hono:从本地开发到云端发布的完整工作流

CLI后端云原生 【免费下载链接】vercel Develop. Preview. Ship. 项目地址: https://gitcode.com/gh_mirrors/ve/vercel 点击查看 免费下载 导读 本文以 vercel 仓库中的 Hono 示例 为主线,完整讲解一个基于 Web 标准的 Hono 应用如何通过 Vercel CLI …

2026/9/21 18:34:30 阅读更多 →
mustbe踩坑实录:3个高频面试题背后的版本升级陷阱

mustbe踩坑实录:3个高频面试题背后的版本升级陷阱

mustbe踩坑实录:3个高频面试题背后的版本升级陷阱 版本升级后 API 全变了?别慌,这不仅是你的噩梦,更是面试官最爱挖的坑。 去年重构项目时,我把一个核心校验模块从 Python 3.8 迁到…

2026/9/21 18:33:29 阅读更多 →

日新闻

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程 【免费下载链接】agentic-awesome-skills AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and …

2026/9/21 0:00:01 阅读更多 →
gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析

gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析

gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析 【免费下载链接】gin-vue-admin 🚀ViteVue3Gin拥有AI辅助的基础开发平台,企业级业务AI开发解决方案,内置mcp辅助服务,内置skills管理,…

2026/9/21 0:00:01 阅读更多 →
Wox 全功能插件开发实战指南:基于 Python / Node.js 宿主与 WebSocket 的持久化插件体系

Wox 全功能插件开发实战指南:基于 Python / Node.js 宿主与 WebSocket 的持久化插件体系

桌面应用AI 应用插件系统 【免费下载链接】Wox A cross-platform launcher that simply works 项目地址: https://gitcode.com/gh_mirrors/wo/Wox 点击查看 免费下载 全功能插件(Full-featured Plugin)是 Wox 三类插件实现方式中能力最完整的…

2026/9/21 0:00:01 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/21 3:13:20 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/21 2:19:36 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →