48.FGUI进阶-窗口-窗口高级使用
48.1 知识点
继承窗口类
回顾窗口基础使用
Window win = new Window();
win.contentPane = UIPackage.CreateObject("Teach", "TeachPanel").asCom;
win.Show();
设置UI模式
GRoot.inst.SetContentScaleFactor(1365, 768, UIContentScaler.ScreenMatchMode.MatchHeight);
重写关键函数
初始化窗口
创建自定义 Window 类继承 Window,重写 OnInit 函数。函数中添加包,设置窗口内容,分辨率等一些初始化的操作
//初始化窗口
protected override void OnInit()
{
base.OnInit();
//需要在初始化函数中 对我们的面板进行关联
//当前包和依赖包的加载
UIPackage package = UIPackage.AddPackage("UI/FGUI教程");
foreach (var item in package.dependencies)
{
UIPackage.AddPackage("UI/" + item["name"]);
}
//即使没有再窗口中使用 frame 以及 对应的窗口内容命名规则 也可以正常使用窗口功能 只是额外的自带功能无法使用(自动关闭按钮,拖拽,锁定内容的区域)
//创建组件设置为窗口 这个组件最好包含frame及其相关
this.contentPane = UIPackage.CreateObject("FGUI教程", "Lesson48_FGUI进阶_窗口_窗口高级使用").asCom;
//设置分辨率
this.contentPane.MakeFullScreen();
//得到组件中其他控件并添加监听 注意btnTest是和frame同级
this.contentPane.GetChild("btnTest").asButton.onClick.Add(()=> {
Debug.Log("点击按钮");
});
}
客户端实例化出自定义窗口进行显示
Lesson48_FGUI进阶_窗口_窗口高级使用Window window = new Lesson48_FGUI进阶_窗口_窗口高级使用Window();
window.Show();
显示窗口时
显示窗口时的回调函数
protected override void OnShown()
{
base.OnShown();
//就是当窗口显示时 会自动调用的函数
//我们可以在这里面处理一些 窗口显示时 想要处理的逻辑
//比如显示面板时获取服务器数据
Debug.Log("显示自己时 调用");
}
隐藏窗口时
隐藏窗口时的回调函数
protected override void OnHide()
{
base.OnHide();
//就是当窗口隐藏时 会自动调用的函数
//我们可以在这里面处理一些 窗口隐藏时 想要处理的逻辑
}
播放动画
显示时 播放动画重写 可以在这里面自己处理一些动效内容
protected override void DoShowAnimation()
{
base.DoShowAnimation();
OnShown();
}
隐藏时 播放动画重写 可以在这里面自己处理一些动效内容
protected override void DoHideAnimation()
{
base.DoHideAnimation();
OnHide();
}
窗口管理
把窗口提到所有窗口最前面
GRoot.inst.BringToFront(window);
隐藏所有窗口
GRoot.inst.CloseAllWindows();
隐藏所有非模态窗口
GRoot.inst.CloseAllExceptModals();
返回当前显示在最上面的窗口
GRoot.inst.GetTopWindow();
当前是否有模态窗口在显示
if (GRoot.inst.hasModalWindow)
{
Debug.Log("有模态窗口显示");
}
窗口自动排序功能
自动排序功能就是点谁 谁显示在最前
取消窗口自动排序功能
UIConfig.bringWindowToFrontOnClick = false;
使用GRoot显示还是使用Window显示
在 GRoot 中,子对象层级需要我们自己去管理控制
在 Window 中,它帮助我们实现了很多排序相关的功能
一般采用混用的方式
- 主界面、战斗界面等全屏面板使用 GRoot 添加
- 背包、人物、商城等弹出面板用 Window 添加
48.2 知识点代码
Lesson48_FGUI进阶_窗口_窗口高级使用
using FairyGUI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson48_FGUI进阶_窗口_窗口高级使用 : MonoBehaviour
{
void Start()
{
#region 知识点一 继承窗口类
//回顾窗口基础使用
//Window win = new Window();
//win.contentPane = UIPackage.CreateObject("Teach", "TeachPanel").asCom;
//win.Show();
//设置UI模式
GRoot.inst.SetContentScaleFactor(1365, 768, UIContentScaler.ScreenMatchMode.MatchHeight);
//重写关键函数
//1.初始化窗口
Lesson48_FGUI进阶_窗口_窗口高级使用Window window = new Lesson48_FGUI进阶_窗口_窗口高级使用Window();
window.Show();
//2.显示窗口时
//3.隐藏窗口时
//3.播放动画
#endregion
#region 知识点二 窗口管理
//1:把窗口提到所有窗口最前面
GRoot.inst.BringToFront(window);
//2:隐藏所有窗口
GRoot.inst.CloseAllWindows();
//3:隐藏所有非模态窗口
GRoot.inst.CloseAllExceptModals();
//4:返回当前显示在最上面的窗口
GRoot.inst.GetTopWindow();
//5:当前是否有模态窗口在显示
if (GRoot.inst.hasModalWindow)
{
Debug.Log("有模态窗口显示");
}
//6:窗口自动排序功能
//自动排序功能就是点谁 谁显示在最前
//取消窗口自动排序功能
UIConfig.bringWindowToFrontOnClick = false;
#endregion
#region 知识点三 使用GRoot显示还是使用Window显示
//GRoot中,子对象层级需要我们自己去管理控制
//Window中,它帮助我们实现了很多排序相关的功能
//一般采用混用的方式
//主界面、战斗界面等全屏面板使用GRoot添加
//背包、人物、商城等弹出面板用Window添加
#endregion
}
}
Lesson48_FGUI进阶_窗口_窗口高级使用Window
using FairyGUI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//继承Window
public class Lesson48_FGUI进阶_窗口_窗口高级使用Window : Window
{
//初始化窗口
protected override void OnInit()
{
base.OnInit();
//需要在初始化函数中 对我们的面板进行关联
//当前包和依赖包的加载
UIPackage package = UIPackage.AddPackage("UI/FGUI教程");
foreach (var item in package.dependencies)
{
UIPackage.AddPackage("UI/" + item["name"]);
}
//即使没有再窗口中使用 frame 以及 对应的窗口内容命名规则 也可以正常使用窗口功能 只是额外的自带功能无法使用(自动关闭按钮,拖拽,锁定内容的区域)
//创建组件设置为窗口 这个组件最好包含frame及其相关
this.contentPane = UIPackage.CreateObject("FGUI教程", "Lesson48_FGUI进阶_窗口_窗口高级使用").asCom;
//设置分辨率
this.contentPane.MakeFullScreen();
//得到组件中其他空间并添加监听 注意btnTest是和frame同级
this.contentPane.GetChild("btnTest").asButton.onClick.Add(()=> {
Debug.Log("点击按钮");
});
}
//显示窗口时的回调函数
protected override void OnShown()
{
base.OnShown();
//就是当窗口显示时 会自动调用的函数
//我们可以在这里面处理一些 窗口显示时 想要处理的逻辑
//比如显示面板时获取服务器数据
Debug.Log("显示自己时 调用");
}
//隐藏窗口时的回调函数
protected override void OnHide()
{
base.OnHide();
//就是当窗口隐藏时 会自动调用的函数
//我们可以在这里面处理一些 窗口隐藏时 想要处理的逻辑
}
//显示时 播放动画重写 可以在这里面自己处理一些动效内容
protected override void DoShowAnimation()
{
base.DoShowAnimation();
OnShown();
}
//隐藏时 播放动画重写 可以在这里面自己处理一些动效内容
protected override void DoHideAnimation()
{
base.DoHideAnimation();
OnHide();
}
}
48.3 练习题
在上节课的练习题基础上,在UIManager中加入窗口显示、隐藏相关的逻辑
UIManager中声明窗口字典
//用于存储已经显示的 窗口
private Dictionary<string, Window> windowDic = new Dictionary<string, Window>();
UIManager创建显示窗口函数
//显示窗口方法 T一定要继承Window 且有一个无参构造函数
public T ShowWindow<T>() where T : Window, new()
{
//用面向对象来看 面板自己初始化逻辑和展示的逻辑 写在自己的类里
Type type = typeof(T); // 获取泛型类型
string windowName = type.Name; // 获取类型名
// 判断有没有面板
if (windowDic.ContainsKey(windowName))
{
windowDic[windowName].Show(); // 显示已存在的窗口
return windowDic[windowName] as T; // 返回已存在的窗口
}
// 创建并显示面板
T win = new T(); // 创建类型为T的对象
win.Show(); // 显示新创建的窗口
// 记录字典中
windowDic.Add(windowName, win); // 将新创建的窗口添加到字典中
return win; // 返回新创建的窗口
}
创建ExercisesWindow,ExercisesWindow脚本继承Window,OnInit中初始化窗口显示的组件和一些基础逻辑。
public class ExercisesWindow : Window
{
protected override void OnInit()
{
base.OnInit();
//关联对应的 组件
UIPackage.AddPackage("UI/Teach");
this.contentPane = UIPackage.CreateObject("Teach", "ExercisesPanel").asCom;
this.contentPane.MakeFullScreen();
}
}
Exercises脚本中
//通过窗口的形式去显示
ExercisesWindow window = UIManager.Instance.ShowWindow<ExercisesWindow>();
UIManager创建隐藏窗口函数
//隐藏窗口方法 传入窗口类型 并传入是否销毁 默认不删除的话只是隐藏而已
public void HideWindow<T>(bool isDispose = false)
{
Type type = typeof(T); // 获取泛型类型
string windowName = type.Name; // 获取类型名
if (windowDic.ContainsKey(windowName)) // 检查字典中是否存在该窗口名的记录
{
if (isDispose) // 如果指定需要释放资源
{
windowDic[windowName].Dispose(); // 释放窗口资源
windowDic.Remove(windowName); // 从字典中移除窗口记录
}
else // 如果不需要释放资源
{
windowDic[windowName].Hide(); // 隐藏窗口
}
}
}
UIManager创建得到窗口函数
// 通过泛型方法获取指定类型的窗口
public T GetWindow<T>() where T : Window
{
// 获取传入类型的实例
Type type = typeof(T);
// 获取窗口名称
string windowName = type.Name;
// 检查窗口字典中是否包含该窗口名称的键值对
if (windowDic.ContainsKey(windowName))
{
// 如果包含,则将对应的窗口实例强制转换为指定类型,并返回
return windowDic[windowName] as T;
}
// 如果不包含,则返回空值
return null;
}
UIManager创建清除所有窗口函数
// 清除所有窗口的方法
public void ClearWindow(bool isGC = false)
{
// 遍历窗口字典中的每个窗口实例
foreach (var item in windowDic.Values)
{
// 销毁当前窗口的资源
item.Dispose();
}
// 清空窗口字典
windowDic.Clear();
// 如果传入的参数 isGC 为 true,则执行以下操作
if (isGC)
{
// 移除所有包资源
UIPackage.RemoveAllPackages();
// 执行垃圾回收
GC.Collect();
}
}
48.4 练习题代码
UIManager
using FairyGUI;
using System;
using System.Collections;
using System.Collections.Generic;
using Teach;
using UnityEngine;
public class UIManager
{
private static UIManager instance = new UIManager();
public static UIManager Instance => instance;
//用于存储已经显示的 UI面板
private Dictionary<string, GComponent> panelDic = new Dictionary<string, GComponent>();
//用于存储已经显示的 窗口
private Dictionary<string, Window> windowDic = new Dictionary<string, Window>();
private UIManager()
{
//默认字体
UIConfig.defaultFont = "Other/STHUPO";
//默认音效
UIPackage.AddPackage("UI/Public");
UIConfig.buttonSound = (NAudioClip)UIPackage.GetItemAssetByURL("ui://Public/btnMusic");
//适配相关的设置
GRoot.inst.SetContentScaleFactor(1365, 768, UIContentScaler.ScreenMatchMode.MatchHeight);
//注册相关的代码
UIObjectFactory.SetPackageItemExtension("ui://Teach/ExercisesPanel", typeof(ExercisesPanel));
UIObjectFactory.SetPackageItemExtension("ui://Teach/ExercisesBagPanel", typeof(ExercisesBagPanel));
UIObjectFactory.SetPackageItemExtension("ui://Teach/TeachPanel", typeof(TeachPanel));
UIObjectFactory.SetPackageItemExtension("ui://Teach/ControllerTest", typeof(ControllerTest));
}
//组件名和面板类名 是一致的
public T ShowPanel<T>(string packageName) where T : GComponent
{
Type panelType = typeof(T);
string panelName = panelType.Name;
//如果字典中有该面板的名字 证明已经创建过了 直接返回即可
if (panelDic.ContainsKey(panelName))
{
panelDic[panelName].visible = true;
return panelDic[panelName] as T;
}
//加载包和依赖包
//由于从Resources文件夹中加载包 会帮助我们判断重复没有 所以 这里既是重复执行也没什么问题
UIPackage package = UIPackage.AddPackage("UI/" + packageName);
foreach (var item in package.dependencies)
{
UIPackage.AddPackage("UI/" + item["name"]);
}
//创建组件面板
GComponent panel = UIPackage.CreateObject(packageName, panelName).asCom;
//把组件的尺寸设置的和逻辑分辨率一致
panel.MakeFullScreen();
GRoot.inst.AddChild(panel);
//和父对象建立 宽高关联 这样 分辨率变化时 面板也不会出问题
panel.AddRelation(GRoot.inst, RelationType.Size);
//进行批处理 DC优化 开关开启
panel.fairyBatching = true;
//把当前显示的面板存起来 用于之后的隐藏
panelDic.Add(panelName, panel);
//把父类转换成对应的 子类
return panel as T;
}
//显示窗口方法 T一定要继承Window 且有一个无参构造函数
public T ShowWindow<T>() where T : Window, new()
{
//用面向对象来看 面板自己初始化逻辑和展示的逻辑 写在自己的类里
Type type = typeof(T); // 获取泛型类型
string windowName = type.Name; // 获取类型名
// 判断有没有面板
if (windowDic.ContainsKey(windowName))
{
windowDic[windowName].Show(); // 显示已存在的窗口
return windowDic[windowName] as T; // 返回已存在的窗口
}
// 创建并显示面板
T win = new T(); // 创建类型为T的对象
win.Show(); // 显示新创建的窗口
// 记录字典中
windowDic.Add(windowName, win); // 将新创建的窗口添加到字典中
return win; // 返回新创建的窗口
}
public void HidePanel<T>(bool isDispose = false) where T : GComponent
{
Type panelType = typeof(T);
string panelName = panelType.Name;
//如果没有面板显示着 就直接返回
if (!panelDic.ContainsKey(panelName))
return;
//希望移除面板
if (isDispose)
{
//移除面板 并且从字典中移除
panelDic[panelName].Dispose();
panelDic.Remove(panelName);
}
//希望只是失活
else
{
panelDic[panelName].visible = false;
}
}
//隐藏窗口方法 传入窗口类型 并传入是否销毁 默认不删除的话只是隐藏而已
public void HideWindow<T>(bool isDispose = false) where T : Window
{
Type type = typeof(T); // 获取泛型类型
string windowName = type.Name; // 获取类型名
if (windowDic.ContainsKey(windowName)) // 检查字典中是否存在该窗口名的记录
{
if (isDispose) // 如果指定需要释放资源
{
windowDic[windowName].Dispose(); // 释放窗口资源
windowDic.Remove(windowName); // 从字典中移除窗口记录
}
else // 如果不需要释放资源
{
windowDic[windowName].Hide(); // 隐藏窗口
}
}
}
public T GetPanel<T>() where T : GComponent
{
Type panelType = typeof(T);
string panelName = panelType.Name;
//如果有这个面板 直接返回
if (panelDic.ContainsKey(panelName))
return panelDic[panelName] as T;
return null;
}
// 通过泛型方法获取指定类型的窗口
public T GetWindow<T>() where T : Window
{
// 获取传入类型的实例
Type type = typeof(T);
// 获取窗口名称
string windowName = type.Name;
// 检查窗口字典中是否包含该窗口名称的键值对
if (windowDic.ContainsKey(windowName))
{
// 如果包含,则将对应的窗口实例强制转换为指定类型,并返回
return windowDic[windowName] as T;
}
// 如果不包含,则返回空值
return null;
}
//主要用于销毁所有面板 和 资源垃圾回收的方法
public void ClearPanel(bool isGC = false)
{
//销毁所有面板 并且清空字典
foreach (var item in panelDic.Values)
{
item.Dispose();
}
panelDic.Clear();
if (isGC)
{
//释放所有包资源
UIPackage.RemoveAllPackages();
//垃圾回收
GC.Collect();
}
}
// 清除所有窗口的方法
public void ClearWindow(bool isGC = false)
{
// 遍历窗口字典中的每个窗口实例
foreach (var item in windowDic.Values)
{
// 销毁当前窗口的资源
item.Dispose();
}
// 清空窗口字典
windowDic.Clear();
// 如果传入的参数 isGC 为 true,则执行以下操作
if (isGC)
{
// 移除所有包资源
UIPackage.RemoveAllPackages();
// 执行垃圾回收
GC.Collect();
}
}
}
ExercisesWindow
using FairyGUI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ExercisesWindow : Window
{
protected override void OnInit()
{
base.OnInit();
//关联对应的 组件
UIPackage.AddPackage("UI/Teach");
this.contentPane = UIPackage.CreateObject("Teach", "ExercisesPanel").asCom;
this.contentPane.MakeFullScreen();
}
}
Exercises
using FairyGUI;
using FairyGUI.Utils;
using System.Collections;
using System.Collections.Generic;
using Teach;
using UnityEngine;
public class Exercises : MonoBehaviour
{
public Player player;
ExercisesPanel panel;
void Start()
{
//设置分支
UIPackage.branch = "Exercises";
//设置多国语言
//加载英文翻译xml文件
string fileContent = Resources.Load<TextAsset>("English").text;
//构造一个xml数据对象
XML xml = new XML(fileContent);
//进行多国语言设置
UIPackage.SetStringsSource(xml);
//通过窗口的形式去显示
ExercisesWindow window = UIManager.Instance.ShowWindow<ExercisesWindow>();
}
public static void ClickLinkOpenPanel(EventContext eventData)
{
string info = eventData.data.ToString();
switch (info)
{
case "1":
print("打开任务面板");
break;
case "2":
print("打开装备面板");
break;
case "3":
print("打开PVP面板");
break;
case "4":
print("打开商店面板");
break;
default:
print("数据未知");
break;
}
}
void Update()
{
if (Input.GetKeyDown(KeyCode.H))
UIManager.Instance.HideWindow<ExercisesWindow>(true);
if (Input.GetKeyDown(KeyCode.S))
UIManager.Instance.ShowWindow<ExercisesWindow>();
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com