UGUI动态生成列表功能实现(增删保存)

在UGUI 里不免会有一些列表需要生成和显示。例如最简单的增、删、改、查等都需要列表的变化。本文只讲增、删、保存、清空UGUI配合的变化方法。

下面以实现场景里角色的实时位置的增加、删除、保存为案例开讲。

先看一下实现增加效果图:

首先是UI的制作,这个比较简单,之前讲过的,可以参考:http://blog.csdn.net/alayeshi/article/details/50240075

下面图片是整个列表的核心--grid和其子物体,grid就是生成所有子物体的父物体,而这些子物体就是新生成的列表里的每一行,在grid上规定好子物体的宽度和高度,然后加上Generaterecord脚本。

下面实现增加功能:

点击按钮增加一个grid的子物体,也就是新增加列表里的一行。gridlayoutgroup 是会自动排布好你增加出来的子物体。所以我们只需要写增加物体的代码就好。

而增加的方法其实就是在整个代码里的生成子物体的方法Generategrids()。在这个方法里不要忘记每增加一个gird的子物体都要将gird的高度增加,所以有了这句代码:

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);

删除的操作:

因为删除是多选删除,每次删除列表里的个数不确定,所有我们要给一个标记,因此会看到下图中会有一个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的尺寸调整成你要的尺寸就可以了。

猜你喜欢

转载自www.cnblogs.com/macky/p/9335108.html