反正做都做了,再做一个用XML来布局并生成界面的
运行前它是这个样子:
运行TestXMLloadUI.cs脚本后,就生成了一个UI:
其中,加载XML布局的代码如下:
- using UnityEngine;
- using System.Collections;
- public class testXMLloadUI : MonoBehavIoUr {
- // Use this for initialization
- void Start () {
- UICreator.GetInstance().LoadFromXML(@"E:\work\cardTools\Assets\XMLFile1.xml");
- }
- }
XMLFile1.xml的内容如下:
- <?xml version="1.0" encoding="utf-8" ?>
- <NGUILayout xmlns:UIyang ="983323204">
- <UIRoot
- name ="UI_TEST"
- depth ="0"
- parentName ="ui_1">
- <Sprite
- adpClass = "SpriteAdp"
- objName ="tSprite"
- depth ="2"
- atlasName ="xxx"
- spriteName = "Emoticon - Frown"
- width = "100"
- height = "100"
- collider = "false"
- updateColByCOM = "true"
- cX = "10"
- cY = "10">
- <Layout
- alignParentTop=""
- alignParentBaseLineX ="">
- </Layout>
- </Sprite>
- <Label
- adpClass = "LabelAdp"
- objName ="tLabel"
- depth ="3"
- width ="100"
- height ="100"
- collider ="false"
- text ="xxxx"
- updateColByCOM = "true"
- cX = "10"
- cY = "10">
- <Layout
- alignParentBottom=""
- alignParentBaseLineX="">
- </Layout>
- </Label>
- <Texture
- adpClass = "NormalCOMAdp"
- objName ="tTexture"
- depth ="1"
- width ="10"
- height ="10"
- collider ="false"
- updateColByCOM = "true"
- cX = "10"
- cY = "10">
- <Layout
- fillParent="">
- </Layout>
- </Texture>
- <MeteDate
- adpClass = "MeteDateAdp"
- objName ="md"
- depth ="4">
- <Layout
- centerHorizontal=""
- centerVertical="">
- </Layout>
- </MeteDate>
- </UIRoot>
- </NGUILayout>
格式是我自己定义的,每个组件有它自己的属性和一个布局,其中布局的string是和上一篇中的布局enum一致的,并且在代码中有互相转换的地方
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- using System.Xml;
- using System;
- using yang.UI;
- using System.Reflection;
- public class UICreator : MonoBehavIoUr {
- static UICreator instance;
- public static UICreator GetInstance() {
- return instance;
- }
- void Awake() {
- instance = this;
- }
- public UIWidget[] template;
- public string LastError;
- public UIWidget ui;
- public List<UIWidget> LoadFromXML(string url,Func<string,string> fileHandle = null){
- string xmlPath;
- if(fileHandle!=null){
- xmlPath = fileHandle(url);
- }else{
- xmlPath = url;
- }
- List<UIWidget> lst_R_N = null;
- //try {
- XmlTextReader xTR = new XmlTextReader(xmlPath);
- xTR.WhitespaceHandling = WhitespaceHandling.None;
- while(xTR.Read()){
- xTR.MoveToElement();
- int nd = xTR.Depth;
- if (xTR.NodeType == XmlNodeType.EndElement)
- continue;
- //Debug.Log("current: " + xTR.Name+",depth:"+nd);
- switch (nd) {
- case 0://XML声明,不处理
- break;
- case 1://UIRoot
- if (lst_R_N != null)
- return null;
- else {
- //生成实例
- GameObject uiroot = Instantiate(ui.gameObject) as GameObject;
- UIWidget R = uiroot.GetComponent<UIWidget>();
- //获得属性
- string uiName = xTR.GetAttribute("name");
- string depth = xTR.GetAttribute("depth");
- string parentName = xTR.GetAttribute("parentName");
- //放入场景
- uiroot.name = uiName;
- R.depth = Int32.Parse(depth);
- UIRect pHook = getUIParent(parentName);
- uiroot.transform.parent = pHook.transform;
- uiroot.transform.localScale = Vector3.one;
- Dictionary<Layout,string> hLayout = new Dictionary<Layout,string>();
- hLayout.Add(Layout.fillParent,"");
- UILayoutTool.LayoutUI(R,null,hLayout);
- lst_R_N = new List<UIWidget>();
- lst_R_N.Add(R);
- }
- break;
- case 2://widget
- if (lst_R_N == null) {
- Debug.Log("return");
- return null;
- } else {
- string nodeName = xTR.Name;
- WidgetType wt;
- try {
- wt = (WidgetType)Enum.Parse(typeof(WidgetType),nodeName);
- } catch {
- Debug.Log("转换失败:" + nodeName);
- wt = WidgetType.None;
- }
- //生成实例
- int index = (int)wt;
- GameObject inst = Instantiate(template[index].gameObject) as GameObject;
- UIWidget w = inst.GetComponent<UIWidget>();
- //获得适配类名并反射执行
- string adpClass = xTR.GetAttribute("adpClass");
- //Debug.Log(xTR.Name+","+adpClass+",");
- Type adp = Type.GetType(adpClass);
- var CInfo = adp.GetConstructor(Type.EmptyTypes);
- var objAdp = CInfo.Invoke(null);
- MethodInfo minfo = adp.GetMethod("Init");
- minfo.Invoke(objAdp,new object[] {xTR,w});
- //放入场景
- GameObject uiroot = lst_R_N[0].gameObject;
- inst.transform.parent = uiroot.transform;
- inst.transform.localScale = Vector3.one;
- lst_R_N.Add(w);
- }
- break;
- case 3://layout
- if (lst_R_N == null) {
- return null;
- } else {
- UIWidget currentWidget = lst_R_N[lst_R_N.Count - 1];
- Dictionary<Layout,string> layout = new Dictionary<Layout,string>();
- int ac = xTR.AttributeCount;
- for (int i = 0; i < ac; i++) {
- xTR.MoveToAttribute(i);
- string k = xTR.Name;
- string v = xTR.Value;
- layout.Add((Layout)Enum.Parse(typeof(Layout),k),v);
- }
- UILayoutTool.LayoutUI(currentWidget,layout);
- //xTR.MoveToElement();
- }
- break;
- default://其它层节点,不处理
- break;
- }
- }
- return lst_R_N;
- //} catch (Exception e){
- // Debug.Log(e.ToString());
- // return null;
- //}
- }
- public UIRect defaultRoot;
- /// <summary>
- /// 寻找UI挂接点
- /// </summary>
- private UIRect getUIParent(string name){
- return defaultRoot;
- }
- }
- //UI组件
- public class COMAdp {
- public virtual void Init(XmlTextReader xTR,UIWidget widget) {
- string comName = xTR.GetAttribute("objName");
- string depth = xTR.GetAttribute("depth");
- widget.gameObject.name = comName;
- widget.depth = Int32.Parse(depth);
- }
- }
- public class NormalCOMAdp : COMAdp {
- public override void Init(XmlTextReader xTR,UIWidget widget) {
- base.Init(xTR,widget);
- string width = xTR.GetAttribute("width");
- string heigth = xTR.GetAttribute("height");
- string collider = xTR.GetAttribute("collider");
- string updateColByCOM = xTR.GetAttribute("updateColByCOM");
- string cX = xTR.GetAttribute("cX");
- string cY = xTR.GetAttribute("cY");
- widget.width = Int32.Parse(width);
- widget.height = Int32.Parse(heigth);
- if(Boolean.Parse(collider)){
- var col = widget.gameObject.AddComponent<BoxCollider>();
- if (Boolean.Parse(updateColByCOM)) {
- widget.autoResizeBoxCollider = true;
- } else {
- col.size = new Vector3(Int32.Parse(cX),Int32.Parse(cY));
- }
- }
- }
- }
- public class SpriteAdp : NormalCOMAdp {
- public override void Init(XmlTextReader xTR,widget);
- string atlasName = xTR.GetAttribute("atlasName");
- string spriteName = xTR.GetAttribute("spriteName");
- var s = (UISprite)widget;
- s.spriteName = spriteName;
- }
- }
- public class LabelAdp : NormalCOMAdp {
- public override void Init(XmlTextReader xTR,widget);
- string text = xTR.GetAttribute("text");
- var l = (UILabel)widget;
- l.text = text;
- }
- }
- public class MeteDateAdp : COMAdp {
- public override void Init(XmlTextReader xTR,widget);
- }
- }
同时在调试的过程中发现上一篇的UILayoutTool.cs是存在问题的,就是上次是布局已经存在于场景中的UIWidget,而这一次是从prefab生成的,所以72-75行的获取组件父物体方法是失败的,大概原因是prefab的脚本缓存了错误的父物体,改为如下则没有问题了:
- <span style="white-space:pre"> </span>if (NGUITools.FindInParents<UIRect>(widget.transform.parent.gameObject).GetType() == typeof(UIPanel)) {
- ptarget = (UIPanel)NGUITools.FindInParents<UIRect>(widget.transform.parent.gameObject);
- } else {
- target = (UIWidget)NGUITools.FindInParents<UIRect>(widget.transform.parent.gameObject);
- }
写得比较粗糙,目前还存在的问题有:
XML的格式要求比较严格,没做缺省参数检查,必须写完所有参数;在XML中也不支持注释等
Sprite没有做加载图集部分,现在只能用prefab指定的图集
Textrue同样没有做设置mainTexture的部分,需要手动在其它地方设置
不过,LoadFromXML函数返回了UI的根和所有的组件的list,可以利用它做更多的事情,也可以结合一些动态脚本什么的,做更多东西
哦,对了,还有个UICreatorEditor.cs,就是UICreator的面板显示脚本:
- using UnityEngine;
- using System.Collections;
- using UnityEditor;
- [CustomEditor(typeof(UICreator),true)]
- public class UICreatorEditor : Editor {
- protected UICreator mUICreator;
- void OnEnable() {
- mUICreator = target as UICreator;
- if(mUICreator.template == null)
- mUICreator.template = new UIWidget[10];
- }
- public override void OnInspectorGUI() {
- //base.OnInspectorGUI();
- serializedObject.Update();
- mUICreator.defaultRoot = (UIRect)EditorGUILayout.ObjectField("默认UI挂接点",mUICreator.defaultRoot,typeof(UIRect));
- mUICreator.ui = (UIWidget)EditorGUILayout.ObjectField("UI根",mUICreator.ui,typeof(UIWidget));
- EditorGUILayout.Separator();
- if (NGUIEditorTools.DrawHeader("prefab")) {
- NGUIEditorTools.BeginContents();
- mUICreator.template[0] = (UIWidget)EditorGUILayout.ObjectField("MeteDate(自定义)",mUICreator.template[0],typeof(UIWidget));
- mUICreator.template[1] = (UIWidget)EditorGUILayout.ObjectField("Sprite(精灵)",mUICreator.template[1],typeof(UIWidget));
- mUICreator.template[2] = (UIWidget)EditorGUILayout.ObjectField("Label(字符串)",mUICreator.template[2],typeof(UIWidget));
- mUICreator.template[3] = (UIWidget)EditorGUILayout.ObjectField("Texture(纹理)",mUICreator.template[3],typeof(UIWidget));
- mUICreator.template[4] = (UIWidget)EditorGUILayout.ObjectField("Button(按钮)",mUICreator.template[4],typeof(UIWidget));
- mUICreator.template[5] = (UIWidget)EditorGUILayout.ObjectField("Toggle(选择框)",mUICreator.template[5],typeof(UIWidget));
- mUICreator.template[6] = (UIWidget)EditorGUILayout.ObjectField("ProgressBar(进度条)",mUICreator.template[6],typeof(UIWidget));
- mUICreator.template[7] = (UIWidget)EditorGUILayout.ObjectField("Slider(滑动条)",mUICreator.template[7],typeof(UIWidget));
- mUICreator.template[8] = (UIWidget)EditorGUILayout.ObjectField("Input(输入框)",mUICreator.template[8],typeof(UIWidget));
- mUICreator.template[9] = (UIWidget)EditorGUILayout.ObjectField("ScrollBar(滚动条)",mUICreator.template[9],typeof(UIWidget));
- NGUIEditorTools.EndContents();
- }
- EditorGUILayout.Separator();
- serializedObject.ApplyModifiedProperties();
- }
- }