# 【Unity UI 进阶】仿 Element UI 打造企业级 Unity UI 组件库(06)

【Unity UI 进阶】仿 Element UI 打造企业级 Unity UI 组件库(06)

环境与工具说明

项 说明
代码生成 本系列组件库代码由 Cursor(AI 编程助手)辅助生成与迭代,再结合工程内联调、重构落地
Unity 版本 2022.3.50f1c1(Unity 2022.3 LTS)
UI 框架 UGUI(UnityEngine.UI)
示例工程 EleUnityUI(仿 Element UI 企业级组件库)
图表 XCharts(Assets/XCharts,只调用公开 API,不改插件源码)

建议使用 Unity 2022.3 LTS 同系列版本打开工程。本文实现均在 2022.3.50f1c1 下验证。上篇(05)讲完独立 Tabs;本篇是后台骨架的另一块------顶部导航 EleNavMenu,以及与内容区 / XCharts 的联动。


企业后台常见布局:

text 复制代码
┌─────────────────────────────────────────┐
│  Logo  首页  系统管理 ▼  流程控制 ▼  关于   │  ← EleNavMenu 顶栏
├─────────────────────────────────────────┤
│  ContentHost / Page_{code}              │  ← 业务页(示例用 XCharts 填充)
│  (首页四宫格 / 用户柱状图 / ...)            │
└─────────────────────────────────────────┘

EleNavMenu 仿 Element 顶栏:一级横排、二级下拉、三级侧出;深度由 maxDepth 控制。选中叶子抛 OnNavSelected(code, path),由业务切换内容。Demo 里用 EleNavMenuChartDemoHost 只做显隐切换,页面与图表在 Editor Generate 时烘焙进 Prefab。

本篇覆盖:

  1. 配置与 maxDepth / 间距
  2. 一级项布局、悬停 / 选中高亮、可点击命中区
  3. 父项默认页 + 点击展开子菜单(挂根 Canvas)
  4. Prefab 生成约定(禁止运行时拼装兜底)
  5. 与 XCharts 内容区联动

涉及文件:

能力 主要文件
运行时导航 Runtime/NavMenu/EleNavMenu.cs
配置模型 Runtime/NavMenu/EleNavMenuModels.cs
Config 资产 Runtime/NavMenu/EleNavMenuConfigAsset.cs
Demo 宿主(只切页) Runtime/NavMenu/EleNavMenuChartDemoHost.cs
图表尺寸适配 Runtime/NavMenu/EleNavMenuXChartsLayout.cs
Editor 烘焙页面 Editor/NavMenu/EleNavMenuChartPageBuilder.cs
示例生成 Editor/NavMenu/EleNavMenuSampleGenerator.cs

颜色走 设计变量 :顶栏 HeaderBg,激活 / 悬停 Primary,文字 TextPrimary / TextRegular,下拉白底 + Border 描边。

工程约定(.cursor/rules/eleunityui-conventions.mdc):

  1. 不改插件(含 XCharts)
  2. 新增代码写中文注释
  3. Prefab 用 Generate 烘焙;运行时禁止缺啥建啥

一、整体结构

1. Demo Prefab 层级

text 复制代码
EleNavMenuDemo(全屏壳)
├── ContentHost                         ← 内容在下
│   ├── Page_home                       ← 首页四宫格(XCharts)
│   ├── Page_user / Page_role / ...
│   ├── Page_flow_overview / Page_flow_nodes
│   └── Page_about
└── EleNavMenu(全屏透明根,最后绘制)
    ├── NavBar                          ← 仅顶栏不透明底
    │   └── NavRow → Logo + Nav_* 按钮
    └── DropdownHost                    ← 备用区域;实际下拉挂根 Canvas

要点:

  • 导航根全屏但 Image 透明 :给布局留高度;不能 用不透明 HeaderBg 盖住内容。
  • 只有 NavBar 画顶栏底色。
  • 下拉面板挂到根 Canvas ,sortingOrder 抬高,避免被图表挡住。

2. 数据流

text 复制代码
EleNavMenuConfig.items(children 嵌套)
    → BuildBar() 生成一级按钮(间距 itemSpacing)
    → 点击叶子 → SelectLeaf(code, path) → OnNavSelected
    → 点击父项 → 切默认叶子页 + ToggleDropdown(挂根 Canvas)
    → DemoHost.ShowPage(code) 只 SetActive Prefab 内 Page_*

业务侧最小接入:

csharp 复制代码
nav.OnNavSelected += (code, path) =>
{
    // code: 叶子编码,如 user
    // path: 如 system/user
    host.ShowPage(code);
};

二、配置模型

1. 单项 EleNavItemConfig

csharp 复制代码
new EleNavItemConfig
{
    label = "系统管理",
    code = "system",
    icon = EleUiIcons.Settings,   // 空=无图标
    enabled = true,
    children = new List<EleNavItemConfig> { /* 二级... */ }
}

2. 整体 EleNavMenuConfig

字段 含义
height 顶栏高度,默认 48
maxDepth 1=仅一级;2=可下拉二级;3=可再侧出三级
itemSpacing 一级项间距,默认 16
itemPaddingX 项内左右 padding,默认 14
showLogo / logoText 左侧品牌圆点(及可选文案)
dropdownMinWidth 下拉最小宽度
items 菜单树

3. maxDepth 对照

值 效果
1 仅一级;children 不展开
2 一级 + 向下二级
3 二级行可再侧出三级(如「权限 → 菜单权限」)

4. 示例菜单树(CreateSample)

一级 子项(有内容页)
首页 home 叶子 → Page_home
系统管理 system ▼ 用户 / 角色 / 权限(三级) → Page_user 等
流程控制 process ▼ 流程总览 / 节点监控
关于 about 叶子 → Page_about

父项本身没有 Page_system / Page_process。点父项会:

  1. 打开第一个叶子作为默认页(系统管理 → 用户管理;流程控制 → 流程总览)
  2. 展开子菜单,可再点其它子项

三、一级顶栏:间距、命中、悬停与选中

1. 布局

  • NavRow 使用 HorizontalLayoutGroup,spacing = itemSpacing
  • 按钮宽度按「图标 + 文字 + ▼ + padding」估算,标签宽只按文字,避免图标与文字脱节
  • 父项显示明显的 ▼

2. 为什么必须能点中

UGUI 对 alpha=0 的 Graphic 往往不参与射线检测。按钮底图使用极低透明度(如 0.02),文字 / 图标 raycastTarget = false,点击落到整块按钮上。

3. 悬停与选中

状态 表现
常态 近透明底 + TextPrimary
悬停 浅蓝底 + Primary 文字 / 图标
选中 更深浅蓝底 + Primary(含子路径:选中 user 时 system 也高亮)

选中判断:activeCode 或 activePath 以 code/ 为前缀。


四、子菜单(二级 / 三级)

1. 交互

  • 仅点击展开(不在悬停时自动弹出,避免闪关)
  • 再点同一父项 → 收起
  • 点面板外 → 关闭(打开后忽略 1~2 帧,防止点开即关)

2. 实现要点

text 复制代码
ShowDropdown
  → 父节点 = rootCanvas.transform(不是只有 48px 高的导航条)
  → 白底 + Outline + 子 Canvas(sortingOrder≈500)
  → 按子项数量定高:count * 40 + padding
  → 用按钮左下角屏幕坐标转到 Canvas 本地定位

三级:ShowSubmenu 贴在二级行右侧,sortingOrder 更高。

3. 踩过的坑(文档化)

现象 原因 处理
有 ▼ 但看不到下拉 导航根只有栏高,DropdownHost 高度≈0 导航根全屏透明;下拉改挂根 Canvas
内容区整页被盖住 全屏根用了不透明 HeaderBg 根 Image Color.clear,底色只在 NavBar
下拉闪一下消失 同帧「点外部关闭」 _ignoreOutsideClickUntilFrame
图表盖住下拉 排序不够 下拉独立 Canvas + 高 sortingOrder

五、Prefab 生成与运行时约定

1. 资源路径

资源 路径
Config Resources/NavMenu/EleNavMenuSampleConfig.asset
仅顶栏 Prefab Prefabs/NavMenu/EleNavMenuSample.prefab
整页 Demo Prefab Prefabs/NavMenu/EleNavMenuDemo.prefab

2. 菜单

text 复制代码
EleUnityUI → Samples → NavMenu → Generate EleNavMenu Sample   # 烘焙 Config + Prefab
EleUnityUI → Samples → NavMenu → Spawn EleNavMenu Preview In Scene  # 只实例化
EleUnityUI → Samples → NavMenu → Reset EleNavMenu Config To Preset

3. Generate 做什么(Editor)

  1. 写 / 更新 Config
  2. GenerateNavBarPrefab:顶栏样例
  3. GenerateDemoPrefab:全屏壳 + 透明导航根 + ContentHost
  4. EleNavMenuChartPageBuilder.BakeAllPages:烘焙全部 Page_* 与 XCharts
  5. FitAllChartsUnder:纠正 XCharts Init 强制的 580×300,改回 stretch

4. Spawn / Play 做什么(禁止兜底创建)

csharp 复制代码
// ✅ 只实例化 + 切已有 Page_*
PrefabUtility.InstantiatePrefab(demoPrefab);
host.CachePagesFromPrefab();
host.ShowPage("home");

// ❌ 运行时发现没有 ContentHost / Page 就 CreateRect、BuildChart

缺 Prefab 时 Spawn 弹窗提示先 Generate,不在 Spawn 里临时拼整页。

5. XCharts 注意

  • Chart 与 Image 不能同物体 (都是 Graphic)→ 挂在卡片下 ChartRoot
  • Init 在 sizeDelta 偏小时会写成 580×300 → EleNavMenuXChartsLayout.FitChartToParent 改回拉伸

六、与内容区 / Tabs 的职责划分

组件 管什么
NavMenu 跨模块导航(大分区 + 下拉)
Tabs 模块内多视图
Table.showTabs 同一张表的数据筛选(不是全局导航)
DemoHost 按 code 显隐 Page_*(可换成你自己的路由)

典型组合:顶栏 Nav → 某 Page_* 里再放 Tabs / Table。


七、API 一览

API / 事件 说明
SetConfig(config, rebuild) 换配置并重建顶栏
Rebuild() / EditorRebuild() Editor「按 Config 重建」
SelectNav(code, path, notify) 代码选中
OnNavSelected (code, path)
ActiveCode / ActivePath 当前叶子与路径
DemoHost.ShowPage(code) 只切换已烘焙页
DemoHost.CachePagesFromPrefab() 收集 Page_*

八、落地检查清单

  1. Generate 后存在 EleNavMenuDemo.prefab,且 ContentHost 下有多个 Page_*
  2. Spawn 后能看到首页四宫格;顶栏未盖住内容
  3. 一级项间距正常;悬停 / 选中高亮
  4. 父项有明显 ▼ ;点击弹出白底子菜单(Console 有 打开下拉 日志)
  5. 点「用户管理」等子项内容切换正确
  6. 未改过 Assets/XCharts 源码
  7. 改菜单配置后重新 Generate,不要依赖 Play 时自动拼页

九、小结

  1. EleNavMenu = 透明全屏根 + 不透明 NavBar + 挂根 Canvas 的下拉
  2. maxDepth / itemSpacing / Logo 配置驱动
  3. 父项 = 默认叶子页 + 点击展开子菜单;内容在子项 Page_*
  4. Demo 页面与图表 Editor 烘焙;运行时只切显隐
  5. XCharts 只作适配调用;图表 stretch 适配分辨率

系列回顾与下篇

篇 内容
04 Table 下:选中、列显示、工具栏与弹窗
05 Tabs:图标、下划线、内容面板
06 NavMenu:1~3 级、默认页、下拉、XCharts Demo(本文)

07|ContextMenu 右键菜单 :挂载目标、ShowAt、danger / divider / 子菜单,以及点外部关闭与 NavMenu 下拉的异同。

若你在 UGUI 里也遇到过「全屏导航根盖住内容」或「下拉挂在 48px 高的父节点里」,欢迎留言------透明根 + 下拉挂根 Canvas,就是为此准备的。

相关推荐
FII工业富联科技服务13 小时前
Intelligent UI重构工业软件交互:从固定界面到动态生成式交互
人工智能·ui·重构
FII工业富联科技服务16 小时前
从大模型到自主运营:Intelligent UI如何成为工业AI的新入口
人工智能·ui
qq_2529599720 小时前
ChatGPT突然长出“可操作界面”:GPT-6 Intelligent UI让答案变成计算器、地图和小游戏
gpt·ui·chatgpt
兰亭妙微UI设计公司21 小时前
兰亭妙微ui设计公司分享:从零搭建网站设计:3 个核心维度,少走设计弯路
ui
Cx330❀2 天前
Qt 多线程深度解析:从底层原理到 UI 线程与同步实战
开发语言·qt·ui·搜索引擎·性能优化·图形渲染
传奇开心果编程2 天前
【声明式UI实用开发技术学与练】第5课 表单处理:受控与非受控
ui·移动开发·开发范式·编程框架·声明式ui
传奇开心果编程2 天前
【声明式UI开发实用技术学与练】第9课 派生状态与计算
ui·移动开发·ux·编程框架·声明式ui
ZARD9962 天前
Codex 连接 Figma:让 AI 读取 Figma UI 设计稿数据
ui·figma·codex
事圆则缓2 天前
Android 一次性事件怎么设计:Channel、SharedFlow 还是 UI State?
android·ui
我命由我123452 天前
Photoshop - Photoshop 使用魔棒工具选择单独的区域
学习·ui·职场和发展·求职招聘·职场发展·学习方法·photoshop