48.Window窗口高级使用

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

×

喜欢就点赞,疼爱就打赏