【Unity UI 进阶】仿 Element UI 打造企业级 Unity UI 组件库(10)
环境与工具说明
| 项 | 说明 |
|---|---|
| 代码生成 | 本系列组件库代码由 Cursor(AI 编程助手)辅助生成与迭代,再结合工程内联调、重构落地 |
| Unity 版本 | 2022.3.50f1c1(Unity 2022.3 LTS) |
| UI 框架 | UGUI(UnityEngine.UI) + TextMeshPro |
| 示例工程 | EleUnityUI(仿 Element UI 企业级组件库) |
建议使用 Unity 2022.3 LTS 同系列版本打开工程。上篇(09)讲完
EleAccordion;本篇是EleDialog对话框 :模态遮罩、表单字段、确认/取消,以及和 Table 行编辑弹窗 的复用关系。
Dialog 对话框:模态 / 非模态、标题拖拽、右下角缩放、边缘收起
后台里删一行、改一行、批量改字段,几乎都绕不开「弹窗」。Element 的 Dialog 心智是:
- 遮罩可选:Modal 挡住底层;Modeless 可继续点表格
- 确认 / 取消:危险操作要二次确认
- 表单窗:按字段配置生成 Input / Select / Number...
- 可拖可缩:标题栏移动、右下角改尺寸;需要时可收到边缘
EleDialog 按同一模型实现:Alert / Confirm / Form 共用一副壳;Table 行编辑不另写弹窗 ,只调 ShowForm。
本篇覆盖:
- 模态遮罩 (
EleDialogMode.Modal/Modeless) - 表单字段与校验
- 确认 / 取消回调
- 标题拖拽 / 右下角缩放 / 边缘收起还原
- 与 Table 行编辑的复用关系
- Prefab Generate 约定
涉及文件:
| 能力 | 主要文件 |
|---|---|
| 运行时壳与交互 | Runtime/Dialog/EleDialog.cs |
| 标题拖 / 缩放把手 | EleDialogTitleDrag.cs / EleDialogResizeHandle.cs |
| 示例配置 | Runtime/Dialog/EleDialogModels.cs、EleDialogConfigAsset.cs |
| 示例宿主 | Runtime/Dialog/EleDialogSampleDemoHost.cs |
| 示例生成 | Editor/Dialog/EleDialogSampleGenerator.cs |
| 表单配置类型 | Runtime/Tables/EleTableModels.cs(EleDialogConfig / EleFormFieldConfig) |
| Table 打开弹窗 | Runtime/Tables/EleTable.Dialogs.cs |
颜色走设计变量:遮罩半透明黑、面板 PanelBg、标题栏 HeaderBg、主按钮 Primary。
工程约定:不改第三方插件;新增 C# 写中文注释;Generate 烘焙 EleDialogHost 壳(Overlay + Panel + ResizeHandle),运行时缺引用打日志,不在 Demo 路径「缺啥建啥」。
一、整体结构
1. Prefab 层级(示例)
text
EleDialogSample
├── DemoPanel ← 左侧演示按钮 + 日志
│ ├── BtnAlert / BtnConfirm
│ ├── BtnFormModal / BtnFormModeless
│ └── Log
└── EleDialogHost ← EleDialog(铺满,sortingOrder 置顶)
├── Overlay ← 模态遮罩(非模态时隐藏)
└── Panel
├── TitleBar ← Title + Collapse(---/□) + Close(×)
├── Body
│ ├── Message ← Alert/Confirm 文案;表单校验提示
│ └── Form ← 动态字段行
├── Footer ← Cancel / Ok
└── ResizeHandle ← 右下角缩放(ignoreLayout)
2. 数据流
text
ShowAlert / ShowConfirm / ShowForm
→ EnsureShell(重绑已烘焙壳)
→ ApplyChrome(标题、按钮、模态、尺寸、可拖/缩/收)
→ 用户交互
→ 拖 TitleBar → anchoredPosition
→ 拖 ResizeHandle → sizeDelta(夹最小尺寸)
→ 点 --- → 藏 Body/Footer,贴最近边缘成条;点 □ 还原
→ Ok → CollectForm + 校验 → onSubmit / onOk
→ Cancel / × → onCancel → Close
业务最小接入(独立使用):
csharp
var dlg = EleDialog.Ensure(parent);
dlg.ApplyChromeOptions(draggable: true, resizable: true, collapsible: true);
dlg.ShowConfirm("确认", "确定删除?", onOk: () => Delete(), onCancel: null);
Table 侧更常见:
csharp
table.OpenConfiguredDialog("editRow", new List<EleTableRowData> { row.Data });
// 或行操作 actionKind=Edit → 默认 key = openDialogKey ?? "editRow"
二、配置模型
1. EleDialogConfig(与 Table 共用)
| 字段 | 含义 |
|---|---|
key |
工具栏 / 行操作 openDialogKey 引用 |
title |
标题栏文案 |
mode |
Modal / Modeless |
width / minHeight |
初始尺寸 |
confirmText / cancelText / showCancel |
底栏按钮 |
bindSelectedRow |
打开时用选中行第一条填字段 |
draggable / resizable / collapsible |
拖、缩、收起 |
fields |
EleFormFieldConfig 列表 |
2. 字段类型 EleFormFieldType
| 类型 | UI |
|---|---|
| Input | 单行 TMP_InputField |
| Number | 数字内容类型 |
| TextArea | 多行 |
| Select | 按钮轮换选项(值存隐藏 Input) |
| Checkbox | Toggle,提交 "1" / "0" |
必填失败时在 Message 区用危险色提示,不关窗。
3. 示例 EleDialogSampleConfig
独立 Demo 用:默认 chrome 开关 + demoForm(结构与 Table editRow 对齐,便于对照博文 04)。
三、模态与非模态
| 模式 | Overlay | 底层可否操作 |
|---|---|---|
| Modal | 半透明黑、raycastTarget=true |
否(先关窗) |
| Modeless | 隐藏 / 透明、不挡射线 | 是(可继续点表格或 Demo 按钮) |
ShowAlert / ShowConfirm 用 bool modal 参数;ShowForm 读 config.mode。
示例按钮:
- 表单(模态) →
EleDialogMode.Modal - 表单(非模态) →
EleDialogMode.Modeless
四、拖拽、缩放、边缘收起
1. 拖标题
EleDialogTitleDrag 挂在 TitleBar:左键拖动把 eventData.delta 换算成 Canvas 本地增量,写入 _panel.anchoredPosition,并夹在 Host 矩形内。收起成条后仍可拖,松手按最近边再贴齐。
2. 右下角缩放
EleDialogResizeHandle 锚在 Panel 右下,LayoutElement.ignoreLayout=true 避免被竖排布局挤走。拖动时增大 sizeDelta,并按中心枢轴补偿 anchoredPosition,夹 minWidth / minHeight。
3. 边缘收起
| 操作 | 行为 |
|---|---|
| 点标题栏 --- | 记住位置与尺寸;隐藏 Body / Footer / ResizeHandle;缩成条贴最近边 |
| 点 □ | 还原尺寸与位置,重新显示内容区 |
贴边枚举:EleDialogDockEdge = Left / Right / Top / Bottom。
五、与 Table 行编辑的复用关系
这是本篇重点:不要为表格再写一套弹窗。
text
行操作 Edit / 工具栏 openDialogKey
→ EleTable.OpenConfiguredDialog(key, contextRows)
→ config.FindDialog(key) → EleDialogConfig
→ EleDialog.Ensure(table.transform) // Host 名 EleDialogHost
→ ShowForm(cfg, seedRow, onSubmit, onCancel)
→ OnDialogSubmitted(EleDialogSubmitRequest)
| 能力 | Dialog 独立示例 | Table 行编辑 |
|---|---|---|
| 壳 UI | Generate 烘焙 EleDialogHost |
Ensure 复用同组件 |
| 配置 | EleDialogSampleConfig.demoForm |
EleTableConfig.dialogs |
| 种子数据 | Demo 构造 EleTableRowData |
bindSelectedRow → 选中行 |
| 提交 | Demo 打日志 | OnDialogSubmitted → 业务改行 / 调接口 |
| 确认框 | ShowConfirm |
行删除 confirmBeforeExecute 等同壳 |
因此改遮罩、拖拽、缩放、收起,表格编辑窗一并受益 。字段模型仍放在 EleTableModels(历史原因),运行时组件在 Runtime/Dialog/。
六、Prefab 生成与菜单
1. 菜单
text
EleUnityUI → Samples → Dialog → Generate EleDialog Sample
EleUnityUI → Samples → Dialog → Spawn EleDialog Preview In Scene
EleUnityUI → Samples → Dialog → Reset EleDialog Config To Preset
GameObject → EleUnityUI → Dialog → Sample
Spawn 不会在缺 Prefab 时自动 Generate。
2. Generate 烘焙什么
- 左侧
DemoPanel与四个入口按钮 EleDialogHost:Overlay、Panel、TitleBar(含 Collapse/Close)、Body、Form、Footer、ResizeHandleEleDialogSampleDemoHost序列化引用
3. 运行时约定
csharp
// ✅ 壳已烘焙,EnsureShell 只 Rebind
dialog.EnsureShell();
dialog.ShowForm(cfg, seed, onSubmit, onCancel);
// ❌ Demo 里发现没有 Panel 就临时拼一棵树
缺 dialog 引用:Debug.LogError("[EleDialog] 缺少 dialog 引用,请重新 Generate Prefab")。
七、API 一览
| API / 事件 | 说明 |
|---|---|
Ensure(parent) |
获取/创建 EleDialogHost |
ApplyChromeOptions(...) |
拖 / 缩 / 收起与最小尺寸 |
ShowAlert / ShowConfirm |
警告 / 确认 |
ShowForm(config, seed, onSubmit, onCancel) |
表单窗 |
Close(invokeCancel) |
关闭 |
ToggleCollapse |
收起 ↔ 还原 |
CollectForm |
收集字段值 |
IsOpen / IsCollapsed / IsModal |
状态 |
Table:OpenConfiguredDialog / OnDialogSubmitted |
行编辑入口 |
八、落地检查清单
- Generate 后有
EleDialogSample.prefab,含EleDialogHost/Panel/ResizeHandle - Spawn 后点 Alert / Confirm / 两种表单均能打开
- 模态时遮罩挡住 Demo;非模态时可再点其它按钮
- 拖标题可移动;拖右下角可改大小(不低于最小尺寸)
- 点 --- 收到边缘成条;点 □ 还原
- 表单必填为空时提示且不关闭;提交后日志有字段值
- Table 行「编辑」仍打开同一套
EleDialog(见博文 04)
九、小结
- EleDialog = 一副壳覆盖 Alert / Confirm / Form
- Modal / Modeless 只切换 Overlay,不换组件
- 拖标题、右下角缩放、边缘收起 是窗体 chrome,与表单字段正交
- Table 行编辑 =
openDialogKey→ 同一ShowForm,业务听OnDialogSubmitted
系列回顾与下篇
| 篇 | 内容 |
|---|---|
| 04 | Table 下:工具栏、弹窗入口、OnDialogSubmitted |
| 05 | Tabs:Panel_{tabCode} |
| 09 | Accordion:手风琴与 Tabs 边界 |
| 10 | Dialog:模态、表单、拖缩收起、与 Table 复用(本文) |
11|反馈类补齐:EleMessage 页面提示 + Tooltip 用法 :UGUI 无 Message/Alert/Tooltip ------ 新建轻量 EleMessage;Tooltip 基于已有 EleUiTooltip 写清配置与用法(不另造一层壳)。
若你也在纠结「表格编辑要不要单独做 Page」:字段少、要挡操作 → Modal Dialog ;要对照表格边改边看 → Modeless;整页复杂向导 → 另开路由/面板,别硬塞 Dialog。