在UGUI 里难免会有一些列表须要生成和显示。例如最简单的增、删、改、查等都须要列表的变化。本文只讲增、删、保存、清空UGUI配合的变化方法。ide
下面以实现场景里角色的实时位置的增长、删除、保存为案例开讲。post
先看一下实现增长效果图:this
首先是UI的制做,这个比较简单,以前讲过的,能够参考:http://blog.csdn.net/alayeshi/article/details/50240075spa
下面图片是整个列表的核心--grid和其子物体,grid就是生成全部子物体的父物体,而这些子物体就是新生成的列表里的每一行,在grid上规定好子物体的宽度和高度,而后加上Generaterecord脚本。.net
下面实现增长功能:设计
点击按钮增长一个grid的子物体,也就是新增长列表里的一行。gridlayoutgroup 是会自动排布好你增长出来的子物体。因此咱们只须要写增长物体的代码就好。rest
而增长的方法其实就是在整个代码里的生成子物体的方法Generategrids()。在这个方法里不要忘记每增长一个gird的子物体都要将gird的高度增长,因此有了这句代码:code
this.gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(this.gameObject.GetComponent<RectTransform>().sizeDelta.x, this.gameObject.GetComponent<RectTransform>().sizeDelta.y + this.GetComponent<GridLayoutGroup>().cellSize.y + this.GetComponent<GridLayoutGroup>().spacing.y);
删除的操做:orm
由于删除是多选删除,每次删除列表里的个数不肯定,全部咱们要给一个标记,所以会看到下图中会有一个toggle。若是Toggle是被选中的状态而且点击了删除按钮那么列表里全部被选中的行都会被删除。在代码里须要一个list来保存全部被添加进来的子物体们,在删除时要遍历他们,而后根据toggle的状态决定这些子物体中那些要被删除,删除要destroy被选中的物体,还要把list里的对应的移除掉,以及把grid的高度改变。整个方法在代码里是Destroyselfs()整个方法。对象
下面实现保存的方法:
保存咱们用unity本身的方法 PlayerPrefs.SetInt();原理很简单,它里面的两个参数分别是一个key,一个value。根据key来判断value。例如: PlayerPrefs.SetInt("存储个数", gridlist.Count);若是“存储个数”整个字符串是存在的那么就能够得到gridlist.count整个value。因此咱们在保存的时候要保证key是不一样的。而后当下次运行时就根据key来判断,而后加载那些value而且显示到列表的行中。
具体要看如下代码:
下面是以上增删保存的所有的代码:
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 using UnityEngine.UI; 5 6 public class generaterecords : MonoBehaviour 7 { 8 public Button ADD, Delete, Save, Clearsave; 9 private string gridpath; 10 private GameObject gridrecord; 11 12 string positions;//用来解析位置信息 13 Vector3 personpositions;//坐标位置 14 15 List<string> postionlist = new List<string>();//保存grid里面的文字 16 List<string> describepositionlist = new List<string>();//位置前的文字描述 17 18 List<GameObject> gridlist = new List<GameObject>(); //用来存储grid下的对象 19 GameObject go;//生成的grid子物体 20 21 22 23 string loadpositions;//加载的位置信息 24 string loadstring;//加载位置信息对应的文字 25 // Use this for initialization 26 void Start() 27 { 28 ADD.onClick.AddListener(Addposition); 29 Delete.onClick.AddListener(Deletposition); 30 Save.onClick.AddListener(Saveposition); 31 Clearsave.onClick.AddListener(Clearall); 32 33 34 gridpath = "backup/gridcontent"; 35 36 gridrecord = Resources.Load(gridpath, typeof(GameObject)) as GameObject; 37 38 if (gridrecord != null) 39 { 40 Debug.Log(gridrecord.name); 41 } 42 43 //清空位置的list 44 postionlist.Clear(); 45 //清空物体list 46 gridlist.Clear(); 47 ///初始化加载grid物体个数 48 /// 49 if (PlayerPrefs.GetInt("存储个数", 0) > 0) 50 { 51 Debug.Log("得到到存储的个数是" + PlayerPrefs.GetInt("存储个数", 0)); 52 53 //遍历存储的个数,并生产grid物体 54 for (int i = 0; i < PlayerPrefs.GetInt("存储个数", 0); i++) 55 { 56 57 Debug.Log("得到的当前存储key是" + i); 58 59 //获取保存的位置数据--以备填充到grids物体里 60 ///经过key来进行获取数值,key必定是从0开始的,只要最后小于存储个数(也就是list.count)一位就OK, 61 ///而该for循环里的i也是从0开始的因此正好 62 63 if (i < PlayerPrefs.GetInt("存储个数", 0)) 64 { 65 loadpositions = PlayerPrefs.GetString(i.ToString(), "没有该key呀"); 66 Debug.Log("获取的内容;" + loadpositions); 67 postionlist.Add(loadpositions); 68 69 loadstring = PlayerPrefs.GetString(i.ToString() + "describe", "描述位置的文字"); 70 describepositionlist.Add(loadstring); 71 } 72 73 //生成grids物体 74 Generategrids(); 75 76 } 77 } 78 else 79 { 80 Debug.Log("存储次数居然为" + PlayerPrefs.GetInt("存储次数", 0)); 81 } 82 83 } 84 //添加方法 85 void Addposition() 86 { 87 //主角位置信息获取 88 personpositions = GameObject.Find("FPSControllermine").transform.position; 89 positions = personpositions.ToString(); 90 Debug.Log("主角位置:" + positions); 91 92 Generategrids(); 93 94 //生成文字位置 95 Generateposition(); 96 } 97 98 //delet方法 99 void Deletposition() 100 { 101 Destroyselfs(); 102 } 103 ////保存的方法 104 void Saveposition() 105 { 106 Debug.Log("描述文字:8888"); 107 if (gridlist.Count > 0) 108 { 109 for (int i = 0; i < gridlist.Count; i++) 110 { 111 Debug.Log("描述文字:qqq"); 112 //存的描述的文字不能是空和“” 113 if (gridlist[i].transform.FindChild("InputField/Text").GetComponent<Text>().text != "") 114 115 { 116 Debug.Log("描述文字:ssss"); 117 string describetextfor = gridlist[i].transform.FindChild("InputField/Text").GetComponent<Text>().text;//保持描述 118 119 string positionstextfor = gridlist[i].transform.FindChild("positontext").GetComponent<Text>().text;//保存位置 120 deleteclicksaved(i, positionstextfor, describetextfor);//保存方法 121 Debug.Log("描述文字:" + describetextfor); 122 } 123 } 124 125 } 126 } 127 128 /// <summary> 129 /// 清空方法 130 /// </summary> 131 void Clearall() 132 { 133 PlayerPrefs.DeleteAll(); 134 } 135 // Update is called once per frame 136 void Update() 137 { 138 139 140 141 } 142 /// <summary> 143 /// 生成整个gird子物体 144 /// </summary> 145 public void Generategrids() 146 { 147 148 //生成record的物体、 149 go = Instantiate(gridrecord, this.transform.position, Quaternion.identity); 150 go.transform.SetParent(this.transform); 151 152 153 //默认是false,也就是不被选中的 154 go.transform.FindChild("Toggle").GetComponent<Toggle>().isOn = false; 155 156 157 //每个go位置信息显示(加载过来的文本显示) 158 if (loadpositions != null) 159 { 160 go.transform.FindChild("positontext").GetComponent<Text>().text = loadpositions;//位置的文字 161 162 163 go.transform.FindChild("InputField/content").gameObject.SetActive(true);//显示出来不可更改的东西 (描述文字的父物体) 164 165 go.transform.FindChild("InputField/content/changed").GetComponent<Text>().text = loadstring; //描述文字 166 167 } 168 169 gridlist.Add(go); 170 171 Debug.Log("物体个数" + gridlist.Count); 172 173 //本grid长度加go的高度 174 175 this.gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(this.gameObject.GetComponent<RectTransform>().sizeDelta.x, this.gameObject.GetComponent<RectTransform>().sizeDelta.y + this.GetComponent<GridLayoutGroup>().cellSize.y + this.GetComponent<GridLayoutGroup>().spacing.y); 176 Debug.Log("grid的高度" + this.gameObject.GetComponent<RectTransform>().sizeDelta); 177 } 178 179 180 /// <summary> 181 /// 位置获取,只有新添加位置才会触发,从外面加载不走这里 182 /// </summary> 183 /// 184 private void Generateposition() 185 { 186 187 //位置信息显示 188 go.transform.FindChild("positontext").GetComponent<Text>().text = positions; 189 190 go.transform.FindChild("InputField/content").gameObject.SetActive(false);//描述文字的父物体不显示 191 192 193 194 } 195 /// <summary> 196 /// 销毁被选中的gird子物体 197 /// </summary> 198 /// 199 void Destroyselfs() 200 { 201 202 //由于gridlist的数量会在销毁期间变,因此把即将销毁的取出来存放而后销毁 203 204 //取出被勾选,将销毁的物体 205 // for (int i = 0; i <gridlist.Count; i++) 206 for (int i = gridlist.Count - 1; i >= 0; i--) 207 { 208 Debug.Log("list里有" + gridlist.Count + "个gird----" + "第" + i + "个是" + gridlist[i].transform.FindChild("Toggle").GetComponent<Toggle>().isOn); 209 if (gridlist[i].transform.FindChild("Toggle").GetComponent<Toggle>().isOn) 210 { 211 //所谓的key就是该物体当前在list里所处的位置 212 213 Destroy(gridlist[i]); 214 215 // 将对应里面的坐标list销毁 216 // postionlist.Remove(postionlist[i]); 217 218 //将物体引用list销毁 219 gridlist.Remove(gridlist[i]); 220 221 222 //本grid长度减小60 223 this.gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(this.gameObject.GetComponent<RectTransform>().sizeDelta.x, this.gameObject.GetComponent<RectTransform>().sizeDelta.y - this.GetComponent<GridLayoutGroup>().cellSize.y - this.GetComponent<GridLayoutGroup>().spacing.y); 224 225 Debug.Log("删除后list里有" + gridlist.Count); 226 227 //将本次删除完剩下的list遍历,获取每一个物体的key,而后保存起来 228 for (int rest = 0; rest < gridlist.Count; rest++) 229 { 230 // if (gridlist[i].transform.FindChild("InputField/changed").GetComponent<Text>().text == "") 231 { 232 string savetext = gridlist[rest].transform.FindChild("positontext").GetComponent<Text>().text; 233 234 string describetext = gridlist[rest].transform.FindChild("InputField/content/changed").GetComponent<Text>().text; //描述文字 235 236 deleteclicksaved(rest, savetext, describetext); 237 238 } 239 240 } 241 242 if (gridlist.Count == 0) 243 { 244 PlayerPrefs.SetInt("存储个数", gridlist.Count); 245 } 246 247 248 } 249 250 } 251 252 253 } 254 255 256 void deleteclicksaved(int listkey, string saveposi, string described) 257 { 258 PlayerPrefs.SetInt("存储个数", gridlist.Count); 259 260 //存储个数就是最后剩下的list里的个数,比key的最大值大一,由于key是从0开始的 261 Debug.Log("存储key是" + listkey + "值是" + described); 262 //保存每一个位置 263 PlayerPrefs.SetString(listkey.ToString(), saveposi); 264 265 //保存描述文字 266 PlayerPrefs.SetString(listkey.ToString() + "describe", described); 267 } 268 269 }
注:
在我设计的这个需求里,保存过的列表再次加载出来是不容许修改的。
实现这个很简单,在原来输入框(Inputfield)上又遮挡了一个透明的图片(此图名曰:content,默认是不出现这个图片的由于出现了就没法点击输入了),目的就是为了当被保存的输入框再次加载后鼠标点击没有反应,又由于是透明的图片因此依然能够看到以前你保存的名字。
这就是为何代码里会出现这句代码: go.transform.FindChild("InputField/content").gameObject.SetActive(false);
以下图:
这样全部的功能都实现了。若是你不想看原理,那就是把上面的脚本绑定到grid(你要展现的列表)上再把UI的尺寸调整成你要的尺寸就能够了。