unity UGUI動態滑動列表
步驟:
1.在SceneMail建立一個Panel 改名為ScrollRect,ScrollRect新增Mask和Scroll Rect元件,Scroll Rect元件勾選Vertical 只需要垂直滾動
2.在SceneMail建立一個Scrollbar控制元件
3.ScrollRect上新增子控制元件Panel 改名為ScorllView,ScorllView大小覆蓋ScrollRect
4.ScorllView新增子控制元件Panel 改名為Content,Content大小覆蓋ScorllView
5.Content新增Vertical Layout Group和Content size Fitter元件,Vertical Layout Group元件設定好間隔和對其方式,會自動排列我們新增的控制元件,Content size Fitter用來調整顯示內容
6.將ScorllView、Content和Scrollbar分別拖到ScrollRect裡面 如圖所示
7.Scollbar元件屬性Direction修改成 Bottom To Top(往下拉將ScorllRect底部隱藏部分拖出來)
8.製作Prefab Item
程式碼
using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class SceneMail : MonoBehaviour { public Button mItemPrefab;//要新增到列表的預設體按鈕元件 public Transform mContentTransform;//容器Content的transform public Scrollbar mScrollbar;//滑動條 List<Button> lists = newList<Button>();//存放按鈕元件 float itemHeight;//單個按鈕元件的height RectTransform rect;//容器content的rect public VerticalLayoutGroup group;//用於計算內容的高度 // Use this for initialization void Start() { rect = mContentTransform.GetComponent<RectTransform>(); itemHeight = mItemPrefab.GetComponent<RectTransform>().rect.height; ShowItems(); mScrollbar.value = 1.0f; } /// <summary> /// 顯示Item列表 /// </summary> void ShowItems() { for (int i = 0; i < 20; i++) { AddItem(); } } void Update() { //新增 if (Input.GetKeyDown(KeyCode.Alpha0)) { AddItem(); } //使列表跳轉到頂部 if (Input.GetKeyDown(KeyCode.Alpha1)) { ToTopFunc(); } //清空列表 if (Input.GetKeyDown(KeyCode.Alpha2)) { ClearFunc(); } } //新增元件 void AddItem() { Button item = Instantiate(mItemPrefab, transform.position, transform.rotation); item.GetComponentInChildren<Text>().text = lists.Count.ToString(); item.transform.parent = mContentTransform; lists.Add(item); //給每個按鈕元件監聽點選事件 item.onClick.AddListener( () => { onClickFunc(item); } ); //rect.sizeDelta的x是width //rect.sizeDelta的y是height //rect.sizeDelta=new Vector2(rect.sizeDelta.x, lists.Count * itemHeight); rect.sizeDelta = new Vector2(rect.sizeDelta.x, group.padding.top + group.padding.bottom + lists.Count * itemHeight + (lists.Count - 1) * group.spacing); //rect.sizeDelta = new Vector2(rect.sizeDelta.x, lists.Count * itemHeight); } //使列表跳轉到頂部 void ToTopFunc() { //offsetMin 是vector2(left, bottom); //offsetMax 是vector2(right, top); rect.offsetMin = new Vector2(rect.offsetMin.x,-rect.sizeDelta.y); rect.offsetMax = new Vector2(rect.offsetMax.x,0); } //使列表跳轉到底部 void ToBottomFunc() { /*rect.offsetMin = new Vector2(rect.offsetMin.x, 0); rect.offsetMax = new Vector2(rect.offsetMax.x, rect.sizeDelta.y);*/ } void onClickFunc(Button btn) { Debug.Log(btn.gameObject.GetComponent<Text>()); removeItemFunc(btn); } //清空列表 void ClearFunc() { for(int i = 0; i < lists.Count; i++) { Destroy(lists[i].gameObject); } lists = new List<Button>(); rect.sizeDelta = new Vector2(rect.sizeDelta.x, lists.Count * itemHeight); } //刪除單個按鈕元件 void removeItemFunc(Button _btn) { //因為Vertical Layout Group元件會自動排列新增上的控制元件,所以只需要移除場景中的物體模型和list中物件就行了 //排列位置的任務就交給Vertical Layout Group 了 Destroy(_btn.gameObject); int index = lists.IndexOf(_btn); lists.Remove(_btn); Debug.Log(lists.Count); //需要重置容器的height rect.sizeDelta = new Vector2(rect.sizeDelta.x, group.padding.top + group.padding.bottom + lists.Count * itemHeight + (lists.Count - 1) * group.spacing); //rect.sizeDelta = new Vector2(rect.sizeDelta.x, lists.Count * itemHeight); /* if (rect.sizeDelta.y > 1080) { rect.sizeDelta = new Vector2(rect.sizeDelta.x, lists.Count * itemHeight); } else { rect.sizeDelta = new Vector2(rect.sizeDelta.x, 1080); }*/ } }
用的時候只要把這個指令碼隨便綁到場景中就行
另外,在重置容器的height時,兩種方法我覺得都差不多,而且在新增和刪減元件時好像都還是有些問題的,這一點在用的時候要注意
其中group關聯的是
PS:
rect是RectTransform
rect.sizeDelta的x是width
rect.sizeDelta的y是height
rect.offsetMin 是vector2(left, bottom);
rect.offsetMax 是vector2(right, top);