【GFFrameWork】UI框架

前言

曾经的老大说过,游戏开发70%跟UI打交道,貌似也是,UI是游戏开发里面的大头,这么说一个不错的UI框架就比较重要,UI界面会比较多,大项目大几十个系统界面,管理不当会造成比较大的麻烦。之前NGUI项目界面层级通过Depth管理界面的显示层级,Depth越大就显示在前面,后来UGUI通过设置SetSiblingIndex,值越大越显示在前面。有时候我们有需求某些界面固定显示在最上面,例如引导界面,有的显示在中间,有的显示在后面,GFFrameWork设置了三层显示层级,加载的界面由开发者自行执行放在哪一层上,然后每一层的界面进行设置显示前后顺序。

说明

本UI结构基于UGUI,后续也考虑对接FairyGUI,一款非常强大的UI编辑器。

UI显示结构

UI界面在Hierarchy中的显示
在这里插入图片描述

在这里插入图片描述
分成三层显示,每一层的就Order in Layer不同,数值越大的越显示在前面,动态加载的UI根据需要显示在具体的哪一层。

UIManager和窗口

窗口基类 Window_Base

在这里插入图片描述

在这里插入图片描述

主要就是窗口的管理(初始化、打开、关闭、消息管理),加载对应的界面预设,子窗口管理(添加、打开、关闭)

UIManager设计

在这里插入图片描述

在这里插入图片描述
主要是UI的加载(同步、异步)和管理(、显示、卸载、获取、关闭、获取UI状态),发送消息

UI导航

我们如何打开一个UI界面呢?这里采用类似iOS开发中界面跳转,导航跳转。
我们每创建一个需要跳转显示的界面,我们要创建两个脚本,一个UI的View界面脚本,一个导航脚本:
在这里插入图片描述

跳转界面
ScreenViewManager.Inst.MainLayer.BeginNavTo("main");

参数是导航脚本的特性的值
在这里插入图片描述

导航跳转原理

上面的截图会发现导航脚本类都继承自IScreenView接口,这个用于导航管理器搜集所有导航组件用的。
在这里插入图片描述
接口里面重要的是BeginInit和BeginExit方法,是导航跳转到这个界面和离开这个界面触发的事件方法。所有这些导航跳转脚本都归ScreenViewLayer管理,
这个其实就是导航组件Manager,既然是Manager,那肯定是有所有导航组件的管理器的,
在这里插入图片描述
当调用了跳转方法的时候会将这个界面的导航组件添加进这个navViews

/// <summary>
/// 灵魂功能,导航到一个指定名称的ScreenView,可能是向前,也可能是向后
/// </summary>
/// <param name="_name"></param>
/// <param name="onLoad"></param>
public void BeginNavTo(string name)
{
    //
    if (currentView != null && currentView.Name == name)
    {
        Debugger.LogError("别闹,当前就是" + name);
        return;
    }
    //
    IScreenView view = null;
    if (this.allViews.TryGetValue(name, out view))
    {
        view.BeginInit();
        if (currentView != null)
        {
           currentView.BeginExit();
        }
        //
        currentView = view;
        currentViewIndex = -1;
        //
        this.navViews.Add(view);
        if (navViews.Count > 10)
        {
            navViews.RemoveAt(0);
        }
    }
}

这样以便向前,向后跳转。也可以导航到具体的界面,这个也有点跟Cocos的UI管理类似。

根据导航组件加载对应的UI

在这里插入图片描述
根据特性标记搜集导航组件,当调用ScreenViewManager.Inst.MainLayer.BeginNavTo(“main”)的时候,导航器会找到对应UI的导航组件然后调用他的BeinInit()方法,在这个方法里面我们去加载想要加载的UI。
在这里插入图片描述
以上就是UI导航的原理。

UI自动获取属性

由于C#代码热更,所以不能将C#代码直接挂在Prefab上,我们加载出来的Prefab然后动态给他挂在代码组件,UI组件脚本原来的定义一个组件变量,我们就要在Start或者Awake里面取Find然后GetComponent,如果变量很多就会显得这样的代码很多,感觉很冗余,这里采用自定义特性去找对应的UI上的组件节点。
在这里插入图片描述

public class TransformPath : Attribute
{
    public string Path;

    public TransformPath(string path)
    {
        this.Path = path;
    }
}
原理

在界面加载的时候,UITools会调用AutoSetTransformPath方法找到这个界面上特性绑定的节点

static public void AutoSetTransformPath(WindowBase win)
{
    var vt = win.GetType();
    var fields = vt.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
    var vTransform = win.Transform;
    foreach (var f in fields)
    {
        if (f.FieldType.IsSubclassOf(checkType) == false)
        {
            continue;
        }

        //1.自动获取节点
        var _attrs = f.GetCustomAttributes(typeof(TransformPath), false); //as Attribute[];
        if (_attrs != null && _attrs.Length > 0)
        {
            var attr = _attrs.ToList().Find((a) => a is TransformPath) as TransformPath;
            if (attr == null) continue;
            //获取节点,并且获取组件
            var trans = vTransform.Find(attr.Path);
            if (trans == null)
            {
                Debugger.LogError(string.Format("自动设置节点失败:{0} - {1}", vt.FullName, attr.Path));
            }
            var com = trans.GetComponent(f.FieldType);
            if (com == null)
            {
                Debugger.LogError(string.Format("节点没有对应组件:type【{0}】 - {1}", f.FieldType, attr.Path));
            }

            //设置属性
            f.SetValue(win, com);
            //Debug.LogFormat("字段{0}获取到setTransform ,path:{1}" , f.Name , attr.Path);
        }
    }
    #endregion
}

UI之间消息传递

UI窗口之间交互通讯都通过发送消息来实现,这样可以减少UI模块之间的耦合,消息是这样的一个结构:

消息发送

里面主要是一个字典结构,如何发送消息如下:

var data = WindowData.Create("AddDial"); //创建一个消息结构,参数是消息名,用于监听,内部会创建一个消息字典
data.AddData("key", tempDialData); //添加消息键值对
UIManager.Inst.SendMessage((int)WinEnum.Win_Menu, data); //通过UI接口发送消息,第一个参数是接受界面ID

消息接受


在接受消息界面添加消息监听,第一个参数是监听的消息名


获取消息内容

消息发送原理

或许就有人疑惑,为啥注册这个监听,通过UImanager的发送消息就能收到消息回调呢?
每一个界面都继承自Window_Base,WindowsBase里面有一个消息回调表

protected Dictionary<string, Action<WindowData>> callbackMap;

还有消息注册监听方法,也就是我们消息接受调用的监听方法

protected void RegisterAction(string name, Action<WindowData> callback)
{
    callbackMap[name] = callback;
}

还有发送消息的方法

public void SendMessage(WindowData data)
{
    Action<WindowData> action = null;
    callbackMap.TryGetValue(data.Name, out action);
    if (action != null)
    {
        action(data);
    }
}

然后我们在看看UIManager的发送消息,Manager里面缓存了所有的界面,然后根据想要发送消息的界面ID找到对应的界面调用上面的界面的SendMessage方法,这样就明白消息发送的原理了。

public void SendMessage(int Index, WindowData data)
{
    var uiIndex = Index.GetHashCode();
    if (windowMap.ContainsKey(uiIndex))
    {
        var ui = windowMap[uiIndex];

        if (ui.IsLoad)
        {
            ui.SendMessage(data);
            return;
        }
    }
}

GFFramework地址

https://github.com/dingxiaowei/GFFrameWork

更多教程

http://dingxiaowei.cn/

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
vtiger UI框架是一种用于开发和设计用户界面的工具集。它提供了一套可重复使用的组件和模板,使开发者能够快速构建现代化和美观的用户界面。 vtiger UI框架具有以下特点: 1. 响应式设计:vtiger UI框架支持响应式设计,可以自动适应不同的屏幕尺寸和设备类型。这样,用户无论使用台式机、笔记本电脑、平板电脑还是手机浏览网页,都能获得良好的用户体验。 2. 可自定义性:vtiger UI框架提供了丰富的样式和布局选项,开发者可以根据自己的需求进行定制。无论是调整颜色、字体还是布局方式,都可以通过简单的配置来实现。 3. 组件丰富:vtiger UI框架提供了各种常用的UI组件,如按钮、表单、标签页等。这些组件具有一致的设计风格和交互方式,方便开发者在项目中进行使用。 4. 轻量级:vtiger UI框架注重性能优化,使用了轻量级的CSS和JavaScript代码,以确保快速加载和响应。 5. 跨浏览器兼容性:vtiger UI框架经过充分测试,可以在各种现代浏览器上稳定运行,如Chrome、Firefox、Safari等。 使用vtiger UI框架,开发者可以更加高效地构建用户友好的界面,提升用户体验。同时,VTiger UI框架也提供了详细的文档和示例代码,方便开发者学习和使用。无论是开发Web应用程序,还是设计企业级软件界面,vtiger UI框架都是一个强大的工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值