unity的LayoutGroup分為三種,
Horizontal Layout Group(水平布局):對象填充總個父物體,水平會填充
Vertical Layout Group(垂直布局):垂直(高度)會填充
Grid Layout Group (網格布局):以表格的形式布局,不會填充父物體
比如:垂直布局和水平布局效果
Grid Layout Group
如果單純的時候用滑動效果可以使用Scroll Rect組件即可。但使用布局就要使用布局控件
Grid Layout Group是網格布局,先看看一個效果
其實滑動依然是用的Scroll Rect。這個就不說了。這里主要說布局。
Spacing 表示 cell之間的距離。
Cell表示格子的寬度和和高度
Start Axis 表示布局方式,有橫向和縱向
Child Alignment 表示對齊方式。
注意Layout Group節點下面的所有cell節點都是不能修改Rect Transform的。因為cell可能下面會放很多圖片,這樣我們會用個空的gameObject來當父節點。
但你仔細看。會發現。這個不是整塊滑動的。比如手機屏幕左右滑動,是滑動區域判斷的。沒有划過來的時候。會退回去。像這樣
這里可以根據Scroll Rect組件的normalizedPosition屬性來判斷。這是一個Vector2坐標。是滑動中XY的值
horizontalNormalizedPosition:水平的值
verticalNormalizedPosition:垂直的值
需要在拖動結束后判斷。需要繼承
IBeginDragHandler,IEndDragHandler。引用命名空間:using UnityEngine.EventSystems;
具體代碼:
using UnityEngine; using System.Collections; using UnityEngine.EventSystems; using UnityEngine.UI; public class newScroll : MonoBehaviour, IBeginDragHandler, IEndDragHandler { ScrollRect rect; //頁面:0,1,2 索引從0開始 //每夜占的比列:0/2=0 1/2=0.5 2/2=1 float[] page = { 0, 0.5f, 1 }; //滑動速度 public float smooting = 4; //滑動的起始坐標 float targethorizontal = 0; //是否拖拽結束 bool isDrag = false; // Use this for initialization void Start() { rect = transform.GetComponent<ScrollRect>(); } // Update is called once per frame void Update() { //如果不判斷。當在拖拽的時候要也會執行插值,所以會出現閃爍的效果 //這里只要在拖動結束的時候。在進行插值 if (!isDrag) { rect.horizontalNormalizedPosition = Mathf.Lerp(rect.horizontalNormalizedPosition, targethorizontal, Time.deltaTime * smooting); } } /// <summary> /// 拖動開始 /// </summary> /// <param name="eventData"></param> public void OnBeginDrag(PointerEventData eventData) { isDrag = true; } /// <summary> /// 拖拽結束 /// </summary> /// <param name="eventData"></param> public void OnEndDrag(PointerEventData eventData) { isDrag = false; // //拖動停止滑動的坐標 // Vector2 f = rect.normalizedPosition; // //水平 開始值是0 結尾值是1 [0,1] // float h = rect.horizontalNormalizedPosition; // //垂直 // float v = rect.verticalNormalizedPosition; float posX = rect.horizontalNormalizedPosition; int index = 0; //假設離第一位最近 float offset = Mathf.Abs(page[index] - posX); for (int i = 1; i < page.Length; i++) { float temp = Mathf.Abs(page[i] - posX); if (temp < offset) { index = i; //保存當前的偏移量 //如果到最后一頁。反翻頁。所以要保存該值,如果不保存。你試試效果就知道 offset = temp; } } /* 因為這樣效果不好。沒有滑動效果。比較死板。所以改為插值 */ //rect.horizontalNormalizedPosition = page[index]; targethorizontal = page[index]; } }
像這種布局。內容是動態添加的。所以內容的多少是不確定的。很多時候是用u3d自帶的ContentSizeFitter。這個組件可以自動計算寬度
那么問題來了。當總數不是頁數的倍數,那么horizontalNormalizedPosition是不正確的。比如:有2頁。一頁5條
當只有6條。是不是也是2頁呢?。
所以又得必須動態計算了。
這里寫了一個適用於其他場合的類

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using UnityEngine; 6 using UnityEngine.EventSystems; 7 using UnityEngine.UI; 8 9 class UIScrollItemTips : MonoBehaviour, IBeginDragHandler, IEndDragHandler 10 { 11 //頁面:0,1,2 索引從0開始 12 //每夜占的比列:0/2=0 1/2=0.5 2/2=1 13 public List<float> pageArray; 14 15 //public List<float> PageArray 16 //{ 17 // // get { return pageArray; } 18 // set { pageArray = value; } 19 //} 20 private List<Toggle> toggleArray; 21 22 public List<Toggle> ToggleArray 23 { 24 //get { return toggleArray; } 25 set { toggleArray = value; } 26 } 27 public int pageCount;//多少頁 28 29 public int pageIndex = 0;//:當前頁碼 30 private ScrollRect rect; 31 //滑動速度 32 public float smooting; 33 34 public float Smooting 35 { 36 get { return smooting; } 37 set { smooting = value; } 38 } 39 40 private int pageSize; 41 42 /// <summary> 43 /// 一頁顯示多少條 44 /// </summary> 45 public int setPageSize 46 { 47 get { return pageSize; } 48 set { pageSize = value; } 49 } 50 51 private int sumRecord; 52 53 /// <summary> 54 /// 總記錄數 55 /// </summary> 56 public int setSumRecord 57 { 58 get { return sumRecord; } 59 set { sumRecord = value; } 60 } 61 62 private List<GameObject> pageList = new List<GameObject>(); 63 64 //滑動的起始坐標 65 public float targethorizontal = 0; 66 67 //是否拖拽結束 68 public bool isDrag = false; 69 70 71 public GameObject root; 72 73 private int updateInfo; 74 75 public int UpdateInfo 76 { 77 //get { return updateInof; } 78 set { Init(); } 79 } 80 81 //private static UIScrollItem instance; 82 //public static UIScrollItem Instance 83 //{ 84 // get { return instance; } 85 // //set { ObjectPools.instance = value; } 86 //} 87 88 void Init() 89 { 90 UnInit(); 91 //pageSize = 8; 92 //setSumRecord = 54; 93 smooting = 4; 94 rect = transform.GetComponent<ScrollRect>(); 95 pageArray = new List<float>(); 96 toggleArray = new List<Toggle>(); 97 targethorizontal = 0; 98 rect.horizontalNormalizedPosition = 0; 99 //instance = this; //單列 100 101 pageCount = Convert.ToInt32(Math.Ceiling((double)sumRecord / pageSize)); //sumRecord為總記錄數 102 103 //Debug.LogError(pageCount); 104 105 //求出每頁的臨界角,頁索引從0開始 106 int num = pageCount - 1; 107 if (num == 0) num = 1; 108 for (int i = 0; i < pageCount; i++) 109 { 110 //Debug.LogError(i + "/" + num + "==" + (float)i / (float)num); 111 pageArray.Add((float)i / (float)num); 112 } 113 114 if (root != null) 115 { 116 ToggleGroup group = root.GetComponent<ToggleGroup>(); 117 118 for (int i = 0; i < pageCount; i++) 119 { 120 //獲取頁碼預設體 121 GameObject pageItem = U3DResources.SpawnUI("Item_New"); 122 pageList.Add(pageItem); 123 pageItem.transform.SetParent(root.transform); 124 pageItem.transform.localScale = new Vector3(1, 1, 1); 125 pageItem.transform.localRotation = new Quaternion(); 126 pageItem.transform.localPosition = Vector3.one; 127 128 Toggle toogle = pageItem.transform.Find("page").GetComponent<Toggle>(); 129 toogle.group = group; 130 toggleArray.Add(toogle); 131 } 132 133 134 } 135 136 //Debug.LogError(pageSize); 137 138 //rect.horizontalNormalizedPosition = 0; 139 140 //不管怎樣默認都是顯示最后一頁,同理,頁碼頁碼也是。已在生成頁碼時處理 141 //初始化不需要顯示滑動效果。直接賦值即可 142 //targethorizontal = pageArray[pageArray.Count - 1]; 143 //rect.horizontalNormalizedPosition = pageArray[pageArray.Count - 1]; 144 145 foreach (var item in toggleArray) 146 { 147 item.isOn = false; 148 } 149 150 if (toggleArray.Count > 0) 151 { 152 //默認第一個選中 153 toggleArray[0].isOn = true; 154 155 } 156 } 157 158 void Awake() 159 { 160 } 161 void Start() 162 { 163 //Init(); 164 //rect.horizontalNormalizedPosition = 0; 165 } 166 167 void Update() 168 { 169 //如果不判斷。當在拖拽的時候要也會執行插值,所以會出現閃爍的效果 170 ////這里只要在拖動結束的時候。在進行插值 171 if (!isDrag) 172 { 173 rect.horizontalNormalizedPosition = Mathf.Lerp(rect.horizontalNormalizedPosition, targethorizontal, Time.deltaTime * smooting); 174 175 //rect.horizontalNormalizedPosition = targethorizontal; 176 } 177 } 178 /// <summary> 179 /// 拖動開始 180 /// </summary> 181 /// <param name="eventData"></param> 182 public void OnBeginDrag(PointerEventData eventData) 183 { 184 isDrag = true; 185 } 186 187 /// <summary> 188 /// 拖拽結束 189 /// </summary> 190 /// <param name="eventData"></param> 191 public void OnEndDrag(PointerEventData eventData) 192 { 193 isDrag = false; 194 195 float posX = rect.horizontalNormalizedPosition; 196 int index = 0; 197 //假設離第一位最近 198 float offset = Mathf.Abs(pageArray[index] - posX); 199 for (int i = 1; i < pageArray.Count; i++) 200 { 201 float temp = Mathf.Abs(pageArray[i] - posX); 202 if (temp < offset) 203 { 204 index = i; 205 //保存當前的偏移量 206 offset = temp; 207 } 208 } 209 try 210 { 211 targethorizontal = pageArray[index]; 212 //說明頁碼大於1 toggle有值 213 if (pageCount > 1 && toggleArray.Count > 0) 214 toggleArray[index].isOn = true; 215 } 216 catch (Exception) 217 { 218 return; 219 } 220 } 221 222 void UnInit() 223 { 224 foreach (var item in pageList) 225 { 226 U3DResources.Despawn(item); 227 } 228 } 229 }
調用

1 itemTips.setSumRecord = nows; 2 itemTips.setPageSize = 8; 3 mItemGrid.GetComponent<ContentSizeFitter>().enabled = false; 4 5 //總頁數 6 int pageCount = Convert.ToInt32(Math.Ceiling((double)nows / itemTips.setPageSize)); //sumRecord為總記錄數 7 8 int resultCount = nows; 9 10 if (nows % itemTips.setPageSize != 0) 11 { 12 //求差 13 int poor = pageCount * itemTips.setPageSize - nows; 14 //加上差數。湊整 15 resultCount = nows + poor; 16 } 17 else 18 { 19 //可以啟用自動計算寬度 20 //mItemGrid.GetComponent<ContentSizeFitter>().enabled = true; 21 } 22 23 //Debug.LogError(nows); 24 //Debug.LogError(resultCount); 25 26 GridLayoutGroup group = mItemGrid.GetComponent<GridLayoutGroup>(); 27 float cellSize = group.cellSize.x; //一個格子的寬度 28 float spacing = group.spacing.x; //格子的間距 29 30 //總寬度 31 float totalWidth = cellSize * resultCount + (resultCount - 1) * spacing; 32 //Debug.LogError(totalWidth); 33 34 RectTransform rectWidth = mItemGrid.GetComponent<RectTransform>(); 35 Vector2 targetVec = new Vector2(totalWidth, rectWidth.sizeDelta.y); 36 rectWidth.sizeDelta = targetVec;
itemTips是UIScrollItemTips變量
ScrollRect滑動組件。怎么可以定位到哪個地方呢。即滑動到指定位置;
ScrollRect有個屬性normalizedPosition,是Vector2類型的。
如果是垂直滑動;那么范圍是1-0
比如到初始位置
GetComponent<ScrollRect>().normalizedPosition = new Vector2(0, 1);
滑動到最后一頁
GetComponent<ScrollRect>().normalizedPosition = new Vector2(0, 0);