第一次写博客,感觉好激动啊,哈哈哈。前些天博主在蛮牛社区看到一位博主自己写的UI框架,感觉太好了,然后就下载了下来。自己摸索了一段时间,按着那位博主的想法,自己实现了一下。然而那套框架完整版需要花几百块的大洋,对于博主这样的乡下人,太贵、买不起,哈哈。我就按着那个简易版的实现了一下,里面的Json配置加载文件,那位博主给的例子里面没有,我就按着他给的文章敲了一遍。然后博主又多加了一种用XML的配置加载。
其他的功能我都是按着那位博主的思想实现的。下面附带那位博主的博客地址http://www.manew.com/thread-102761-1-1.html
下面是我写的关于Xml配置加载
using System.Collections.Generic;
using UnityEngine;
using System.Xml;
public class ConfigManagerByXml
{
private Dictionary<string , string > _DicPathForms = new Dictionary<string, string>();
public Dictionary<string, string> DicPathForms
{
get
{
return _DicPathForms;
}
set
{
_DicPathForms = value;
}
}
public void LoadConfig()
{
_DicPathForms = LoadConfig<PathForms>("XmlConfig");
}
public Dictionary<string , string > LoadConfig<T>(string tablename)
{
// 定义配置字典
//Dictionary<int, T> dic = new Dictionary<int, T>();
Dictionary<string, string> dic = new Dictionary<string, string>();
// 定义xml文档
XmlDocument doc = new XmlDocument();
// 动态加载xml文档并强制转化为TextAsset
TextAsset text = Resources.Load("XmlConfig/" + tablename) as TextAsset;
// 载入文本资源的文本信息
doc.LoadXml(text.text);
// 获取节点路径获取配置的节点列表
XmlNodeList nodeList = doc.SelectNodes("Nodes/Node");
if (nodeList != null)
{
// 遍历节点列表,并获取列表中的所有数据
for (int i = 0; i < nodeList.Count; i++)
{
// 获取节点列表的一个子节点,并强制转化为Xml元素;
XmlElement elem = nodeList[i] as XmlElement;
// 生成一个配置对象,并将对象的成员赋值
T obj = XmlHelper.GreateAndSetValue<T>(elem);
//获取FormName
string formName = (string)obj.GetType().GetField("FormName").GetValue(obj);
//获取Paths
string paths = (string)obj.GetType().GetField("Paths").GetValue(obj);
if (!dic .ContainsKey (formName ))
{
dic.Add(formName, paths);
}
}
}
return dic;
}
}
public class PathForms
{
public string FormName;
public string Paths;
}
下面是简易版的XML配置工具
以后写Xml配置文件就直接可以引用下面两个类
using System;
using System.Collections.Generic;
using System.Reflection;
public static class TableParser
{
public static void ParsePropertyValue<T>(T obj, FieldInfo fieldInfo, string valueStr)
{
System.Object value = valueStr;
if (fieldInfo.FieldType.IsEnum)
value = Enum.Parse(fieldInfo.FieldType, valueStr);
else
{
if (fieldInfo.FieldType == typeof(int))
value = int.Parse(valueStr);
else if (fieldInfo.FieldType == typeof(byte))
value = byte.Parse(valueStr);
else if (fieldInfo.FieldType == typeof(bool))
value = bool.Parse(valueStr);
else if (fieldInfo.FieldType == typeof(float))
value = float.Parse(valueStr);
else if (fieldInfo.FieldType == typeof(double))
value = double.Parse(valueStr);
else if (fieldInfo.FieldType == typeof(uint))
value = uint.Parse(valueStr);
else if (fieldInfo.FieldType == typeof(ulong))
value = ulong.Parse(valueStr);
else
{
if (valueStr.Contains("\"\""))
valueStr = valueStr.Replace("\"\"", "");
if (valueStr.Contains("\\n"))
valueStr = valueStr.Replace("\\n", "\n");
// process the excel string.
if (valueStr.Length > 2 && valueStr[0] == '\"' && valueStr[valueStr.Length - 1] == '\"')
valueStr = valueStr.Substring(1, valueStr.Length - 2);
value = valueStr;
if (valueStr.Contains("[") && valueStr.Contains("]"))
{
valueStr = valueStr.Replace("[", "");
valueStr = valueStr.Replace("]", "");
List<object> idList = new List<object>();
string[] array = valueStr.Split(',');
for (int i = 0; i < array.Length; i++)
idList.Add(array[i]);
value = idList;
}
}
}
if (value == null)
return;
fieldInfo.SetValue(obj, value);
}
static T ParseObject<T>(string[] lines, int idx, Dictionary<int, FieldInfo> propertyInfos)
{
T obj = Activator.CreateInstance<T>();
string line = lines[idx];
string[] values = line.Split('\t');
foreach (KeyValuePair<int, FieldInfo> pair in propertyInfos)
{
if (pair.Key >= values.Length)
continue;
string value = values[pair.Key];
if (string.IsNullOrEmpty(value))
continue;
try
{
ParsePropertyValue(obj, pair.Value, value);
}
catch (Exception ex)
{
Console.WriteLine(string.Format("[{5}]ParseError: Row={0} Column={1} Name={2} Want={3} Get={4}",
idx + 1,
pair.Key + 1,
pair.Value.Name,
pair.Value.FieldType.Name,
value,
typeof(T).ToString()));
throw ex;
}
}
return obj;
}
static Dictionary<int, FieldInfo> GetPropertyInfos<T>(string memberLine)
{
Type objType = typeof(T);
string[] members = memberLine.Split("\t".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
Dictionary<int, FieldInfo> propertyInfos = new Dictionary<int, FieldInfo>();
for (int i = 0; i < members.Length; i++)
{
FieldInfo fieldInfo = objType.GetField(members[i]);
if (fieldInfo == null)
continue;
propertyInfos[i] = fieldInfo;
}
return propertyInfos;
}
public static T[] ParseContent<T>(string content)
{
// try parse the table lines.
string[] lines = content.Split("\n\r".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
if (lines.Length < 3)
{
//Console.WriteLine("表格文件行数错误,【1】属性名称【2】变量名称【3-...】值:" + typeof(T).ToString());
Console.WriteLine("表格文件行数错误,【1】属性名称【2】变量名称【3-...】值:" + typeof(T).ToString());
return null;
}
// fetch all of the field infos.
Dictionary<int, FieldInfo> propertyInfos = GetPropertyInfos<T>(lines[1]);
// parse it one by one.
T[] array = new T[lines.Length - 2];
for (int i = 0; i < lines.Length - 2; i++)
array[i] = ParseObject<T>(lines, i + 2, propertyInfos);
return array;
}
public static List<int[]> ParsePropertyValue(string text)
{
List<int[]> PropertyList = new List<int[]>();
if (text != "\"" && text != "")
{
string[] propertys = text.Split(";".ToCharArray());
foreach (string propertyString in propertys)
{
string[] propertySet = propertyString.Split("-".ToCharArray());
if (propertySet.Length >= 2)
{
int[] PropertyValue = new int[propertySet.Length];
for (int i = 0; i < propertySet.Length; i++)
PropertyValue[i] = int.Parse(propertySet[i]);
PropertyList.Add(PropertyValue);
}
}
}
return PropertyList;
}
}
using System;
using System.Reflection;
using System.Security;
using System.Xml;
public class XmlHelper
{
static public T GreateAndSetValue<T>(SecurityElement node)
{
T obj = Activator.CreateInstance<T>();
FieldInfo[] fields = typeof(T).GetFields();
for (int i = 0; i < fields.Length; i++)
{
string name = string.Format("{0}", fields[i].Name);
if (string.IsNullOrEmpty(name)) continue;
string fieldValue = node.Attribute(name);
if (string.IsNullOrEmpty(fieldValue)) continue;
try
{
TableParser.ParsePropertyValue<T>(obj, fields[i], fieldValue);
}
catch (Exception ex)
{
Console.WriteLine(string.Format("XML读取错误:对象类型({2}) => 属性名({0}) => 属性类型({3}) => 属性值({1})",
fields[i].Name, fieldValue, typeof(T).ToString(), fields[i].FieldType.ToString()));
}
}
return obj;
}
static public T GreateAndSetValue<T>(XmlElement node)
{
T obj = Activator.CreateInstance<T>();
FieldInfo[] fields = typeof(T).GetFields();
for (int i = 0; i < fields.Length; i++)
{
string name = string.Format("{0}", fields[i].Name);
if (string.IsNullOrEmpty(name)) continue;
string fieldValue = node.GetAttribute(name);
if (string.IsNullOrEmpty(fieldValue)) continue;
try
{
TableParser.ParsePropertyValue<T>(obj, fields[i], fieldValue);
}
catch (Exception ex)
{
Console.WriteLine(string.Format("XML读取错误:对象类型({2}) => 属性名({0}) => 属性类型({3}) => 属性值({1})",
fields[i].Name, fieldValue, typeof(T).ToString(), fields[i].FieldType.ToString()));
}
}
return obj;
}
}
下面是博主实现的效果
自己总结一下
使用这款UI框架时,编写UIForms脚本要注意自己写的该页面的UIType,那位博主UIType也标注清楚了。
这里我重复一下
UIFormType 三种类型:
Nomal 正常显示界面 Fixed 固定的界面 PopUp 弹出窗口界面
UIFormShowMode 三种类型:
Normal 正常显示 将所有显示的窗口存放到一个集合中
ReverseChange 反向切换类型 将反向切换的窗口存放到一个栈中出栈入栈实现窗口切换
HideOther 隐藏其他类型,该窗口显示时其他显示窗口的状态都会置为false
(博主补充一下,博主在测试这些功能时发现Fixed类型配合其他其他显示模式可能有些问题,自己看了很长时间,感觉还是有些问题,博主没有完整版感觉哈哈哈。)
UIFormLucenyType四种类型:
这个是关于PopUp界面时UIMask的显示\隐藏.界面可穿透/不可穿透的。
Lucency 完全透明,不能穿过
Translucence, 半透明,不能穿过
ImPentrate 低透明,不能穿过
Pentrate 可以穿透
那位博主UI框架实现了UI窗体的自动加载功能,我就想如果这些UI的Prefabs放到网络端再加载感觉是不是很美好,这不就可以实现了资源的热更新。这些预置体配置又是通过Json或XML配置那感觉不就太爽了。博主比较菜还在尝试中。。。。。
下面是我实现的UI框架Demo的下载地址链接:http://pan.baidu.com/s/1eSH03AE 密码:9s3p
第一次写博客,写的不完善的地方还多多包涵,谢谢指出~以后这里就是我的小屋了,会转载分享、创作一些博客,谢谢大家光临~