2026-05-22 11:21:57 +08:00
|
|
|
|
# StrayFog 框架 UI窗口开发指南
|
|
|
|
|
|
|
|
|
|
|
|
## 一、UI窗口基础
|
|
|
|
|
|
|
|
|
|
|
|
### 1.1 窗口创建流程
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
2026-05-22 14:40:44 +08:00
|
|
|
|
[HFAssetBundlePath(enHFLanguageRootFolder.ASSETS_GAME_GAMEHFRESOURCE, "UIWindows/Bag/BagWindow.prefab")]
|
|
|
|
|
|
[HFUIWindowLayer(enHFUICanvasLayer.UIWindow, enHFUIWindowLayer.Fixed, isIgnoreCloseByESC = false)]
|
|
|
|
|
|
public class BagWindow : AbsHFUIWindow
|
2026-05-22 11:21:57 +08:00
|
|
|
|
{
|
2026-05-22 13:36:49 +08:00
|
|
|
|
// ========== UI组件 ==========
|
2026-05-22 14:40:44 +08:00
|
|
|
|
private SFUI_Button BtnClose;
|
|
|
|
|
|
private SFUI_ScrollRect BagListView;
|
|
|
|
|
|
private BagTips tips;
|
|
|
|
|
|
|
|
|
|
|
|
// ========== 数据 ==========
|
|
|
|
|
|
private List<ItemInfo> m_items = new List<ItemInfo>();
|
|
|
|
|
|
private ItemInfo m_select;
|
2026-05-22 13:36:49 +08:00
|
|
|
|
|
2026-05-22 11:21:57 +08:00
|
|
|
|
protected override void OnRunAwake()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnRunAwake();
|
2026-05-22 14:40:44 +08:00
|
|
|
|
// ✅ 初始化UI组件引用
|
|
|
|
|
|
BtnClose = FindUICtrlByName<SFUI_Button>("BtnClose");
|
|
|
|
|
|
BagListView = FindUICtrlByName<SFUI_ScrollRect>("BagListView");
|
|
|
|
|
|
tips = BindUI<BagTips, SFUI_Image>("BagTips");
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ 按钮事件绑定(带防重复注册保护)
|
|
|
|
|
|
BtnClose.OnAddClickListener -= OnBtnClose;
|
|
|
|
|
|
BtnClose.OnAddClickListener += OnBtnClose;
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ 列表绑定
|
|
|
|
|
|
var itemPrefab = FindUICtrlByName<SFUI_Behaviour>("Item");
|
|
|
|
|
|
BagListView.BindEvent(
|
|
|
|
|
|
() => { return m_items.Count; },
|
|
|
|
|
|
(idx) => { return itemPrefab.gameObject; },
|
|
|
|
|
|
OnUpdateItem,
|
|
|
|
|
|
(item) => { return item.gameObject.HFGetOrAddSimulateBehaviour<BagItemSlot>(); }
|
|
|
|
|
|
);
|
2026-05-22 11:21:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnOpen(Action _onOpenComplete)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnOpen(_onOpenComplete);
|
2026-05-22 14:40:44 +08:00
|
|
|
|
// ✅ 注册全局事件监听
|
|
|
|
|
|
HFFunCatalogue.Event.TCEvent.AddListener<HFEvent_BagItemUpdate>(
|
|
|
|
|
|
enHFCTCEvent.BagItemUpdate, OnBagItemUpdate);
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ 初始化数据
|
|
|
|
|
|
RefreshBagItems();
|
2026-05-22 11:21:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnClose(Action _onCloseComplete)
|
|
|
|
|
|
{
|
2026-05-22 14:40:44 +08:00
|
|
|
|
// ✅ 取消全局事件监听
|
|
|
|
|
|
HFFunCatalogue.Event.TCEvent.RemoveListener<HFEvent_BagItemUpdate>(
|
|
|
|
|
|
enHFCTCEvent.BagItemUpdate, OnBagItemUpdate);
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ 清理资源
|
|
|
|
|
|
tips.Clear();
|
|
|
|
|
|
|
2026-05-22 13:36:49 +08:00
|
|
|
|
base.OnClose(_onCloseComplete);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-22 14:40:44 +08:00
|
|
|
|
private void OnBtnClose(GameObject go) => CloseWindow();
|
|
|
|
|
|
private void OnUpdateItem(SFUI_ScrollRectItem item) { /* 更新列表项 */ }
|
|
|
|
|
|
private void RefreshBagItems() { /* 刷新背包数据 */ }
|
2026-05-22 11:21:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 1.2 窗口打开方式
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
// 方式1:直接打开(无回调)
|
2026-05-22 14:40:44 +08:00
|
|
|
|
HFFunCatalogue.UIManager.OpenWindow<BagWindow>();
|
2026-05-22 11:21:57 +08:00
|
|
|
|
|
|
|
|
|
|
// 方式2:打开并获取窗口实例(推荐)
|
2026-05-22 14:40:44 +08:00
|
|
|
|
HFFunCatalogue.UIManager.OpenWindow<BagWindow>((win, args) => {
|
2026-05-22 11:21:57 +08:00
|
|
|
|
Debug.Log("窗口打开完成");
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 方式3:带额外参数打开
|
|
|
|
|
|
object[] extraArgs = new object[] { "param1", 123 };
|
2026-05-22 14:40:44 +08:00
|
|
|
|
HFFunCatalogue.UIManager.OpenWindow<BagWindow>((win, args) => {
|
2026-05-22 11:21:57 +08:00
|
|
|
|
// 使用窗口实例
|
|
|
|
|
|
}, extraArgs);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 二、窗口生命周期
|
|
|
|
|
|
|
|
|
|
|
|
### 2.1 生命周期方法
|
|
|
|
|
|
|
2026-05-22 14:40:44 +08:00
|
|
|
|
| 方法 | 调用时机 | 说明 | 推荐操作 |
|
|
|
|
|
|
|-----|---------|------|---------|
|
|
|
|
|
|
| `OnRunAwake` | 窗口创建时调用一次 | 初始化组件引用 | **绑定按钮事件、列表初始化** |
|
|
|
|
|
|
| `OnOpen` | 每次打开窗口时调用 | 注册事件、刷新数据 | **注册全局TC事件、初始化数据** |
|
|
|
|
|
|
| `OnClose` | 每次关闭窗口时调用 | 取消事件、清理资源 | **取消全局TC事件、清理UI状态** |
|
|
|
|
|
|
| `OnDestroy` | 窗口销毁时调用 | 释放资源 | **释放非托管资源** |
|
|
|
|
|
|
|
|
|
|
|
|
### 2.2 生命周期流程图
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
窗口创建
|
|
|
|
|
|
↓
|
|
|
|
|
|
OnRunAwake() ──→ 初始化组件、绑定按钮事件
|
|
|
|
|
|
↓
|
|
|
|
|
|
窗口打开(可多次)
|
|
|
|
|
|
↓
|
|
|
|
|
|
OnOpen() ──→ 注册TC事件、刷新数据
|
|
|
|
|
|
↓
|
|
|
|
|
|
窗口关闭(可多次)
|
|
|
|
|
|
↓
|
|
|
|
|
|
OnClose() ──→ 取消TC事件、清理资源
|
|
|
|
|
|
↓
|
|
|
|
|
|
窗口销毁
|
|
|
|
|
|
↓
|
|
|
|
|
|
OnDestroy() ──→ 释放资源
|
|
|
|
|
|
```
|
2026-05-22 11:21:57 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 三、窗口配置属性
|
|
|
|
|
|
|
|
|
|
|
|
### 3.1 常用属性
|
|
|
|
|
|
|
|
|
|
|
|
| 属性 | 说明 | 默认值 |
|
|
|
|
|
|
|-----|------|-------|
|
|
|
|
|
|
| `isIgnoreCloseByESC` | 是否忽略ESC关闭 | false |
|
|
|
|
|
|
| `isCloseOtherWindow` | 是否关闭其他窗口 | false |
|
|
|
|
|
|
| `isNeedMask` | 是否需要遮罩 | true |
|
|
|
|
|
|
| `maskType` | 遮罩类型 | 半透明 |
|
|
|
|
|
|
|
2026-05-22 14:40:44 +08:00
|
|
|
|
### 3.2 层叠配置
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
[HFUIWindowLayer(enHFUICanvasLayer.UIWindow, enHFUIWindowLayer.Fixed, isIgnoreCloseByESC = false)]
|
|
|
|
|
|
// ↑ Canvas层级 ↑ 窗口层级
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 四、子组件开发
|
|
|
|
|
|
|
|
|
|
|
|
### 4.1 物品槽组件示例
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
public class BagItemSlot : AbsHFUIWindow
|
|
|
|
|
|
{
|
|
|
|
|
|
private SFUI_Button Btn_Item;
|
|
|
|
|
|
private SFUI_Image Img_Icon;
|
|
|
|
|
|
private SFUI_TextMeshProUGUI Txt_Num;
|
|
|
|
|
|
|
|
|
|
|
|
private Action<ItemInfo, int, Vector3> selectCallback;
|
|
|
|
|
|
private ItemInfo item;
|
|
|
|
|
|
private int m_index;
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnRunAwake()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnRunAwake();
|
|
|
|
|
|
Btn_Item = FindUICtrlByName<SFUI_Button>("Btn_Item");
|
|
|
|
|
|
Img_Icon = FindUICtrlByName<SFUI_Image>("Img_Icon");
|
|
|
|
|
|
Txt_Num = FindUICtrlByName<SFUI_TextMeshProUGUI>("Txt_Num");
|
|
|
|
|
|
|
|
|
|
|
|
Btn_Item.OnAddClickListener -= OnClick;
|
|
|
|
|
|
Btn_Item.OnAddClickListener += OnClick;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void SetData(ItemInfo item, ItemInfo nowSelect, int index, Action<ItemInfo, int, Vector3> onSelect)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.item = item;
|
|
|
|
|
|
this.m_index = index;
|
|
|
|
|
|
this.selectCallback = onSelect;
|
|
|
|
|
|
|
|
|
|
|
|
Img_Icon.HFSetItemIcon(item.ItemConfig.Resource);
|
|
|
|
|
|
Txt_Num.text = item.Info.count.ToString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnClick(GameObject go)
|
|
|
|
|
|
{
|
|
|
|
|
|
selectCallback?.Invoke(item, m_index, go.transform.position);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4.2 提示框组件示例
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
public class BagTips : AbsHFUIWindow
|
|
|
|
|
|
{
|
|
|
|
|
|
private SFUI_Image Img_ItemIcon;
|
|
|
|
|
|
private SFUI_TextMeshProUGUI Txt_ItemName;
|
|
|
|
|
|
private SFUI_TextMeshProUGUI Txt_ItemDesc;
|
|
|
|
|
|
|
|
|
|
|
|
public ItemInfo Info { get; private set; }
|
|
|
|
|
|
|
|
|
|
|
|
protected override void OnRunAwake()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.OnRunAwake();
|
|
|
|
|
|
Img_ItemIcon = FindUICtrlByName<SFUI_Image>("Img_ItemIcon");
|
|
|
|
|
|
Txt_ItemName = FindUICtrlByName<SFUI_TextMeshProUGUI>("Txt_ItemName");
|
|
|
|
|
|
Txt_ItemDesc = FindUICtrlByName<SFUI_TextMeshProUGUI>("Txt_ItemDesc");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void SetData(ItemInfo item)
|
|
|
|
|
|
{
|
|
|
|
|
|
Info = item;
|
|
|
|
|
|
Img_ItemIcon.HFSetItemIcon(item.ItemConfig.Resource);
|
|
|
|
|
|
Txt_ItemName.text = item.ItemConfig.NameCN;
|
|
|
|
|
|
Txt_ItemDesc.text = item.ItemConfig.DesLanguageCN;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Clear()
|
|
|
|
|
|
{
|
|
|
|
|
|
Info = null;
|
|
|
|
|
|
Img_ItemIcon.HFClearSprite();
|
|
|
|
|
|
Txt_ItemName.text = string.Empty;
|
|
|
|
|
|
Txt_ItemDesc.text = string.Empty;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
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项目业务开发人员
|