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的尺寸調整成你要的尺寸就可以了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM