UGUI之布局的使用
2015-10-03 23:20 糯米粥 阅读(12841) 评论(4) 编辑 收藏 举报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);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?