UGUI實現(xiàn)ScrollView無限滾動效果
抽空做了一個UGUI的無限滾動的效果。只做了一半(向下無限滾動)。網(wǎng)上也看了很多教程,感覺還是按照自己的思路來寫可能比較好。搭建如下:
content節(jié)點不添加任何組件。布局組件默認是會重新排版子節(jié)點的,所以如果子節(jié)點的位置變化,會重新排版,不能達到效果。Size Fitter組件也不加,自己寫代碼調(diào)整Size大?。ú徽{(diào)整大小,無法滑動)。
最主要的實現(xiàn)過程就是用Queue來搬運Cell。在向下滾動的過程中(鼠標上滑),頂部滑出View Port的Cell被搬運到底部續(xù)上。這點類似于Queue的先見先出原則,再把Dequeue出來的元素添加到末尾,就很類似于ScrollView的無限滾動的原理了。在鼠標上滑的過程中,content的PosY值是一直增加的,所以觸發(fā)滾動的條件就可以設(shè)定為位移之差大于Cell的高度值即可。
數(shù)據(jù)的刷新,數(shù)據(jù)到頭之后,不能再次進行滾動輪換了,這里用一組值來記錄初始化的一組Cell顯示的是數(shù)據(jù)的哪一段。例如HeadNum和TaiNum。比如用20個Cell顯示100條數(shù)據(jù)。初始化后,HeadNum就是0,TailNum就是19。上滑一行數(shù)據(jù)后,HeadNum=4,TailNum=23(這里假設(shè)是20個Cell排成4列)。
下面是完整代碼:
public class UIScrollViewTest : MonoBehaviour { public RectTransform content; public GameObject cell; // cell的初始化個數(shù) public int cellAmount = 0; // 鼠標上滑時,存儲Cell的Queue。正序存儲 public Queue F_cellQuee = new Queue(); // 鼠標下滑時,存儲Cell的Queue。到序存儲 public Queue B_cellQuee = new Queue(); // cell的Size public Vector2 cellSize = new Vector2(100,100); // cell的間隔 public Vector2 cellOffset = new Vector2(0,0); // 列數(shù) public int columnCount = 0; private int rowCount; // 上一次content的位置 public float lastPos; // 滾動的次數(shù) public int loopCount = 0; // cell顯示的數(shù)據(jù)段的開頭和結(jié)尾序號 public int HeadNum = 0; public int TailNum; public Sprite[] sp; public List<Sprite> data; void Start() { for (int i = 0; i < sp.Length; i++) { data.Add(sp[i]); } InitialScrollView(data); TailNum = cellAmount-1; lastPos = content.localPosition.y; //Debug.LogError("行數(shù)是:::" + rowCount); //Debug.LogError("+++++++++++++++++ " + (5>>3)); } void Update() { // 觸發(fā)滾動。 if (content.localPosition.y - lastPos > cellSize.y && data.Count - cellAmount - loopCount*columnCount >0) { //Debug.LogError("11111111111 " + (data.Count - cellAmount - loopCount * columnCount)); LoopScrolView(data); lastPos = content.localPosition.y; } } // 初始化cell void InitialScrollView(List<Sprite> data) { for (int i = 0; i < cellAmount; i++) { GameObject obj = Instantiate(cell.gameObject); obj.transform.SetParent(content); obj.name = "cell0" + i.ToString(); obj.transform.GetChild(0).GetComponent<Text>().text = "cell0"+i.ToString(); // 顯示默認的數(shù)據(jù) obj.GetComponent<Image>().sprite = data[i]; } // 初始化Queue for (int i = content.childCount-1; i >= 0; i--) { B_cellQuee.Enqueue(content.GetChild(i).gameObject); } for (int i = 0; i < content.childCount; i++) { F_cellQuee.Enqueue(content.GetChild(i).gameObject); } // 計算行數(shù) if (cellAmount % columnCount >0) { rowCount = cellAmount / columnCount + 1; } else { rowCount = cellAmount / columnCount; } // 排列cell的位置 int index = 0; for (int r = 1; r <= rowCount; r++) { for (int c = 1; c <= columnCount; c++) { if (index < cellAmount) { Vector2 pos = new Vector2(cellSize.x / 2 + (cellSize.x + cellOffset.x) * (c-1), -cellSize.y / 2 - (cellOffset.y + cellSize.y) * (r-1)); content.GetChild(index).GetComponent<RectTransform>().SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, 0, 100); content.GetChild(index).GetComponent<RectTransform>().SetInsetAndSizeFromParentEdge(RectTransform.Edge.Left, 0, 100); content.GetChild(index).GetComponent<RectTransform>().anchoredPosition = pos; index++; } } } Vector2 v = content.sizeDelta; // 初始化content的size content.sizeDelta = new Vector2(v.x, rowCount * cellSize.y + cellOffset.y*(rowCount-1)); } /// 保持content的大小,這里是保持大小為在cell的行數(shù)基礎(chǔ)上,向下多出bottomCount行的距離 void SetContentSize(int upperCount, int bottomCount) { if (content.sizeDelta != new Vector2(content.sizeDelta.x, content.sizeDelta.y + bottomCount * (cellSize.y + cellOffset.y))) { content.sizeDelta = new Vector2(content.sizeDelta.x, content.sizeDelta.y + bottomCount*(cellSize.y + cellOffset.y)); } } // 計算頂部的Cell輪換到底部時的位置。以當前最后一行的最后一個Cell的位置為基準計算。 void SetBottomCellPosition(int index, RectTransform rect, Vector2 pos) { Vector2 v = Vector2.zero; if (cellAmount % columnCount == 0) // 整除。每一行都滿的情況。 { float x = pos.x - cellSize.x * (columnCount - index-1) - cellOffset.x * (columnCount-index-1); float y = pos.y - cellSize.y - cellOffset.y; v = new Vector2(x,y); } // 出現(xiàn)不滿行的情況。例如數(shù)據(jù)有103個,可以用23個cell來輪換。這樣就會出現(xiàn)不滿行的情況。 // 這種情況下是頂部的一行cell順次接到底部不滿的行。例如23號cell后面接1號和2號cell,3號和4號cell填充到第“7”行 else if (cellAmount % columnCount + index+1<=columnCount) { float x = pos.x + cellSize.x * (index+1) + cellOffset.x * (index+1); float y = pos.y; v = new Vector2(x, y); } else { float x = pos.x - cellSize.x * (columnCount - index-1) - cellOffset.x * (columnCount - index-1); float y = pos.y - cellSize.y - cellOffset.y; v = new Vector2(x, y); } //Debug.LogError("++++++++++++++ " + pos+ " "+ v); rect.anchoredPosition = v; rect.SetAsLastSibling(); } // 計算底部的cell輪換到頂部是的位置,基準位置是當前行的第一個cell。 void SetUpperCellPosition(int index, RectTransform rect, Vector2 pos) { Vector2 v = Vector2.zero; if (cellAmount % columnCount == 0) // 整除 { float x = pos.x + cellSize.x * index + cellOffset.x * index; float y = pos.y + cellSize.y + cellOffset.y; v = new Vector2(x, y); } //else if (cellAmount % columnCount + index + 1 <= columnCount) //{ // float x = pos.x + cellSize.x * (index + 1) + cellOffset.x * (index + 1); // float y = pos.y; // v = new Vector2(x, y); //} //else //{ // float x = pos.x - cellSize.x * (columnCount - index - 1) - cellOffset.x * (columnCount - index - 1); // float y = pos.y - cellSize.y - cellOffset.y; // v = new Vector2(x, y); //} //Debug.LogError("++++++++++++++ " + pos+ " "+ v); rect.anchoredPosition = v; rect.SetAsFirstSibling(); } // 鼠標上滑時,顯示當前cell的數(shù)據(jù)。同時記錄數(shù)據(jù)段的序號遞增。 void ShowRestCellData(Image cell, int index) { if (TailNum< data.Count-1) { Debug.LogError("當前的序號是::::" + TailNum); TailNum++; HeadNum++; cell.sprite = data[TailNum]; } } void ShowPreviousCellData(Image cell, int index) { if (HeadNum > 0) { Debug.LogError("當前的序號是::::" + HeadNum); TailNum--; HeadNum--; cell.sprite = data[HeadNum]; } } // 輪換的函數(shù)。每次亂換一行的cell。 void LoopScrolView(List<Sprite> data) { SetContentSize(0, 1); loopCount++; RectTransform rect2 = content.GetChild(content.childCount - 1).GetComponent<RectTransform>(); for (int i = 0; i < columnCount; i++) { GameObject obj = F_cellQuee.Dequeue() as GameObject; RectTransform rect = obj.GetComponent<RectTransform>(); ShowRestCellData(obj.GetComponent<Image>(), i); SetBottomCellPosition(i, rect, rect2.anchoredPosition); F_cellQuee.Enqueue(obj); } } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
上一篇:Unity3D利用DoTween實現(xiàn)卡牌翻轉(zhuǎn)效果
欄 目:C#教程
下一篇:Unity5.6大規(guī)模地形資源創(chuàng)建方法
本文標題:UGUI實現(xiàn)ScrollView無限滾動效果
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/4875.html
您可能感興趣的文章
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻 器左下角滾動新聞效果的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當前操作系統(tǒng)已安裝軟件變化的方法
- 01-10C#實現(xiàn)多線程下載文件的方法
- 01-10C#實現(xiàn)Winform中打開網(wǎng)頁頁面的方法
- 01-10C#實現(xiàn)遠程關(guān)閉計算機或重啟計算機的方法
- 01-10C#自定義簽名章實現(xiàn)方法
- 01-10C#文件斷點續(xù)傳實現(xiàn)方法
- 01-10winform實現(xiàn)創(chuàng)建最前端窗體的方法


閱讀排行
本欄相關(guān)
- 01-10C#通過反射獲取當前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻 器左下角滾動新
- 01-10C#停止線程的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當前操作系統(tǒng)已
隨機閱讀
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10C#中split用法實例總結(jié)
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery
- 01-10delphi制作wav文件的方法
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-11ajax實現(xiàn)頁面的局部加載
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05織夢dedecms什么時候用欄目交叉功能?