2026-05-22 11:21:57 +08:00
|
|
|
|
# StrayFog 框架 UI组件使用指南
|
|
|
|
|
|
|
|
|
|
|
|
## 一、常用UI组件(框架封装)
|
|
|
|
|
|
|
|
|
|
|
|
### 1.1 SFUI_Button组件
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
SFUI_Button btn = GetComponent<SFUI_Button>();
|
|
|
|
|
|
|
2026-05-22 14:40:44 +08:00
|
|
|
|
// 添加点击事件(带防重复注册保护)
|
|
|
|
|
|
btn.OnAddClickListener -= OnBtnClick;
|
2026-05-22 11:21:57 +08:00
|
|
|
|
btn.OnAddClickListener += OnBtnClick;
|
|
|
|
|
|
|
|
|
|
|
|
// 添加鼠标进入/退出事件
|
2026-05-22 14:40:44 +08:00
|
|
|
|
btn.OnAddEnterListener -= OnBtnEnter;
|
2026-05-22 11:21:57 +08:00
|
|
|
|
btn.OnAddEnterListener += OnBtnEnter;
|
2026-05-22 14:40:44 +08:00
|
|
|
|
|
|
|
|
|
|
btn.OnAddExitListener -= OnBtnExit;
|
2026-05-22 11:21:57 +08:00
|
|
|
|
btn.OnAddExitListener += OnBtnExit;
|
|
|
|
|
|
|
|
|
|
|
|
// 设置按钮状态
|
|
|
|
|
|
btn.SetSelfGray(true); // 设置灰色不可用
|
|
|
|
|
|
btn.interactable = false; // 设置不可交互
|
2026-05-22 14:40:44 +08:00
|
|
|
|
btn.SetSelected(true); // 设置选中状态
|
2026-05-22 11:21:57 +08:00
|
|
|
|
|
2026-05-22 14:40:44 +08:00
|
|
|
|
void OnBtnClick(GameObject go) { /* 处理点击 */ }
|
|
|
|
|
|
void OnBtnEnter(GameObject go) { /* 鼠标进入 */ }
|
|
|
|
|
|
void OnBtnExit(GameObject go) { /* 鼠标退出 */ }
|
2026-05-22 11:21:57 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-05-22 14:40:44 +08:00
|
|
|
|
### 1.2 SFUI_TextMeshProUGUI组件
|
2026-05-22 11:21:57 +08:00
|
|
|
|
|
|
|
|
|
|
```csharp
|
2026-05-22 14:40:44 +08:00
|
|
|
|
SFUI_TextMeshProUGUI txt = GetComponent<SFUI_TextMeshProUGUI>();
|
2026-05-22 11:21:57 +08:00
|
|
|
|
|
|
|
|
|
|
// 设置文本
|
|
|
|
|
|
txt.text = "Hello World";
|
|
|
|
|
|
|
|
|
|
|
|
// 设置颜色
|
|
|
|
|
|
txt.color = Color.red;
|
|
|
|
|
|
|
|
|
|
|
|
// 设置字体大小
|
|
|
|
|
|
txt.fontSize = 24;
|
|
|
|
|
|
|
|
|
|
|
|
// 设置描边
|
|
|
|
|
|
txt.outlineColor = Color.black;
|
|
|
|
|
|
txt.outlineWidth = 2;
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 1.3 SFUI_Image组件
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
SFUI_Image img = GetComponent<SFUI_Image>();
|
|
|
|
|
|
|
2026-05-22 14:40:44 +08:00
|
|
|
|
// 加载Sprite(使用框架封装方法)
|
|
|
|
|
|
img.HFSetItemIcon("Icon_Player");
|
|
|
|
|
|
|
|
|
|
|
|
// 加载远程图片
|
|
|
|
|
|
img.HFSetUrlSprite("https://example.com/icon.png");
|
2026-05-22 11:21:57 +08:00
|
|
|
|
|
|
|
|
|
|
// 设置透明度
|
|
|
|
|
|
img.SetAlpha(0.5f);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置灰度
|
|
|
|
|
|
img.SetSelfGray(true);
|
2026-05-22 14:40:44 +08:00
|
|
|
|
|
|
|
|
|
|
// 清空Sprite
|
|
|
|
|
|
img.HFClearSprite();
|
2026-05-22 11:21:57 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 1.4 SFUI_Toggle组件
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
SFUI_Toggle toggle = GetComponent<SFUI_Toggle>();
|
|
|
|
|
|
|
|
|
|
|
|
// 添加状态改变事件
|
2026-05-22 14:40:44 +08:00
|
|
|
|
toggle.onValueChanged.RemoveListener(OnToggleValueChanged);
|
2026-05-22 11:21:57 +08:00
|
|
|
|
toggle.onValueChanged.AddListener(OnToggleValueChanged);
|
|
|
|
|
|
|
|
|
|
|
|
void OnToggleValueChanged(bool isOn)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.Log($"Toggle is {isOn}");
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-05-22 14:40:44 +08:00
|
|
|
|
### 1.5 SFUI_ScrollRect组件(列表绑定模式)
|
2026-05-22 11:21:57 +08:00
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
SFUI_ScrollRect scroll = GetComponent<SFUI_ScrollRect>();
|
2026-05-22 14:40:44 +08:00
|
|
|
|
List<ItemInfo> m_items = new List<ItemInfo>();
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ 列表绑定(推荐方式)
|
|
|
|
|
|
scroll.BindEvent(
|
|
|
|
|
|
() => { return m_items.Count; }, // 数据源数量
|
|
|
|
|
|
(idx) => { return itemPrefab.gameObject; }, // 实例化模板
|
|
|
|
|
|
OnUpdateItem, // 更新回调
|
|
|
|
|
|
(item) => { // 组件获取
|
|
|
|
|
|
return item.gameObject.HFGetOrAddSimulateBehaviour<BagItemSlot>();
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// 刷新列表
|
|
|
|
|
|
scroll.ShowView(); // 显示视图
|
|
|
|
|
|
scroll.RefreshView(null); // 刷新当前视图
|
|
|
|
|
|
scroll.ScrollToIndex(0); // 滚动到指定索引
|
|
|
|
|
|
|
|
|
|
|
|
// 添加拖拽事件
|
|
|
|
|
|
scroll.OnAddBeginDragListener -= OnBeginDrag;
|
|
|
|
|
|
scroll.OnAddBeginDragListener += OnBeginDrag;
|
|
|
|
|
|
|
|
|
|
|
|
void OnUpdateItem(SFUI_ScrollRectItem item)
|
2026-05-22 11:21:57 +08:00
|
|
|
|
{
|
2026-05-22 14:40:44 +08:00
|
|
|
|
var slot = item.simulateBehaviour as BagItemSlot;
|
|
|
|
|
|
slot.SetData(m_items[item.dataIdx]);
|
2026-05-22 11:21:57 +08:00
|
|
|
|
}
|
2026-05-22 14:40:44 +08:00
|
|
|
|
|
|
|
|
|
|
void OnBeginDrag(GameObject go) { /* 处理拖拽开始 */ }
|
2026-05-22 11:21:57 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 二、UI组件命名规范
|
|
|
|
|
|
|
|
|
|
|
|
### 2.1 命名规则
|
|
|
|
|
|
|
2026-05-22 13:36:49 +08:00
|
|
|
|
变量名直接使用组件名,保持与 Unity 编辑器中组件名称一致。
|
|
|
|
|
|
|
|
|
|
|
|
| 组件类型 | 示例 |
|
|
|
|
|
|
|---------|-----|
|
2026-05-22 14:40:44 +08:00
|
|
|
|
| SFUI_Button | BtnLogin, BtnClose |
|
|
|
|
|
|
| SFUI_TextMeshProUGUI | TxtTitle, TxtNum |
|
|
|
|
|
|
| SFUI_Image | ImgIcon, ImgKuang |
|
2026-05-22 13:36:49 +08:00
|
|
|
|
| SFUI_Toggle | ToggleSelect |
|
2026-05-22 14:40:44 +08:00
|
|
|
|
| SFUI_ScrollRect | BagListView, ScrollContent |
|
|
|
|
|
|
| SFUI_InputField | InputName, InputPassword |
|
|
|
|
|
|
| SFUI_GridLayoutGroup | GridItemContainer |
|
2026-05-22 13:36:49 +08:00
|
|
|
|
|
|
|
|
|
|
**命名约定**:
|
|
|
|
|
|
- 变量名 = 组件名(保持完全一致)
|
|
|
|
|
|
- 首字母大写,采用 PascalCase 命名风格
|
2026-05-22 14:40:44 +08:00
|
|
|
|
- 前缀说明:Btn(按钮)、Txt(文本)、Img(图片)、Toggle(开关)、Scroll(滚动)、Input(输入框)、Grid(网格)
|
2026-05-22 11:21:57 +08:00
|
|
|
|
|
|
|
|
|
|
### 2.2 层级结构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
WindowRoot/
|
|
|
|
|
|
├── bg/ # 背景层
|
|
|
|
|
|
├── content/ # 内容层
|
2026-05-22 14:40:44 +08:00
|
|
|
|
│ ├── header/ # 头部(标签页、标题)
|
|
|
|
|
|
│ ├── body/ # 主体(列表、内容区)
|
|
|
|
|
|
│ └── footer/ # 底部(操作按钮)
|
|
|
|
|
|
└── top/ # 顶层(弹窗、提示、遮罩)
|
2026-05-22 11:21:57 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 三、框架封装组件列表
|
|
|
|
|
|
|
|
|
|
|
|
| 组件名 | 基类 | 扩展功能 |
|
|
|
|
|
|
|-------|------|---------|
|
2026-05-22 14:40:44 +08:00
|
|
|
|
| `SFUI_Button` | Button | 灰色状态、多事件委托、选中状态 |
|
2026-05-22 11:21:57 +08:00
|
|
|
|
| `SFUI_Text` | Text | 描边、阴影扩展 |
|
2026-05-22 14:40:44 +08:00
|
|
|
|
| `SFUI_TextMeshProUGUI` | TextMeshProUGUI | 继承原生功能 |
|
|
|
|
|
|
| `SFUI_Image` | Image | 灰度、透明度快捷设置、Sprite加载 |
|
2026-05-22 11:21:57 +08:00
|
|
|
|
| `SFUI_Toggle` | Toggle | 状态改变事件 |
|
2026-05-22 14:40:44 +08:00
|
|
|
|
| `SFUI_ScrollRect` | ScrollRect | **列表绑定模式、滚动优化** |
|
2026-05-22 11:21:57 +08:00
|
|
|
|
| `SFUI_InputField` | InputField | 输入限制 |
|
|
|
|
|
|
| `SFUI_Slider` | Slider | 数值范围限制 |
|
|
|
|
|
|
| `SFUI_Dropdown` | Dropdown | 选项管理 |
|
2026-05-22 14:40:44 +08:00
|
|
|
|
| `SFUI_GridLayoutGroup` | GridLayoutGroup | 网格布局 |
|
2026-05-22 11:21:57 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 四、UI性能优化
|
|
|
|
|
|
|
|
|
|
|
|
### 4.1 优化建议
|
|
|
|
|
|
|
2026-05-22 14:40:44 +08:00
|
|
|
|
| 优化项 | 说明 | 实现方式 |
|
|
|
|
|
|
|-------|------|---------|
|
|
|
|
|
|
| **对象池复用** | 频繁创建的UI元素使用对象池 | 使用 `HFClassEntityManager` |
|
|
|
|
|
|
| **图集打包** | 将小图标打包到SpriteAtlas | 在Unity中配置SpriteAtlas |
|
|
|
|
|
|
| **层级优化** | 合理设置Canvas层级 | 使用 `HFUIWindowLayer` 属性 |
|
|
|
|
|
|
| **避免过度绘制** | 减少重叠UI元素 | 合理设计UI布局 |
|
|
|
|
|
|
| **批量操作** | 使用RectTransform批量修改 | 禁用后批量修改再启用 |
|
|
|
|
|
|
| **列表优化** | 使用SFUI_ScrollRect绑定模式 | 自动复用列表项 |
|
|
|
|
|
|
|
|
|
|
|
|
### 4.2 列表性能优化示例
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
// ✅ 使用SFUI_ScrollRect绑定模式(自动复用)
|
|
|
|
|
|
BagListView.BindEvent(
|
|
|
|
|
|
() => { return m_items.Count; },
|
|
|
|
|
|
(idx) => { return itemPrefab.gameObject; },
|
|
|
|
|
|
OnUpdateItem,
|
|
|
|
|
|
(item) => { return item.gameObject.HFGetOrAddSimulateBehaviour<BagItemSlot>(); }
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ 数据变化时只刷新必要项
|
|
|
|
|
|
private void OnBagItemUpdate(IHFEventArg<enHFCTCEvent> arg)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 只在数据实际变化时刷新
|
|
|
|
|
|
if (HasDataChanged())
|
|
|
|
|
|
{
|
|
|
|
|
|
BagListView.ShowView();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 五、子组件开发规范
|
|
|
|
|
|
|
|
|
|
|
|
### 5.1 子组件模板
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
public class CustomSlot : AbsHFUIWindow
|
|
|
|
|
|
{
|
|
|
|
|
|
// UI组件
|
|
|
|
|
|
private SFUI_Button Btn_Item;
|
|
|
|
|
|
private SFUI_Image Img_Icon;
|
|
|
|
|
|
|
|
|
|
|
|
// 数据和回调
|
|
|
|
|
|
private Action<ItemInfo> onSelect;
|
|
|
|
|
|
private ItemInfo item;
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnRunAwake()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnRunAwake();
|
|
|
|
|
|
Btn_Item = FindUICtrlByName<SFUI_Button>("Btn_Item");
|
|
|
|
|
|
Img_Icon = FindUICtrlByName<SFUI_Image>("Img_Icon");
|
|
|
|
|
|
|
|
|
|
|
|
// 事件绑定(带防重复保护)
|
|
|
|
|
|
Btn_Item.OnAddClickListener -= OnClick;
|
|
|
|
|
|
Btn_Item.OnAddClickListener += OnClick;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void SetData(ItemInfo item, Action<ItemInfo> onSelect)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.item = item;
|
|
|
|
|
|
this.onSelect = onSelect;
|
|
|
|
|
|
|
|
|
|
|
|
// 更新UI
|
|
|
|
|
|
Img_Icon.HFSetItemIcon(item.ItemConfig.Resource);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnClick(GameObject go)
|
|
|
|
|
|
{
|
|
|
|
|
|
onSelect?.Invoke(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
2026-05-22 11:21:57 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-05-22 14:40:44 +08:00
|
|
|
|
**版本**: v1.1
|
2026-05-22 11:21:57 +08:00
|
|
|
|
**适用范围**: GiftGameX项目业务开发人员
|