分析:UI框架主要是为了用户(使用框架的程序猿)更快捷、方便地开发UI,UI框架的好处还在于解耦,使得程序更具有灵活性。

UI框架的核心是窗口的管理,窗口管理的主要任务就是显示窗口和关闭窗口。

因为窗口的类型多样,比如弹出式窗口,固定位置窗口,隐藏其他窗口(打开这个窗口会覆盖整个屏幕),模态窗口等等。

这里我目前把窗口分为三大类型:普通窗口、弹出式窗口、隐藏其他窗口,而位置固定、是否模态作为窗口的属性。

1.为了更易于复用和拓展,我设计了一个基类BasePanel, NormalPanel, PopupPanel, HiderOtherPanel都由此基类派生。

BasePanel封装了3个重要方法:Open(), Close(), Freeze()。

2.巧妇难为无米之炊,要显示这些窗体首先要制作这些窗体的预制体,然后加载。为此,我又设计了一个核心类PanelManager。

PanelManager主要负责窗体的创建和销毁(隐藏),核心方法CreatePanel()。另外使用了对象池技术,缓存窗体。

3.要动态加载窗体,必须获得窗体资源的路径,为此我设计了一个SysDefine类,此文件用于定义一些预制体路径常量,节点(Inspector面板中的物体位置)常量。(后期重构时打算用Json文件配置)。加载资源的类ResourceManager。

4.此外,我还设计了一个帮助类Helper,目前实现的功能仅仅是自动化设置窗体节点的父节点。

下面,展示我今天下午的成果。

 using UnityEngine;

 public class BasePanel : MonoBehaviour
{
//窗体类型
public EPanelType panelType;
//是否是模态窗口
public bool isModal;
//是否是固定位置窗口
public bool isFixed;
//透明度
ETransparencyLevel transLevel; //初始化
private void Awake()
{
panelType = EPanelType.Normal;
isModal = true;
isFixed = false;
transLevel = ETransparencyLevel.Opaque;
} private void Start()
{
//自动设置物体的父节点
Helper.GetInstance().SetParent(gameObject); } //打开窗口
public void Open()
{
gameObject.SetActive(true);
}
//关闭窗口
public void Close()
{
gameObject.SetActive(false);
}
//冻结窗口
public void Freeze()
{
//TO DO
}
}
 using System.Collections.Generic;
using UnityEngine;
public class PanelManager
{
//本类实例
private static PanelManager _instance;
//存储面板名字和对应的路径字典
public static Dictionary<string, string> dictPanelPath;
//存储已显示的面板字典
public static Dictionary<string, BasePanel> dictCurPanel;
//存储已隐藏的面板字典
public static Dictionary<string, BasePanel> dictHidePanel;
//存储Popup类型面板的字典
public static Dictionary<string, Stack<BasePanel>> dictPopupPanel; //单例模式
private PanelManager() { }
public static PanelManager GetInstance()
{
if(_instance == null)
{
_instance = new PanelManager(); InitProperties();
}
return _instance;
}
//初始化字段
private static void InitProperties()
{
dictPanelPath = new Dictionary<string, string>();
dictCurPanel = new Dictionary<string, BasePanel>();
dictHidePanel = new Dictionary<string, BasePanel>();
dictPopupPanel = new Dictionary<string, Stack<BasePanel>>();
}
/// <summary>
/// 创建一个面板
/// 先检查dictHidePanel集合里是否存在此面板,有则取出显示并加入dictCurPanel集合
/// 没有,则创建一个,然后加如dictCurPanel集合。
/// </summary>
/// <param name="panelName">要创建的面板的名字</param>
/// <returns></returns>
public BasePanel CreatePanel(string panelName)
{
BasePanel basePanel = null;
dictHidePanel.TryGetValue(panelName, out basePanel);
if(basePanel != null)
{
return basePanel;
}
else
{
//创建面板
GameObject go = ResourceManager.GetInstance().LoadAsset<GameObject>(panelName);
if(go != null)
{
basePanel = go.GetComponent<BasePanel>();
if(basePanel != null)
{
//添加到正在显示的面板集合
dictCurPanel.Add(panelName, basePanel);
}
else
{
Debug.LogError(GetType()+"你可能忘记挂在了BasePanel类型的脚本");
}
return basePanel;
}
else
{
Debug.Log(GetType()+"panelName可能不存在"); }
}
return null;
} }
 using UnityEngine;

 public class ResourceManager
{
private static ResourceManager _instance;
public static ResourceManager GetInstance()
{
if (_instance == null)
{
_instance = new ResourceManager();
}
return _instance;
}
private ResourceManager() { } public T LoadAsset<T>(string path)where T:Object
{
Object o = Resources.Load(path);
//实例化
GameObject go = GameObject.Instantiate(o) as GameObject; return go as T;
} }
 public enum ETransparencyLevel
{
Opaque, //不透明
Translucence, //半透明的
Transparent, //透明的
}
public enum EPanelType
{
Normal,
Popup,
HideOther
}
public class PrefabPathStr
{
public const string uiRootPath = @"Prefabs/UIRoot";
public const string logOnPanelPath = @"Prefabs/LogOnPanel";
}
public class NodePathStr
{
public const string normalPath = @"UIRoot/Normal";
public const string popupPath = @"UIRoot/Popup";
public const string hiderOtherPath = @"UIRoot/HideOther";
} public class SysDefine
{
}
 using UnityEngine;

 public class Helper
{
private static Helper _instance = null; //本类实;
private static Transform normal; //normal 节点
private static Transform popup; //popup 节点
private static Transform hiderOther; //hiderOther 节点 //单利模式
public static Helper GetInstance()
{
if(_instance == null)
{ //本类实例化时,初始化节点字段
normal = GameObject.Find(NodePathStr.normalPath).transform;
popup = GameObject.Find(NodePathStr.popupPath).transform;
hiderOther = GameObject.Find(NodePathStr.hiderOtherPath).transform;
_instance = new Helper();
}
return _instance;
}
private Helper() { }
/// <summary>
/// 若用户自定义了parent则使用,若没有则根据panelType自动设定。
/// </summary>
/// <param name="child">子物体</param>
/// <param name="parent">父物体</param>
public void SetParent(GameObject child, Transform parent = null)
{
if(parent != null)
{
child.transform.SetParent(parent, true);
child.transform.localScale = new Vector3(, , );
child.transform.localPosition = Vector3.zero;
}
else
{
if(child.GetComponent<BasePanel>()!= null)
{
EPanelType panelType = child.GetComponent<BasePanel>().panelType;
switch (panelType)
{
case EPanelType.Normal:
child.transform.SetParent(normal);
break;
case EPanelType.Popup:
child.transform.SetParent(popup);
break;
case EPanelType.HideOther:
child.transform.SetParent(hiderOther);
break;
default:
Debug.LogError("错误,未知的窗体类型");
break;
}
child.transform.localScale = new Vector3(, , );
child.transform.localPosition = Vector3.zero;
}
else
{
Debug.LogError(GetType()+ "请检查此物体是否挂载了BasePanel类型脚本!");
} }
}
}

启动框架类StartGame.cs

 using UnityEngine;

 public class StartGame : MonoBehaviour
{ private GameObject uiRoot = null;
void Start()
{
uiRoot = GameObject.FindGameObjectWithTag("UIRoot");
if (uiRoot != null) //已生成UIRoot
{
Destroy(uiRoot); }
//获取UIRoot对象
uiRoot = ResourceManager.GetInstance().LoadAsset<GameObject>(PrefabPathStr.uiRootPath); //修改克隆体的名字
uiRoot.name = "UIRoot";
//加载场景时不销毁UIRoot
DontDestroyOnLoad(uiRoot); //加载登陆面板
PanelManager.GetInstance().CreatePanel(PrefabPathStr.logOnPanelPath); } }

测试代码LogOnPanel.cs

 using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class LogOnPanel : BasePanel
{
private void Awake()
{
this.panelType = EPanelType.Normal;
} }

UIRoot预制体效果图

LogOnPanel预制体效果图:

运行效果图:

UI框架搭建DAY1的更多相关文章

  1. Element UI 框架搭建

    Element UI 框架搭建 1.webpack 全局安装 npm install -g webpack 2.淘宝镜像cnpm安装 npm install -g cnpm --registry=ht ...

  2. UI框架搭建DAY2

    今天的主要任务是完善NormalPanel, 搭建PopupPanel. 在编写PanelManager的过程中,发现了一个bug.昨天把panelPath直接传给了ResourceManager.G ...

  3. ASP.NET MVC搭建项目后台UI框架—1、后台主框架

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  4. ASP.NET MVC搭建项目后台UI框架—11、自动加载下拉框查询

    ASP.NET MVC搭建项目后台UI框架—1.后台主框架 需求:在查询记录的时候,输入第一个字,就自动把以这个字开头的相关记录查找出来,输入2个字就过滤以这两个子开头的记录,依次类推. 突然要用到这 ...

  5. 从零开始,搭建博客系统MVC5+EF6搭建框架(4)上,前后台页面布局页面实现,介绍使用的UI框架以及JS组件

    一.博客系统进度回顾以及页面设计 1.1页面设计说明 紧接前面基础基本完成了框架搭建,现在开始设计页面,前台页面设计我是模仿我博客园的风格来设计的,后台是常规的左右布局风格. 1.2前台页面风格 主页 ...

  6. ASP.NET MVC搭建项目后台UI框架—2、菜单特效

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  7. ASP.NET MVC搭建项目后台UI框架—3、面板折叠和展开

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  8. ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  9. ASP.NET MVC搭建项目后台UI框架—5、Demo演示Controller和View的交互

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

随机推荐

  1. python 解除装饰器,调用原本函数。

    假设fun函数被装饰器装饰了,name调用fun,就不是调用fun本身了,那么如何继续调用本身呢.使用fun_raw = fun.__wrapped__这样使用fun_raw就是调用没被装饰器修饰后的 ...

  2. [Cassandra] Mutation of <x> bytes is too large for the maxiumum size of <y>

    [Cassandra] Mutation of bytes is too large for the maxiumum size of Q: WARN [SharedPool-Worker-4] 20 ...

  3. java相对路径、绝对路径及类路径

    import java.io.File; import java.net.URL; /** * java相对路径.绝对路径及类路径的测试 */ public class Test { /** * 测试 ...

  4. Windows补丁更新Tips

    1.Windows 2012 R2 MS14-066补丁安装失败 现象:下载对应版本的补丁,提示“此更新不适用于你的计算机” 解决:使用命令行可成功安装 @echo off expand –F:* d ...

  5. 【MyBatis学习06】_parameter:解决There is no getter for property named in class java.lang.String

    我们知道在mybatis的映射中传参数,只能传入一个.通过#{参数名} 即可获取传入的值. Mapper接口文件: public int delete(int id) throws Exception ...

  6. 禅道迁移(windows_to_linux)

    需求分析 随着禅道数据的增加,原来通过虚拟机提供的mysql服务器相应速度跟不上需求.且原来禅道的前端与数据库分离安装在windows与linux中,现在提供实体服务器,需要将禅道环境迁移. 确认环境 ...

  7. java基础编程

    java的类和常用编程模式还是要多练习,多手写java代码 return new String(filecontent, encoding); 看懂这个意思了吗?第一次见这个构造函数吧,而String ...

  8. [LeetCode] Group Anagrams 群组错位词

    Given an array of strings, group anagrams together. Example: Input: ["eat", "tea" ...

  9. PHP(方法 函数 循环 和 数组 查找)

    循环 和 数组 查找 顺序查找 二分法查找 冒泡排序 方法 函数 定义:一堆代码的集合叫做函数(满足条件下“一堆”) 语法,定义,调用,参数列表(形参,实参),返回值 两种方法: function 方 ...

  10. itoa()、atoi()、任意进制转换

    头文件:<stdlib.h> itoa --功能:将任意类型的数字转换为字符串.在<stdlib.h>中与之有相反功能的函数是atoi. atoi----功 能: 将字符串转换 ...