当前位置: 首页 > news >正文

程序框架——UI管理模块

UI基类BasePanel

负责帮助我们通过代码快速的找到所有的子控件,方便我们在子类中处理逻辑,节约找控件的工作量。

public class BasePanel : MonoBehaviour
{//通过里式转换原则 来存储所有的控件private Dictionary<string, List<UIBehaviour>> controlDic = new Dictionary<string, List<UIBehaviour>>();// Use this for initializationprotected virtual void Awake () {FindChildrenControl<Button>();FindChildrenControl<Image>();FindChildrenControl<Text>();FindChildrenControl<Toggle>();FindChildrenControl<Slider>();FindChildrenControl<ScrollRect>();FindChildrenControl<InputField>();}/// <summary>/// 显示自己/// </summary>public virtual void ShowMe(){}/// <summary>/// 隐藏自己/// </summary>public virtual void HideMe(){}protected virtual void OnClick(string btnName){}protected virtual void OnValueChanged(string toggleName, bool value){}/// <summary>/// 得到对应名字的对应控件脚本/// </summary>/// <typeparam name="T"></typeparam>/// <param name="controlName"></param>/// <returns></returns>protected T GetControl<T>(string controlName) where T : UIBehaviour{if(controlDic.ContainsKey(controlName)){for( int i = 0; i <controlDic[controlName].Count; ++i ){if (controlDic[controlName][i] is T)return controlDic[controlName][i] as T;}}return null;}/// <summary>/// 找到子对象的对应控件/// </summary>/// <typeparam name="T"></typeparam>private void FindChildrenControl<T>() where T:UIBehaviour{T[] controls = this.GetComponentsInChildren<T>();for (int i = 0; i < controls.Length; ++i){string objName = controls[i].gameObject.name;if (controlDic.ContainsKey(objName))controlDic[objName].Add(controls[i]);elsecontrolDic.Add(objName, new List<UIBehaviour>() { controls[i] });//如果是按钮控件if(controls[i] is Button){(controls[i] as Button).onClick.AddListener(()=>{OnClick(objName);});}//如果是单选框或者多选框else if(controls[i] is Toggle){(controls[i] as Toggle).onValueChanged.AddListener((value) =>{OnValueChanged(objName, value);});}}}
}

UI管理模块UIManager

管理所有显示的面板,提供给外部 显示和隐藏等等方法。

/// <summary>
/// UI层级
/// </summary>
public enum E_UI_Layer
{Bot,Mid,Top,System,
}/// <summary>
/// UI管理器
/// 1.管理所有显示的面板
/// 2.提供给外部 显示和隐藏等等接口
/// </summary>
public class UIManager : BaseManager<UIManager>
{public Dictionary<string, BasePanel> panelDic = new Dictionary<string, BasePanel>();private Transform bot;private Transform mid;private Transform top;private Transform system;//记录我们UI的Canvas父对象 方便以后外部可能会使用它public RectTransform canvas;public UIManager(){//创建Canvas 让其过场景的时候 不被移除GameObject obj = ResMgr.GetInstance().Load<GameObject>("UI/Canvas");canvas = obj.transform as RectTransform;GameObject.DontDestroyOnLoad(obj);//找到各层bot = canvas.Find("Bot");mid = canvas.Find("Mid");top = canvas.Find("Top");system = canvas.Find("System");//创建EventSystem 让其过场景的时候 不被移除obj = ResMgr.GetInstance().Load<GameObject>("UI/EventSystem");GameObject.DontDestroyOnLoad(obj);}/// <summary>/// 通过层级枚举 得到对应层级的父对象/// </summary>/// <param name="layer"></param>/// <returns></returns>public Transform GetLayerFather(E_UI_Layer layer){switch(layer){case E_UI_Layer.Bot:return this.bot;case E_UI_Layer.Mid:return this.mid;case E_UI_Layer.Top:return this.top;case E_UI_Layer.System:return this.system;}return null;}/// <summary>/// 显示面板/// </summary>/// <typeparam name="T">面板脚本类型</typeparam>/// <param name="panelName">面板名</param>/// <param name="layer">显示在哪一层</param>/// <param name="callBack">当面板预设体创建成功后 你想做的事</param>public void ShowPanel<T>(string panelName, E_UI_Layer layer = E_UI_Layer.Mid, UnityAction<T> callBack = null) where T:BasePanel{if (panelDic.ContainsKey(panelName)){panelDic[panelName].ShowMe();// 处理面板创建完成后的逻辑if (callBack != null)callBack(panelDic[panelName] as T);//避免面板重复加载 如果存在该面板 即直接显示 调用回调函数后  直接return 不再处理后面的异步加载逻辑return;}ResMgr.GetInstance().LoadAsync<GameObject>("UI/" + panelName, (obj) =>{//把他作为 Canvas的子对象//并且 要设置它的相对位置//找到父对象 你到底显示在哪一层Transform father = bot;switch(layer){case E_UI_Layer.Mid:father = mid;break;case E_UI_Layer.Top:father = top;break;case E_UI_Layer.System:father = system;break;}//设置父对象  设置相对位置和大小obj.transform.SetParent(father);obj.transform.localPosition = Vector3.zero;obj.transform.localScale = Vector3.one;(obj.transform as RectTransform).offsetMax = Vector2.zero;(obj.transform as RectTransform).offsetMin = Vector2.zero;//得到预设体身上的面板脚本T panel = obj.GetComponent<T>();// 处理面板创建完成后的逻辑if (callBack != null)callBack(panel);panel.ShowMe();//把面板存起来panelDic.Add(panelName, panel);});}/// <summary>/// 隐藏面板/// </summary>/// <param name="panelName"></param>public void HidePanel(string panelName){if(panelDic.ContainsKey(panelName)){panelDic[panelName].HideMe();GameObject.Destroy(panelDic[panelName].gameObject);panelDic.Remove(panelName);}}/// <summary>/// 得到某一个已经显示的面板 方便外部使用/// </summary>public T GetPanel<T>(string name) where T:BasePanel{if (panelDic.ContainsKey(name))return panelDic[name] as T;return null;}/// <summary>/// 给控件添加自定义事件监听/// </summary>/// <param name="control">控件对象</param>/// <param name="type">事件类型</param>/// <param name="callBack">事件的响应函数</param>public static void AddCustomEventListener(UIBehaviour control, EventTriggerType type, UnityAction<BaseEventData> callBack){EventTrigger trigger = control.GetComponent<EventTrigger>();if (trigger == null)trigger = control.gameObject.AddComponent<EventTrigger>();EventTrigger.Entry entry = new EventTrigger.Entry();entry.eventID = type;entry.callback.AddListener(callBack);trigger.triggers.Add(entry);}}
  • 测试代码


public class LoginPanel : BasePanel
{public void InitData() {Debug.Log("初始化信息!");}// Start is called before the first frame updatevoid Start(){//GetControl<Button>("btnLogin").onClick.AddListener(()=> {//    Debug.Log("我被点击了");//});//  GetControl<Button>("btnExit").onClick.AddListener(()=> {//      Debug.Log("我要退出了");//      this.gameObject.SetActive(false);//  });UIManager.AddCustomEventListener(GetControl<Button>("btnExit"), EventTriggerType.PointerEnter, (data) =>{Debug.Log("我要进入了");});UIManager.AddCustomEventListener(GetControl<Button>("btnExit"), EventTriggerType.PointerExit, (data) =>{Debug.Log("我要退出了");});}protected override void OnClick(string btnName){switch (btnName){case "btnLogin":Debug.Log("我被点击了");break;case "btnExit":Debug.Log("我要退出了");break;default:break;}}public override void ShowMe(){Debug.Log("我显示出来了!");}public override void HideMe(){Debug.Log("我要隐藏了!");}// Update is called once per framevoid Update(){}
}
public class UITest : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){UIManager.GetInstance().ShowPanel<LoginPanel>("LoginPanel", E_UI_Layer.Mid, showPanel);}void showPanel(LoginPanel loginPanel){loginPanel.InitData();}// Update is called once per framevoid Update(){}
}

相关文章:

程序框架——UI管理模块

UI基类BasePanel 负责帮助我们通过代码快速的找到所有的子控件&#xff0c;方便我们在子类中处理逻辑&#xff0c;节约找控件的工作量。 public class BasePanel : MonoBehaviour {//通过里式转换原则 来存储所有的控件private Dictionary<string, List<UIBehaviour>…...

MySQL 慢查询探究分析

目录 背景&#xff1a; mysql 整体结构&#xff1a; SQL查询语句执行过程是怎样的&#xff1a; 知道了mysql的整体架构&#xff0c;那么一条查询语句是怎么被执行的呢&#xff1a; 什么是索引&#xff1a; 建立索引越多越好吗&#xff1a;   如何发现慢查询&#xff1…...

wpf 项目中使用 Prism + MaterialDesign

1.通过nuget安装MaterialDesign 2.通过nuget安装Prism 3.修改App.xmal <prism:PrismApplication x:Class"VisionMeasureGlue.App"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/…...

【Spring Boot】Thymeleaf模板引擎 — Thymeleaf页面布局

Thymeleaf页面布局 熟悉Thymeleaf的语法和表达式后&#xff0c;后面开发起来会更加得心应手。接下来好好研究一下Thymeleaf如何实现完整的Web系统页面布局。 1.引入代码片段 在模板中经常希望包含来自其他模板页面的内容&#xff0c;如页脚、页眉、菜单等。为了做到这一点&a…...

整理mongodb文档:删

个人博客 整理mongodb文档:删 求关注&#xff0c;哪儿不足&#xff0c;求大佬们指出&#xff0c;哪儿写的不够通俗易懂跟清晰&#xff0c;也求指出 文章概叙 本文主要是介绍了删除数据的几个方法&#xff0c;主要还是在介绍deleteMany、deleteOne以及remove&#xff0c;对于…...

篇二十三:设计模式的综合实例:构建完整项目

篇二十三&#xff1a;"设计模式的综合实例&#xff1a;构建完整项目" 开始本篇文章之前先推荐一个好用的学习工具&#xff0c;AIRIght&#xff0c;借助于AI助手工具&#xff0c;学习事半功倍。欢迎访问&#xff1a;http://airight.fun/。 另外有2本不错的关于设计模…...

FFmpeg常见命令行(三):FFmpeg转码

前言 在Android音视频开发中&#xff0c;网上知识点过于零碎&#xff0c;自学起来难度非常大&#xff0c;不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》。本文是Android音视频任务列表的其中一个&#xff0c; 对应的要学习的内容是&#xff1a;如何使…...

合宙Air724UG LuatOS-Air script lib API--scanCode

Table of Contents scanCode scanCode.request(cbFnc, timeout) scanCode 模块功能&#xff1a;扫码. 支持二维码、条形码扫描 scanCode.request(cbFnc, timeout) 设置扫码请求 参数 名称 传入值类型 释义 cbFnc function 扫码返回或者超时未返回的回调函数&#xff0c;回调…...

2023年新手如何学剪辑视频 想学视频剪辑如何入门

随着短视频、vlog等媒体形式的兴起&#xff0c;视频剪辑已经成为了热门技能。甚至有人说&#xff0c;不会修图可以&#xff0c;但不能不会剪视频。实际上&#xff0c;随着各种智能软件的发展&#xff0c;视频剪辑已经变得越来越简单。接下来&#xff0c;一起来看看新手如何学剪…...

C++的auto究竟是何方神圣

C的auto究竟是何方神圣 前言&#x1f64c;auto&#xff08;C 11&#xff09; 的使用细则auto是什么&#xff1f; auto声明的变量是在什么时期被编译器推导出来呢&#xff1f;为什么使用auto进行定义变量时&#xff0c;必须进行初始化&#xff1f; auto 的使用场景auto与指针和引…...

网络安全【黑客】面试题汇总

前言 一眨眼2023年已经过去一大半&#xff0c;不知道大家有没有找到心仪的工作。作为一个安全老鸟&#xff0c;工作这么多年&#xff0c;面试过很多人也出过很多面试题目&#xff0c;也在网上收集了各类关于渗透面试题目&#xff0c;里面有我对一些问题的见解&#xff0c;希望…...

docker菜谱大全

记录docker常用软件安装&#xff0c;感谢小马哥和杨师傅的投稿。&#x1f60e;&#x1f60e;&#x1f60e; 相关文档&#xff1a; DockerHub&#xff1a;https://hub.docker.com/Linux手册&#xff1a;https://linuxcool.com/Docker文档&#xff1a;https://docs.docker.com/Do…...

git: git checkout命令

git checkout 命令在Git中有不同的用法和功能&#xff0c;具体取决于您在命令后面提供的参数。以下是一些常见的用法&#xff1a; 1. 切换分支&#xff1a;您可以使用 git checkout <branch> 切换到指定的分支。例如&#xff0c;要切换到名为 "feature-branch"…...

以游戏编程的角度看待模拟时间的算法题——以PAT甲级1026 Table Tennis为例

对于需要模拟时间的算法题&#xff0c;可以将开始时间作为游戏的开始&#xff08;如Unity的Start或UE的BeginPlay&#xff09;&#xff0c;每一秒的模拟作为游戏的画面更新&#xff08;如Unity的Update或UE的Tick&#xff09;&#xff0c;结束时间可作为游戏的结束&#xff08;…...

SNAT与DNAT原理

SNAT和DNAT &#xff08;源地址转换和目标地址转换&#xff09; SNAT&#xff1a;源地址转换。内网到外网转换的是源地址。 DNAT&#xff1a;目标地址转换&#xff1a;外网到内网转换的是目的地址 &#xff08;把内部服务器的ip地址转换成一个所有人都可以访问的地址&#xff0…...

04-2_Qt 5.9 C++开发指南_SpinBox使用

文章目录 1. SpinBox简介2. SpinBox使用2.1 可视化UI设计2.2 widget.h2.3 widget.cpp 1. SpinBox简介 QSpinBox 用于整数的显示和输入&#xff0c;一般显示十进制数&#xff0c;也可以显示二进制、十六进制的数&#xff0c;而且可以在显示框中增加前缀或后缀。 QDoubleSpinBox…...

接口安全防护方案

文章目录 1.认证与授权机制2.参数校验3.接口加密4.防止暴力破解5.安全头设置6.日志监控 1.认证与授权机制 使用令牌&#xff08;Token&#xff09;、OAuth等认证方式&#xff0c;确保只有合法用户可以访问接口。授权机制可以防止未经授权的用户访问敏感接口。 示例&#xff1a;…...

机器学习复习题

1 单选题 ID3算法、C4.5算法、CART算法都是&#xff08; &#xff09;研究方向的算法。 A . 决策树 B. 随机森林 C. 人工神经网络 D. 贝叶斯学习 参考答案&#xff1a;A &#xff08; &#xff09;作为机器学习重要算法之一&#xff0c;是一种利用多个树分类器进行分类和预测…...

无线液位传感器—简介

近年来&#xff0c;随着无线传感网络技术的愈发成熟和稳定&#xff0c;无线传感器因其安装、维护方便&#xff0c;不用布线、节约成本&#xff0c;监测方便&#xff0c;使用灵活&#xff0c;可适用于多种工业领域等优点&#xff0c;正在逐步替代部分传统有线传感器&#xff0c;…...

通讯协议034——全网独有的OPC HDA知识一之聚合(三)时间加权平均

本文简单介绍OPC HDA规范的基本概念&#xff0c;更多通信资源请登录网信智汇(wangxinzhihui.com)。 本节旨在详细说明HDA聚合的要求和性能。其目的是使HDA聚合标准化&#xff0c;以便HDA客户端能够可靠地预测聚合计算的结果并理解其含义。如果用户需要聚合中的自定义功能&…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态

前言 在人工智能技术飞速发展的今天&#xff0c;深度学习与大模型技术已成为推动行业变革的核心驱动力&#xff0c;而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心&#xff0c;系统性地呈现了两部深度技术著作的精华&#xff1a;…...