ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

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

【Unity UI 进阶】仿 Element UI 打造企业级 Unity UI 组件库(05) 【Unity UI 进阶】仿 Element UI 打造企业级 Unity UI 组件库05环境与工具说明项说明代码生成本系列组件库代码由CursorAI 编程助手辅助生成与迭代再结合工程内联调、重构落地Unity 版本2022.3.50f1c1Unity 2022.3 LTSUI 框架UGUIUnityEngine.UI示例工程EleUnityUI仿 Element UI 企业级组件库建议使用Unity 2022.3 LTS同系列版本打开工程。本文实现均在2022.3.50f1c1下验证。上篇04讲完 Table 的选中、列显示与弹窗联动本篇进入独立组件EleTabs。Tabs 标签页图标、下划线指示、内容面板与 Table 内页签的区别Element 的 Tabs 是「页面级分区」上面一排标签下面一整块内容区切换时只显示对应面板。EleUnityUI 的EleTabs按同一心智模型实现并刻意与 Table 顶部的「筛选页签」区分开。本篇覆盖图标— 配置icon键走EleUiIcons下划线指示— 主题色横条跟随当前 Tab 滑动内容面板—ContentHost/Panel_{tabCode}Prefab 里可继续塞 UI与 Table 内页签的区别— 何时用EleTabs何时用EleTable.showTabs涉及文件能力主要文件运行时Runtime/Tabs/EleTabs.cs配置模型Runtime/Tabs/EleTabsModels.csConfig 资产Runtime/Tabs/EleTabsConfigAsset.cs示例生成Editor/Tabs/EleTabsSampleGenerator.cs图标Runtime/Common/EleUiIcons.csTable 内页签对比Runtime/Tables/EleTable.Structure.cs、EleTableModels.cs→EleTableTabConfig颜色继续走设计变量Primary激活文字 / 下划线 / 图标、TextPrimary/TextRegular、White、BorderLighter。一、整体结构先建立全局图EleTabs根 ├── TabBar ← 标签栏固定高度 tabBarHeight │ ├── TabRow ← 横向排布 Tab 按钮 │ │ ├── Tab_user │ │ ├── Tab_config │ │ └── … │ ├── Divider ← 底部分割线 │ └── Underline ← 蓝色下划线指示器 └── ContentHost ← 内容区stretch 填满 TabBar 下方 ├── Panel_user ← 仅当前 Tab 显示 ├── Panel_config └── Panel_role数据流EleTabsConfig.tabs → BuildTabs() 生成按钮 EnsurePanel() → SelectTab(tabCode) → ApplyActiveStyles()文字/图标色 面板显隐 → MoveUnderline()下划线对齐当前按钮 → OnTabChanged(tabCode, tabName)业务侧最小接入tabs.OnTabChanged(code,name){Debug.Log($切换到{name}({code}));};// 往某个面板里动态挂内容varpaneltabs.GetPanel(config);二、配置模型1. 单项EleTabItemConfignewEleTabItemConfig{tabName配置管理,// 显示文字tabCodeconfig,// 唯一编码 → 面板名 Panel_configiconEleUiIcons.Settings,// 图标键空无图标activetrue// 初始选中多项时取第一个 active}2. 整体EleTabsConfigpublicclassEleTabsConfig{publicstringtitleEleTabs;publicEleTableThemethemeEleTableTheme.ElementLight;publicfloattabBarHeight40f;publicfloaticonSize14f;publicfloatunderlineHeight2f;publicboolstretchPanelstrue;publicListEleTabItemConfigtabsnewListEleTabItemConfig();}示例预设EleTabsConfig.CreateSample()包含四个 Tab用户管理 / 配置管理 / 角色管理 / 定时任务补偿分别对应user/config/role/schedule图标键。3. 资源路径资源路径ConfigResources/Tabs/EleTabsSampleConfig.assetPrefabPrefabs/Tabs/EleTabsSample.prefab菜单EleUnityUI → Samples → Tabs → Generate EleTabs Sample EleUnityUI → Samples → Tabs → Spawn EleTabs Preview In Scene GameObject → EleUnityUI → Tabs → Sample三、图标1. 配置方式icon填字符串键由EleUiIcons.Get(icon)取 Sprite。常用键键常量典型用途userEleUiIcons.User用户 / 账号settingsEleUiIcons.Settings配置roleEleUiIcons.Role角色权限clockEleUiIcons.Clock定时 / 任务键不存在或 Sprite 为空时不画图标只显示文字不会报错。2. 实现步骤CreateTabButton里判断item.icon是否为空EleUiIcons.Get成功则创建ImagepreserveAspect true尺寸取config.iconSize默认 14与 Label 横向HLayout间距 6px左右 padding 12激活态icon.color Primary未激活TextRegular3. 关键代码if(!string.IsNullOrEmpty(item.icon)){varspEleUiIcons.Get(item.icon);if(sp!null){iconImgEleUiFactory.CreateImage(Icon,content,EleUiStyle.TextRegular);iconImg.spritesp;iconImg.preserveAspecttrue;floatsMathf.Max(12f,config.iconSize);EleUiFactory.AddFixedColumn(iconImg.gameObject,s,s);}}// ApplyActiveStylesif(t.icon!null)t.icon.coloron?EleUiStyle.Primary:EleUiStyle.TextRegular;扩展新图标在EleUiIcons增加常量 Get()分支 绘制函数即可Tabs 侧不用改。四、下划线指示器Element Tabs 的标志性交互底边主题色横条滑到当前标签下方。EleTabs 用独立Underline节点实现而不是给按钮加 Border避免和 TabBar 底部分割线抢层级。1. 创建BuildTabs末尾varunderImgEleUiFactory.CreateImage(Underline,tabBarRoot,EleUiStyle.Primary);underImg.raycastTargetfalse;underlineunderImg.rectTransform;underline.anchorMinnewVector2(0f,0f);underline.anchorMaxnewVector2(0f,0f);underline.pivotnewVector2(0.5f,0f);underline.sizeDeltanewVector2(48f,Mathf.Max(2f,config.underlineHeight));underline.SetAsLastSibling();// 盖在 Divider 上方underlineHeight默认 2px工业风可略加厚。2. 跟随当前 TabMoveUnderlinevoidMoveUnderline(RectTransformtabBtn){Canvas.ForceUpdateCanvases();LayoutRebuilder.ForceRebuildLayoutImmediate(tabBarRoot);varworldtabBtn.TransformPoint(tabBtn.rect.center);varlocaltabBarRoot.InverseTransformPoint(world);floatwidthMathf.Max(32f,tabBtn.rect.width*0.72f);underline.sizeDeltanewVector2(width,Mathf.Max(2f,config.underlineHeight));underline.anchoredPositionnewVector2(local.x,0f);}要点切换前先ForceRebuildLayoutImmediate避免 HLayout 未算完导致偏移宽度取按钮宽度的72%比整宽略短更接近 Element 视觉pivot在底边中点anchoredPosition.y 0贴在 TabBar 底部3. 激活样式文字boolont.tabCodecurrentTabCode;varcoloron?EleUiStyle.Primary:EleUiStyle.TextPrimary;if(t.label!null)t.label.colorcolor;按钮本身用近乎透明的Button色块 轻微 Primary 悬停高亮主要靠文字、图标和下划线而不是整块背景变色。五、内容面板Panel_{tabCode}1. 命名约定每个 Tab 对应内容区子节点ContentHost/Panel_{tabCode}例如tabCode config→Panel_config。GetPanel(config)就是取这个RectTransform。2.EnsurePanel复用优先RectTransformEnsurePanel(EleTabItemConfigitem){varname$Panel_{item.tabCode};varexistingcontentRoot.Find(name)asRectTransform;if(existing!null){EleUiFactory.Stretch(existing);returnexisting;}varpanelEleUiFactory.CreateImage(name,contentRoot,EleUiStyle.White);EleUiFactory.Stretch(panel.rectTransform);// 首次创建时加占位 LabelPrefab 里可删returnpanel.rectTransform;}已存在的面板不会销毁你在 Prefab 里手动加的子 UITable、表单、图表会在Rebuild后保留。3. 显隐逻辑voidApplyActiveStyles(){foreach(vartin_tabs){boolont.tabCodecurrentTabCode;// …文字 / 图标色…if(t.panel!null)t.panel.gameObject.SetActive(on);}}一次只显示一个Panel_*其余SetActive(false)。不做 Addressables / 懒加载时所有面板在层级里同时存在只是隐藏——简单、适合企业后台体量。4. Prefab 工作流推荐Generate EleTabs Sample生成 Prefab打开Prefabs/Tabs/EleTabsSample.prefab在ContentHost/Panel_config下拖入你的 UI或挂脚本动态创建删掉占位Placeholder文本可选Play 时Start→RebindButtons()保留子节点只重绑点击publicRectTransformGetPanel(stringtabCode){foreach(vartin_tabs)if(t.tabCodetabCode)returnt.panel;returnnull;}代码里往面板塞内容varrttabs.GetPanel(user);vartableInstantiate(tablePrefab,rt);EleUiFactory.Stretch(table.GetComponentRectTransform());5. 重建时清理策略ClearTabBarChildrenKeepPanels只清 TabBar子节点按钮、分割线、下划线会重建ContentHost里配置中仍存在的Panel_{tabCode}保留配置删掉的 Tab 对应面板才销毁这样改tabs列表后点「按 Config 重建 Tabs UI」不会误删你辛苦摆好的面板内容。六、与 Table 内筛选页签的区别这是本篇最容易混淆的一点名字都叫 Tab职责完全不同。1. 对照表维度EleTabs独立组件EleTable.showTabs表内页签定位页面 / 模块级分区同一张表的数据分类筛选配置EleTabsConfig→EleTabItemConfigtabCode/tabName/iconEleTableConfig.tabs→EleTableTabConfigkey/label内容区Panel_{tabCode}整块 UI 切换没有独立面板始终是同一张表切换后果显示/隐藏面板OnTabChanged(code, name)_activeTabKey key→回到第 1 页→RequestCurrentPage()视觉文字 图标 滑动下划线小按钮块TabActive/TabIdle背景色典型场景「用户管理 | 角色管理 | 系统配置」三个子页「全部 | 进行中 | 已归档」筛同一数据源与查询栏无关常与queryBar关键字、状态下拉叠加使用Config 里已写明[Header(页签表内筛选 Tab不是独立 EleTabs)]publicboolshowTabs;publicListEleTableTabConfigtabs;2. Table 内页签实现精简voidBuildTabs(){tabsRoot.gameObject.SetActive(config.showTabsconfig.tabs.Count0);foreach(vartabinconfig.tabs){boolactivetab.key_activeTabKey;varbtnEleUiFactory.CreateEleButton($Tab_{tab.key},tabsRoot,tab.label,...);varkeytab.key;btn.onClick.AddListener((){_activeTabKeykey;BuildTabs();// 刷新按钮高亮OnTabChanged?.Invoke(key);_page1;RequestCurrentPage();// 重新拉表数据});}}业务在OnTabChanged或OnRequestPage里根据ActiveTabKey过滤数据Demo 里也可配合statusFilter。3. 和「筛选」QueryBar 的关系Table 还有一套查询栏showQueryEleTableQueryBar页签 Tab粗粒度分类如业务线、单据状态组查询栏细粒度条件关键字、日期、下拉枚举状态筛选showStatusFilters历史 / 新增等行状态走statusFilter字段三者可并存但都不会创建Panel_*——数据始终绑定到同一个EleTable实例。4. 选型建议需要切换「整块不同 UI」 → EleTabs 各 Panel 里放 Table / 表单 / 图表 需要切换「同一表格不同数据集」 → EleTable.showTabs OnRequestPage 里按 key 过滤 需要临时搜几条 → queryBar不必为此单独做 EleTabs常见组合外层EleTabs分模块某个Panel_*里再放一张EleTable表内页签管该模块下的数据视图。七、API 与生命周期API / 事件说明SetConfig(config, rebuild)换配置并重建Rebuild()/EditorRebuild()编辑器按钮「按 Config 重建 Tabs UI」SelectTab(tabCode, notify)代码切换notifyfalse不抛事件GetPanel(tabCode)取内容面板CurrentTabCode/CurrentTabName当前选中OnTabChanged(tabCode, tabName)生命周期Awake→ApplyThemeStart若未 Build 则Rebuild()若 Prefab 已构建则RebindButtons() 恢复currentTabCode初始 Tab优先currentTabCode序列化值 → 否则第一个activetrue→ 否则列表第一项八、落地检查清单每个tabCode唯一且与Panel_{tabCode}一致图标键能在EleUiIcons.Get里解析切换 Tab 时下划线是否对齐、文字/图标是否变Primary非当前Panel_*是否SetActive(false)Prefab 里手改面板内容后Play 是否仍在RebindButtons路径从 Config 删掉某个 Tab 后对应孤立面板是否被清理不要把「筛表」需求硬塞进EleTabs——应使用EleTable.showTabs验证菜单EleUnityUI → Samples → Tabs → Generate EleTabs Sample EleUnityUI → Samples → Tabs → Spawn EleTabs Preview In Scene九、小结EleTabs 标签栏 下划线 多面板配置驱动Panel_{tabCode}可在 Prefab 扩展图标走EleUiIcons键激活态与下划线同色Primary下划线独立节点 布局刷新后按按钮中心定位宽度约为按钮 72%重建保面板只清 TabBarContentHost 按 tabCode 复用Table 内页签是数据筛选无Panel_*切换会RequestCurrentPage——与EleTabs互补而非替代系列回顾与下篇篇内容03Table 上多行表头、拖宽、排序、分页04Table 下选中、斑马纹、列显示、工具栏与弹窗05Tabs图标、下划线、内容面板、与表内页签区别本文06NavMenu 导航条13 级菜单、maxDepth、顶栏与内容区联动以及和 Tabs 组合成典型后台布局。若你在 UGUI 里做过「Tab 内容被父级 Layout 挤没高度」或「下划线 Play 才偏一格」欢迎留言——ContentHost用手工锚点 stretch、切换前ForceRebuildLayoutImmediate都是为这类坑准备的。
返回列表