更新UI相关指南文档 v1.1

修改内容:
1. UI事件绑定指南:新增事件绑定位置规范,强调防重复注册保护,新增SFUI_ScrollRect绑定模式
2. UI窗口开发指南:更新窗口创建流程示例,添加子组件开发示例
3. UI组件使用指南:添加防重复注册保护,新增列表绑定模式和子组件开发规范
This commit is contained in:
Shiliang
2026-05-22 14:40:44 +08:00
parent 75687450ad
commit 094ae2eedb
3 changed files with 416 additions and 197 deletions

View File

@@ -5,52 +5,67 @@
### 1.1 窗口创建流程
```csharp
[HFAssetBundlePath(enHFLanguageRootFolder.ASSETS_GAME_GAMEHFRESOURCE, "UIWindows/Login/LoginWindow.prefab")]
[HFUIWindowLayer(enHFUICanvasLayer.UIWindow, enHFUIWindowLayer.Dynamic, isIgnoreCloseByESC = false)]
public class LoginWindow : AbsHFUIWindow
[HFAssetBundlePath(enHFLanguageRootFolder.ASSETS_GAME_GAMEHFRESOURCE, "UIWindows/Bag/BagWindow.prefab")]
[HFUIWindowLayer(enHFUICanvasLayer.UIWindow, enHFUIWindowLayer.Fixed, isIgnoreCloseByESC = false)]
public class BagWindow : AbsHFUIWindow
{
// ========== UI组件 ==========
private SFUI_Button BtnLogin;
private SFUI_InputField InputName;
private SFUI_InputField InputPassword;
private SFUI_TextMeshProUGUI TxtTitle;
private SFUI_Button BtnClose;
private SFUI_ScrollRect BagListView;
private BagTips tips;
// ========== 数据 ==========
private List<ItemInfo> m_items = new List<ItemInfo>();
private ItemInfo m_select;
protected override void OnRunAwake()
{
base.OnRunAwake();
// 初始化UI组件引用(变量名与组件名保持一致)
BtnLogin = FindUICtrlByName<SFUI_Button>("BtnLogin");
InputName = FindUICtrlByName<SFUI_InputField>("InputName");
InputPassword = FindUICtrlByName<SFUI_InputField>("InputPassword");
TxtTitle = FindUICtrlByName<SFUI_TextMeshProUGUI>("TxtTitle");
// 初始化UI组件引用
BtnClose = FindUICtrlByName<SFUI_Button>("BtnClose");
BagListView = FindUICtrlByName<SFUI_ScrollRect>("BagListView");
tips = BindUI<BagTips, SFUI_Image>("BagTips");
// 绑定按钮事件
if (BtnLogin != null)
{
BtnLogin.OnAddClickListener += OnBtnLoginClick;
}
// 按钮事件绑定(带防重复注册保护)
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>(); }
);
}
protected override void OnOpen(Action _onOpenComplete)
{
base.OnOpen(_onOpenComplete);
// 注册事件监听
// ✅ 注册全局事件监听
HFFunCatalogue.Event.TCEvent.AddListener<HFEvent_BagItemUpdate>(
enHFCTCEvent.BagItemUpdate, OnBagItemUpdate);
// ✅ 初始化数据
RefreshBagItems();
}
protected override void OnClose(Action _onCloseComplete)
{
// 取消事件监听
if (BtnLogin != null)
{
BtnLogin.OnAddClickListener -= OnBtnLoginClick;
}
// ✅ 取消全局事件监听
HFFunCatalogue.Event.TCEvent.RemoveListener<HFEvent_BagItemUpdate>(
enHFCTCEvent.BagItemUpdate, OnBagItemUpdate);
// ✅ 清理资源
tips.Clear();
base.OnClose(_onCloseComplete);
}
private void OnBtnLoginClick(GameObject go)
{
// 处理登录逻辑
}
private void OnBtnClose(GameObject go) => CloseWindow();
private void OnUpdateItem(SFUI_ScrollRectItem item) { /* 更新列表项 */ }
private void RefreshBagItems() { /* 刷新背包数据 */ }
}
```
@@ -58,18 +73,16 @@ public class LoginWindow : AbsHFUIWindow
```csharp
// 方式1直接打开无回调
HFFunCatalogue.UIManager.OpenWindow<LoginWindow>();
HFFunCatalogue.UIManager.OpenWindow<BagWindow>();
// 方式2打开并获取窗口实例推荐
HFFunCatalogue.UIManager.OpenWindow<LoginWindow>((win, args) => {
// win: 打开的窗口实例
// args: 传入的额外参数
HFFunCatalogue.UIManager.OpenWindow<BagWindow>((win, args) => {
Debug.Log("窗口打开完成");
});
// 方式3带额外参数打开
object[] extraArgs = new object[] { "param1", 123 };
HFFunCatalogue.UIManager.OpenWindow<LoginWindow>((win, args) => {
HFFunCatalogue.UIManager.OpenWindow<BagWindow>((win, args) => {
// 使用窗口实例
}, extraArgs);
```
@@ -80,12 +93,32 @@ HFFunCatalogue.UIManager.OpenWindow<LoginWindow>((win, args) => {
### 2.1 生命周期方法
| 方法 | 调用时机 | 说明 |
|-----|---------|------|
| `OnRunAwake` | 窗口创建时调用一次 | 初始化组件引用 |
| `OnOpen` | 每次打开窗口时调用 | 注册事件、刷新数据 |
| `OnClose` | 每次关闭窗口时调用 | 取消事件、清理资源 |
| `OnDestroy` | 窗口销毁时调用 | 释放资源 |
| 方法 | 调用时机 | 说明 | 推荐操作 |
|-----|---------|------|---------|
| `OnRunAwake` | 窗口创建时调用一次 | 初始化组件引用 | **绑定按钮事件、列表初始化** |
| `OnOpen` | 每次打开窗口时调用 | 注册事件、刷新数据 | **注册全局TC事件、初始化数据** |
| `OnClose` | 每次关闭窗口时调用 | 取消事件、清理资源 | **取消全局TC事件、清理UI状态** |
| `OnDestroy` | 窗口销毁时调用 | 释放资源 | **释放非托管资源** |
### 2.2 生命周期流程图
```
窗口创建
OnRunAwake() ──→ 初始化组件、绑定按钮事件
窗口打开(可多次)
OnOpen() ──→ 注册TC事件、刷新数据
窗口关闭(可多次)
OnClose() ──→ 取消TC事件、清理资源
窗口销毁
OnDestroy() ──→ 释放资源
```
---
@@ -100,7 +133,96 @@ HFFunCatalogue.UIManager.OpenWindow<LoginWindow>((win, args) => {
| `isNeedMask` | 是否需要遮罩 | true |
| `maskType` | 遮罩类型 | 半透明 |
### 3.2 层叠配置
```csharp
[HFUIWindowLayer(enHFUICanvasLayer.UIWindow, enHFUIWindowLayer.Fixed, isIgnoreCloseByESC = false)]
// ↑ Canvas层级 ↑ 窗口层级
```
---
**版本**: v1.0
## 四、子组件开发
### 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;
}
}
```
---
**版本**: v1.1
**适用范围**: GiftGameX项目业务开发人员