文章目錄
- 一、前言
- 二、使用方法
- 1、創建Scroll View
- 2、設定Scroll View引數
- 2.1、調整寬高
- 2.2、洗掉Scrollbar滑塊
- 2.3、設定item模板: Item Template
- 2.4、設定物件池大小:Pool Size
- 2.5、設定串列排列方向
- 2.6、設定分頁大小: Page Size
- 2.7、其他常規設定
- 3、給item加點元素
- 4、寫測驗代碼
- 5、運行測驗
- 6、item直接增加間隔
- 三、BUG修復
- 四、Demo原始碼
- 五、完畢
一、前言
嗨,大家好,我是新發,
有小伙伴在提問區問Unity如何實作不規則回圈復用串列,

我今天發現GitHub上已經有人實作了一個版本,效果可以,
GitHub地址:https://github.com/aillieo/UnityDynamicScrollView
不過這個版本有個BUG,我做了修復,本文第三部分有說明,
好輪子大家用,今天我就介紹一下這個版本的使用方法吧~
本文最終效果如下

二、使用方法
1、創建Scroll View
在UI節點上創建一個Scroll View,

如下

將Scroll View節點的Scroll Rect組件移除,如下

掛上代碼中的ScrollView組件或ScrollViewEx組件,我這里以ScrollViewEx組件為例,
注:
ScrollViewEx繼承了ScrollView的所有功能,并進行了針對性的優化,它會對item進行分頁,設定適當的頁面尺寸可以得到更好的性能表現

掛上組件后效果如下,

2、設定Scroll View引數
2.1、調整寬高
我們先調整一下Scroll View的寬高,

2.2、洗掉Scrollbar滑塊
我們看到Scroll View帶了兩個Scrollbar滑塊,我們不想要它,

可以直接把子節點下的Scrollbar Horizontal和Scrollbar Vertical洗掉,

洗掉后可以看到Viewport之前給Scrollbar留了空間,現在沒有Scrollbar了,我們要調節一下Viewport使其填充整個Scroll View,

我們選中Viewport,把Right和Bottom都改為0,

如下

2.3、設定item模板: Item Template
串列中要顯示一個一個的item,得先做item模板,我們在Scroll View子節點下創建一個Image,重命名為item,如下,

調整一下item的寬高,

如下,

接著選中Scroll View節點,設定Item Template為剛剛的item,并填寫Default Item Size為item的寬高,如下

2.4、設定物件池大小:Pool Size
為了防止串列item的重復創建銷毀,這里用到了物件池,我們需要設定一下物件池大小Pool Size,如果一直往物件池塞物件(只塞不取),物件池滿了之后,就不再繼續塞物件到物件池中,我們需要設定合理的物件池大小,建議是串列可見區域能夠顯示的item的最大數量的2倍,這里我預估串列可見區域最多顯示10個item,那么我物件池大小設定為20,

2.5、設定串列排列方向
串列提供了4種排列方向,大家一看選項就知道是什么意思了,這里我以Vertical為例,

2.6、設定分頁大小: Page Size
如果你用的是ScrollView組件就沒有Page Size這個設定了,只有ScrollViewEx組件有這個設定,
為什么要設定分頁呢?ScrollView中維護了一份List<ScrollItemWithRect>,用于存盤item的坐標和尺寸,

假設你的串列有巨量的item資料,你現在要往中間插入一個新的item,這個時候要重新計算巨量的item的坐標和尺寸,非常的耗性能,解決辦法就是設定分頁,每次只維護一個分頁的item,大大提升性能,
建議設定為串列可見區域能夠顯示的item的最大數量的2倍以上,這里設定為30,

2.7、其他常規設定
設定一下Content和Viewport,如下

根據滑動方向勾選Horizontal或Vertical,這里我只需豎直方向滑動,所以只勾選Vertical,

3、給item加點元素
上面我們的item光溜溜的,給它加點元素,再微調一下整體界面,如下

節點結構如下

4、寫測驗代碼
創建一個MyTest.cs腳本,如下,
注:
TestScript.cs和TestLargeAmount.cs是原作者提供的測驗腳本,

先定義一個資料結構體
// MyTest.cs
public struct RankItemData
{
// 名次
public int rank;
// 名字
public string name;
}
宣告一個List物件,用于存盤串列資料,
// MyTest.cs
List<RankItemData> testData = new List<RankItemData>();
現在我們寫個方法來構造一些測驗資料,
// MyTest.cs
private void Start()
{
// 構造測驗資料
InitData();
}
private void InitData()
{
// 構建50000個排名資料
for (int i = 1; i <= 50000; ++i)
{
RankItemData data = new RankItemData();
data.rank = i;
data.name = "Name_" + i;
testData.Add(data);
}
}
宣告ScrollView成員物件,并給ScrollView設定回呼函式,如下
// MyTest.cs
using System.Collections.Generic;
using UnityEngine;
using AillieoUtils;
public class MyTest : MonoBehaviour
{
...
public ScrollView scrollView;
private void Start()
{
...
scrollView.SetUpdateFunc((index, rect) =>
{
// TODO 更新item的UI元素
});
scrollView.SetItemSizeFunc((index) =>
{
// TODO 回傳item的尺寸
return Vector2.one;
});
scrollView.SetItemCountFunc(() =>
{
// TODO 回傳資料串列item的總數
return 0;
});
}
}
接下來我們挨個實作回呼的具體內容,
更新item的UI元素,
// MyTest.cs
scrollView.SetUpdateFunc((index, rectTransform) =>
{
// 更新item的UI元素
RankItemData data = testData[index];
rectTransform.gameObject.SetActive(true);
rectTransform.Find("rankText").GetComponent<Text>().text = data.rank.ToString();
rectTransform.Find("nameText").GetComponent<Text>().text = data.name;
Button btn = rectTransform.Find("Button").GetComponent<Button>();
btn.onClick.RemoveAllListeners();
btn.onClick.AddListener(()=>{
Debug.Log(data.name);
});
});
回傳item的尺寸,我希望前三名的item高度高一些,回傳Vector2(812, 180),其他的回傳Vector2(812, 100),
// MyTest.cs
scrollView.SetItemSizeFunc((index) =>
{
// 回傳item的尺寸
RankItemData data = testData[index];
if(data.rank <= 3)
{
return new Vector2(812, 180);
}
else
{
return new Vector2(812, 100);
}
});
回傳資料串列item的總數,
// MyTest.cs
scrollView.SetItemCountFunc(() =>
{
// 回傳資料串列item的總數
return testData.Count;
});
5、運行測驗
我們將MyTest.cs腳本掛到Canvas上,并賦值Scroll View成員,如下,

接著,我們把item隱藏掉,

運行,效果如下,

嗯,item與item之間少了間隔,我們改造一下,
6、item直接增加間隔
在item下創建一個Image并重命名為bg,設定Anchors為stretch-strech,設定Top和Bottom位2,這樣就會上下留2個單位的縫隙了,

我們把item自身的Image組件刪掉,重新運行,效果如下,達到我們的效果了

我們可以看到,雖然我們的串列資料有50000個,但UI只有幾個item在回圈復用著,特別適合用于資料項很多的串列的顯示,

三、BUG修復
測驗的時候發現一個BUG,使用ScrollViewEx.cs時,翻頁的時候,在邊界時會瘋狂觸發OnValueChanged導致快速翻頁,

我在Demo做了修復,增加了一個阻尼,避免瘋狂翻頁,

四、Demo原始碼
本文Demo原始碼我已上傳到GitCode,感興趣的同學可自行下載學習,
地址:https://codechina.csdn.net/linxinfa/UnityDynamicScrollView

五、完畢
好了,就寫到這里吧,
我是新發,https://blog.csdn.net/linxinfa
一個在小公司默默奮斗的Unity開發者,希望可以幫助更多想學Unity的人,共勉~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/386736.html
標籤:其他
