UGUI
控件是UGUI內(nèi)置的,控件上面因因包含不同的組件而不同。
-
Image組件
Image等價(jià)于NGUI的Sprite組件,用于顯示圖片。Panal控件就是包含Image組件的, Image控件也是包含Image組件的,Sprite 有圖集的概念,可以選擇整圖導(dǎo)入,UNITY中使用SpriteEditor切割,也可以選擇導(dǎo)入后設(shè)置圖片的packageTag系統(tǒng)自動(dòng)打包圖集,圖片小的,重復(fù)性比較高的圖片最好打成圖集,
注意:
1,一個(gè)圖集內(nèi)的圖片用UISprite,那么它就是一個(gè)DrawCall。但是如果你做了一個(gè)圖集是1024X1024的。此時(shí)你的界面 上只用了圖集中的一張很小的圖,那么很抱歉1024X1024這張大圖都需要載入你的內(nèi)存里面,1024就是4M的內(nèi)存,如果你做了10個(gè)1024的圖集,你的界面上剛好都只用了每個(gè)圖集里面的一張小圖,那么再次抱歉你的內(nèi)存直接飆40M
2.帶透明通道和不帶透明通道的,CreatMipMap和不Create 的,不能制作成同一圖集
組件屬性
Source Image(圖像源):紋理格式為Sprite(2D and UI)的圖片資源(導(dǎo)入圖片后選擇Texture Type為Sprite(2D and UI))。
Color(顏色):圖片疊加的顏色。
Material(材質(zhì)):圖片疊加的材質(zhì),可以用來實(shí)現(xiàn)一些特殊效果,如凹凸感覺
Raycast Target(射線投射目標(biāo)):是否作為射線投射目標(biāo),關(guān)閉之后忽略UGUI的射線檢測。
Set Native Size:點(diǎn)擊此按鈕則 Image 組件的長寬自動(dòng)與原圖片長寬一致
Image Type(圖片顯示類型):
Simple(基本的):圖片整張全顯示,不裁切,不疊加,根據(jù)邊框大小會(huì)有拉伸。
Preserve Aspect(鎖定比例):針對(duì)Simple模式,勾選之后,無論圖片的外形放大還是縮小,都會(huì)一直保持初始的長寬比例。
Sliced(切片的):圖片切片顯示,在Project頁面選中圖片,切換為Sprite(2D and UI)模式后,點(diǎn)擊Sprite Editor進(jìn)入圖片裁切模式,將圖片裁切為上圖的形狀,使用Sliced模式后,根據(jù)圖片邊框拉伸,圖片的四個(gè)角會(huì)保持原狀,而1和4部分會(huì)隨著圖片的橫向拉伸而拉伸,2和3部分會(huì)隨著圖片的縱向拉伸而拉伸,圖片的中間部分會(huì)拉伸5進(jìn)行填充。
Fill Center(填充中心):勾選后,5顯示,反之,5不可見。
Tiled(平鋪的):若圖片已經(jīng)過裁切,則使用Tiled模式后,根據(jù)圖片邊框拉伸,圖片的四個(gè)角會(huì)保持原狀,而1和4部分會(huì)隨著圖片的橫向拉伸而拉伸,2和3部分會(huì)隨著圖片的縱向拉伸而拉伸,圖片的中間部分會(huì)用5進(jìn)行平鋪填充。若圖片未裁切,則使用Tiled模式后,根據(jù)圖片邊框拉伸,圖片保持原大小不做變化,只是用自身平鋪填充。
Fill Center(填充中心):(已裁切的圖像源才有此選項(xiàng))勾選后,5顯示,反之,5不可見。
Filled(填充的):根據(jù)填充方式、填充起點(diǎn)、填充比例決定圖片顯示哪一部分。
Fill Method(填充方式):分為水平、垂直、90度圓、180度圓、360度圓。
Fill Origin(填充起點(diǎn)):根據(jù)填充方式不同有所變化。
Fill Amount(填充比例):0是完全不顯示,1是完全顯示。
我們將在學(xué)習(xí)button組件時(shí)進(jìn)行技能冷卻設(shè)置。
3D場景使用
1.單個(gè)Sprite 直接拖入場景中,系統(tǒng)自動(dòng)添加SpriteRanderder 組件,作為3D物體直接使用,2. 多個(gè)Sprite直接拖入場景,可以直接制作幀動(dòng)畫,在2D中同樣也可以。
代碼使用:
using UnityEngine;
using UnityEngine.UI;
public class ImgTest : MonoBehaviour {
public Image img;
public Material ml;
void Start () {
img = GetComponent<Image>();
// 通過資源加載進(jìn)行圖片的賦值
img.sprite = Resources.Load<Sprite>("UI/background");
img.color = Color.red;
img.material = ml;
img.raycastTarget = true;
// 根據(jù)填充方式、填充起點(diǎn)、填充比例決定圖片顯示哪一部分
img.type = Image.Type.Filled;
// 圖片具備在水平方向的拉伸,縮小,
// 根據(jù)下面的fillAmount數(shù)值進(jìn)行
img.fillMethod = Image.FillMethod.Horizontal;
// 設(shè)置圖片顯示為一半
img.fillAmount = 0.5f;
}
- RayImage 組件
Textture 指定要顯示的圖片,注意:圖片類型可以是任何類型
Color 設(shè)置圖片的主色調(diào)
Material 設(shè)定Image控件的渲染材質(zhì)
Raycast Target 決定是否可接收射線碰撞事件檢測
UV Rect 可以讓圖片的一部分顯示在RawImage組件中
2D使用中(平面UI):
1.Texture用在Raw Image組件上,可以用來制作動(dòng)畫
2.Tuxture沒有圖集的概念,這樣內(nèi)存里只會(huì)占用你這一張圖的大小,內(nèi)存雖然小了但是DrawCall就上去了。因?yàn)槊恳粡圲ITexture就是一次DrawCall。原畫或者背景圖建議直接使用UITexture。
3.可以通過UV 調(diào)節(jié)圖片顯示的偏移,和重復(fù)(可以用來制作多格子血條)
3D使用中(即直接拖動(dòng)此類型的圖片到3D坐標(biāo)系統(tǒng))
1.無論單個(gè)、多個(gè),不可以直接拖入3D場景中!2D也不行
2.用于3D模型貼圖,(Shader代碼把貼圖和紋理坐標(biāo)映射),再由GPU把模型渲染出來MeshFiiter組件中模型網(wǎng)格,存儲(chǔ)的紋理坐標(biāo)信息(Unity自己創(chuàng)建的Cube會(huì)自動(dòng)添加紋理坐標(biāo)所以創(chuàng)建后就能貼上紋理,3D建模時(shí)如果忽略 沒有給模型生成紋理坐標(biāo),會(huì)導(dǎo)致模型貼上貼圖沒有效果)MesherRenderder 物體渲染組件
using UnityEngine;
using UnityEngine.UI;
public class ImgTest : MonoBehaviour {
public RawImage img;
public Material ml;
void Start () {
img = GetComponent<RawImage>();
img.texture = Resources.Load<Texture2D>("UI/background");
img.color = Color.red;
img.material = ml;
img.raycastTarget = true;
img.uvRect = new Rect(new Vector2(0, 0), new Vector2(1,1));
}
}
-
SpriteEditor (精靈)的切割和導(dǎo)出
1.無論是什么格式的圖片(最好直接使用PS直接導(dǎo)出的PSD格式),Unity都會(huì)自己搞一套格式,并且打包的時(shí)候也不會(huì)用你文件夾下圖片的格式,而是Unity自己的格式。
2.都可以在導(dǎo)入時(shí)設(shè)置,圖片在發(fā)生拉伸變化時(shí)使用那種濾波模式,point ,Biliner,Trilinear,得到依次濾波效果提升的圖片,point 使用最鄰近濾波,采樣像素通常只有一個(gè),
圖像放大縮小后會(huì)有像素風(fēng)格,在制作棋盤時(shí),不希望有模糊效果選擇這這種模式更好。Biliner使用線性濾波,找相鄰四個(gè)像素差值,放大縮小后會(huì)有模糊效果,
會(huì)被模糊,Trilinear,幾乎和Biliner是一樣的,只是Triliner在多級(jí)紋理漸變中進(jìn)行了混合,如果一個(gè)紋理沒有使用該技術(shù)(Creat MitMap)幾乎是一樣效果。
Splite 可以直接選CreatMipMap,Texture需要把圖片設(shè)置為Advance后選擇是否使用多級(jí)紋理漸變技術(shù)(unity會(huì)根據(jù)相機(jī)距離對(duì)象距離,生成8個(gè)Mip,
該做法在3D場景UI是很好的做法,如果UI都在平面就暴露出了它的弊端,因?yàn)槎荚谄矫妫圆粫?huì)有距離相機(jī)距離的變化,勾選就行,不然會(huì)增加內(nèi)存,切記。)
3.Texture 在導(dǎo)入設(shè)置是Warp Mode 設(shè)置可以紋理在渲染超過紋理坐標(biāo)時(shí),Climp只選擇重復(fù)紋理邊緣像素,還是repeat模式重復(fù)整個(gè)紋理的模式
4.MaxSize 該紋理的最大尺寸,如原圖尺寸為1024*568,該項(xiàng)設(shè)置成4096,unity也只會(huì)使用它的原尺寸大小,改值的大小大于等于圖片原尺寸,如果小于該紋理質(zhì)量會(huì)有損失
5.Format 格式設(shè)置
Compressed 壓縮格式,如果紋理沒有透明通道,一般使用該項(xiàng),優(yōu)化內(nèi)存量,如果有透明通道,顯示原圖片有可能出現(xiàn)問題。4位
16bit 低質(zhì)量真彩格式。16位
TrueColor 真彩模式。質(zhì)量最高,是壓縮格式的8倍,但也更消耗內(nèi)存,32位
Crunched 這種類型將會(huì)根據(jù)顯卡的GPU來選擇合適的壓縮格式進(jìn)行壓縮然后會(huì)選用一種CPU上就能處理的壓縮格式再壓縮一遍。
如果在制作供人下載的資源包的時(shí)候這種類型非常的合適。這個(gè)類型的壓縮需要很長時(shí)間,但在運(yùn)行時(shí)解壓是非??斓?。
6.使用Advance 進(jìn)一步設(shè)置Sprite 或者Texture
你的貼圖無論如何都必須是2的冪次方。因?yàn)橹挥?的冪次方圖片 并且沒有透明通道才會(huì)被壓縮,
IOS會(huì)壓縮成pvr格 式,Android會(huì)壓縮成ETC格式,壓縮以后圖片會(huì)小很多的,好幾倍的小
如果原圖不是2的冪次方,可以在advance設(shè)置Non Power of 2值,
ToNearest :轉(zhuǎn)換成距離該圖片最近的2的冪次方值。
ToLarger : 轉(zhuǎn)換成比該圖片大的2的冪次方值。
ToSmaller : 轉(zhuǎn)換成比該圖片小的2的冪次方值。
美工做了一張100100的邊框圖給你,這張圖有時(shí)以100100顯示,有時(shí)以200100顯示,有時(shí)3000100顯示,放大會(huì)失真,如何進(jìn)行?
看那個(gè)綠框,把邊界留出來
切割圖集:
- Text
1、Font:字體
2、Font Style:
(1)Normal:正常
(2)Bold:粗體
(3)Italic:斜體
(4)Bold And Italic:粗體+斜體
3、Font Size:字體大小
4、Line Spacing:行間距(注:Text組件沒有提供修改字間距的屬性,在前面寫過修改字間距的腳本)
5、Rich Text:富文本
1、Alignment:
前面三個(gè)按鈕是水平方向(分別為左對(duì)齊、居中、右對(duì)齊),后面三個(gè)按鈕是垂直方向(分別為頂對(duì)齊,居中,底對(duì)齊)
2、Align By Geometry:
官方解釋:
Use the extents of glyph geometry to perform horizontal alignment rather than glyph metrics.
This can result in better fitting left and right alignment, but may result in incorrect positioning when attempting to overlay multiple fonts (such as a specialized outline font) on top of each other.
使用區(qū)段的字形幾何執(zhí)行水平對(duì)齊,而不是字形指標(biāo)。
這可以導(dǎo)致更好的擬合左和右對(duì)齊,但可能會(huì)導(dǎo)致不正確的定位當(dāng)試圖覆蓋多個(gè)字體(如專業(yè)輪廓字體)上。
3、Horizontal Overflow:水平溢出
(1)Wrap:文本將自動(dòng)換行,當(dāng)達(dá)到水平邊界
(2)Overflow:文本可以超出水平邊界,繼續(xù)顯示
4、Vertical Overflow:垂直溢出
(1)Truncate:文本不顯示超出垂直邊界的部分
(2)Overflow:文本可以超出垂直邊界,繼續(xù)顯示
5、Best Fit:勾選之后,編輯器發(fā)生變化,顯示Min Size和Max Size
(1)Min Size:最小大小
(2)Max Size:最大大小
當(dāng)邊框很大時(shí),文字最大顯示Max Size字體大??;當(dāng)邊框很小時(shí),文字最小顯示Min Size字體大小,邊框顯示不了MinSize字體大小就不再顯示文字了。
Color:顏色
Material:材質(zhì)
Raycast Target:來自類Graphic,當(dāng)該項(xiàng)為false時(shí),消息會(huì)透傳

你好,我是一<color = “red”>雷潮</color>asdjkl
修改顏色,發(fā)現(xiàn)雷潮并沒有改變顏色。這里面是HTML語法控制
- InputField
using UnityEngine;
using UnityEngine.UI;
public class TestInputFiled : MonoBehaviour
{
public InputField filed;
void Start()
{
// InputField 有兩個(gè)空間,一個(gè)是提示文本控件Placeholder,一個(gè)是輸入文本控件Text
filed.placeholder.GetComponent<Text>().text = "請(qǐng)輸入賬號(hào)";
// 修改輸入內(nèi)容框的內(nèi)容
filed.text = "999";
// 設(shè)置內(nèi)容類型格式:密碼
filed.contentType = InputField.ContentType.Password;
// 設(shè)置輸入類型格式:密碼
filed.inputType = InputField.InputType.Password;
// 超過邊界則換行
filed.lineType = InputField.LineType.MultiLineSubmit;
// 設(shè)置字?jǐn)?shù)限制,0表示不限制
filed.characterLimit = 0;
// 光標(biāo)閃爍速度
filed.caretBlinkRate = 1.0f;
// 在手機(jī)端隱藏輸入
filed.shouldHideMobileInput = false;
#region 事件監(jiān)聽
// 添加輸入框的監(jiān)聽事件
filed.onValueChanged.AddListener(OnValueChange);
filed.onEndEdit.AddListener(OnValueEdit);
#endregion
}
// 當(dāng)值發(fā)生改變輸出
void OnValueChange(string str)
{
Debug.Log(str);
}
// 當(dāng)輸入完成后回車后,輸出結(jié)果
void OnValueEdit(string str)
{
Debug.Log("完成編輯后:"+ str);
}
- Button
Interactable:勾選,按鈕可用,取消勾選,按鈕不可用。
Transition:按鈕在狀態(tài)改變時(shí)自身的過渡方式:
Color Tint(顏色改變) Sprite Swap(圖片切換) Animation(執(zhí)行動(dòng)畫)
Normal Color(默認(rèn)顏色):初始狀態(tài)的顏色。
Highlighted Color(高亮顏色):選中狀態(tài)或是鼠標(biāo)靠近會(huì)進(jìn)入高亮狀態(tài)。
Pressed Color(按下顏色):鼠標(biāo)點(diǎn)擊或是按鈕處于選中狀態(tài)時(shí)按下enter鍵。
Disabled Color(禁用顏色):禁用時(shí)顏色。
Color Multiplier(顏色切換系數(shù)):顏色切換速度,越大則顏色在幾種狀態(tài)間變化速度越快。
Fade Duration(衰落延時(shí)):顏色變化的延時(shí)時(shí)間,越大則變化越不明顯。
當(dāng)選擇Sprite Swap,出現(xiàn)的信息我們可這樣設(shè)置
Highlighted Sprite(高亮圖片):選中狀態(tài)或是鼠標(biāo)靠近會(huì)進(jìn)入高亮狀態(tài)。
Pressed Sprite(按下圖片):鼠標(biāo)點(diǎn)擊或是按鈕處于選中狀態(tài)時(shí)按下enter鍵。
Disabled Sprite(禁用圖片):禁用時(shí)圖片。
最下面還有個(gè)Navigation是個(gè)導(dǎo)航鍵,實(shí)現(xiàn)兩個(gè)鍵之間的連接,可在上面條件腳本實(shí)現(xiàn)事件
選擇Animation,選中uto Generate Animatic會(huì)有提示我們保存文件我們保存好就行
關(guān)于按鈕的事件統(tǒng)一管理方法
private Button[] btns;
void Start()
{
btns = FindObjectsOfType<Button>();
for (int i = 0; i < btns.Length; i++)
{
Button btn = btns[i];
// 使用Lambda表達(dá)式添加偵聽方法
btn.onClick.AddListener(()=>BtnClick(btn));
}
}
/* 這里通過Button的名字進(jìn)行操作*/
public void BtnClick(Button btn)
{
switch (btn.name)
{
case "Start":
Debug.Log("Start");
StartGame();
break;
case "Stop":
Debug.Log("Stop");
StopGame();
break;
case "Quit":
Debug.Log("Quit");
QuitGame();
break;
}
}
public void StartGame()
{
Debug.Log("Start");
// 開始游戲的一些邏輯
}
public void StopGame()
{
Debug.Log("Stop");
// 停止游戲的一些邏輯
}
public void QuitGame()
{
Debug.Log("Quit");
// 退出游戲的一些邏輯
}

- Slider
是一個(gè)主要用于形象的拖動(dòng)以改變目標(biāo)值的控件,他的最恰當(dāng)應(yīng)用是用來改變一個(gè)數(shù)值,最大值和最小值自定義,拖動(dòng)滑塊可在此之間改變,例如改變聲音大小。
Fill Rect(填充矩形):滑塊與最小值方向所構(gòu)成的填充區(qū)域所要使用的填充矩形,如果滑動(dòng)條的作用只是用于改變指定值,
那么此選項(xiàng)建議置空,這個(gè)相比于Scrollbar所多出來的屬性主要用于標(biāo)識(shí)從最小值變化到當(dāng)前值所經(jīng)過的變化區(qū)域,
如果用做進(jìn)度條(顯示任務(wù)進(jìn)行進(jìn)度)的話,這個(gè)屬性是比Scrollbar多出來的一個(gè)優(yōu)勢。
Handle Rect(操作條矩形):當(dāng)前值處于最小值與最大值之間比例的顯示范圍,也就是整個(gè)滑條的最大可控制范圍。
Direction(方向):滑動(dòng)條的方向,從左至右,從上至下還是其他的。
Min Value(最小值):滑動(dòng)條的可變化最小值。
Max Value(最大值):滑動(dòng)條的可變化最大值。
Whole Numbers(變化值為整型):勾選此項(xiàng),拖動(dòng)滑動(dòng)條將按整型數(shù)(最小為1)進(jìn)行改變指定值。
Value(值):當(dāng)前滑動(dòng)條對(duì)應(yīng)的值。
On Value Changed:值改變時(shí)觸發(fā)消息。
【注】:在On Value Change 事件被調(diào)用的時(shí)候
每當(dāng)滑塊的數(shù)值由于拖動(dòng)被改變時(shí)調(diào)用,float類型的值會(huì)被傳遞無論WholeNumber屬性是否啟用。
public Slider sl;
public GameObject cube;
public float speed;
private void Start()
{
sl = GetComponent<Slider>();
// 一開始賦值是確保物體按照設(shè)定值進(jìn)行,可以將值保存起來
speed = sl.value;
}
private void Update()
{
cube.transform.Rotate(Vector3.up * Time.deltaTime * speed);
}
// 偵聽我的Value值的改變
public void MyValueChange(float value)
{
speed = value;
}
}
- Toggle
public class MyToggle : MonoBehaviour {
public Toggle tg;
public GameObject panel;
void Start () {
tg = GetComponent<Toggle>();
// Toggle事件監(jiān)聽
//tg.onValueChanged.AddListener(MyIsOn);
// 一開始一定要判斷。不然會(huì)導(dǎo)致勾選了但是一開始沒有效果。
if (tg.isOn == true)
{
MyIsOn1(true);
MyIsOn2(true);
}
}
public void MyIsOn1(bool b)
{
Debug.Log(b + "1---");
// 修改Panel
panel.GetComponent<Image>().color = Color.red;
}
public void MyIsOn2(bool b)
{
Debug.Log(b + "2---");
// 修改Panel
panel.GetComponent<Image>().color = Color.green;
}
}
- Dropdown
Lable和Arrow是用來顯示初始化的文字和勾選項(xiàng)的,Lable會(huì)根據(jù)首選項(xiàng)的內(nèi)容自動(dòng)更改
Caption Text和Caption Image是作為下拉列表首選項(xiàng)的文字和圖片顯示,也是我們每次選擇后的內(nèi)容,因此可代碼調(diào)用獲取
Item Text作為下拉列表中每個(gè)item的文字顯示,
Item Image可以用來擴(kuò)展模板增加內(nèi)容Value值會(huì)隨著下拉列表選項(xiàng)的不同而變化,參考代碼部分
Options選項(xiàng)欄內(nèi):通過代碼可賦值給相應(yīng)的Item對(duì)象 Dropdown.OptionData
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DropScripts : MonoBehaviour {
public Dropdown dw;
private List<string> ListStr;
private List<Sprite> sprite_list;
public string[] showText;
public Sprite[] sprite;
void Start () {
dw = GetComponent<Dropdown>();
ListStr = new List<string>();
sprite_list = new List<Sprite>();
//ListStr.Add("1");
//ListStr.Add("2");
//ListStr.Add("3");
// 清除選項(xiàng)內(nèi)容
// dw.ClearOptions();
// dw.options.Clear();
// 添加選項(xiàng)內(nèi)容
// dw.AddOptions(ListStr);
// 添加List列表
AddNames();
// 賦值
DropValue();
// 檢測值改變
DropValueChange(dw.value); // 因?yàn)橐婚_始默認(rèn)調(diào)用了第一個(gè)值
dw.onValueChanged.AddListener(DropValueChange);
}
public void DropValueChange(int index)
{
Debug.Log(index);
if (index == 0)
{
Debug.Log("模式1調(diào)用了");
}
if (index == 1)
{
Debug.Log("模式2調(diào)用了");
}
if (index == 2)
{
Debug.Log("模式3調(diào)用了");
}
}
// 給內(nèi)部option賦值
public void DropValue()
{
// 清除選項(xiàng)內(nèi)容
dw.options.Clear();
// 申明一個(gè)DropData
Dropdown.OptionData temoData;
for (int i = 0; i < showText.Length; i++)
{
//給每一個(gè)option選項(xiàng)賦值
temoData = new Dropdown.OptionData();
temoData.text = showText[i];
temoData.image = sprite_list[i];
dw.options.Add(temoData);
}
// 默認(rèn)選擇第一個(gè)
dw.captionText.text = showText[0];
}
// 將數(shù)組內(nèi)的元素添加到List列表中
void AddNames()
{
for (int i = 0; i < showText.Length; i++)
{
ListStr.Add(showText[i]);
}
for (int i = 0; i < sprite.Length; i++)
{
sprite_list.Add(sprite[i]);
}
}
}
- Scrollbar
Handle Rect(操作條矩形):當(dāng)前值處于最小值與最大值之間比例的顯示范圍,也就是整個(gè)滑條的最大可控制范圍。
Direction(方向):滾動(dòng)條的方向,從左至右,從上至下還是其他的。
Value(值):當(dāng)前滾動(dòng)條對(duì)應(yīng)的值。
Size(操作條矩形長度):操作條矩形對(duì)應(yīng)的縮放長度。
//(指定可滾動(dòng)的位置數(shù)量)
Numbers Of Steps:滾動(dòng)條可滾動(dòng)的位置數(shù)目,為0和1時(shí)不生效(事實(shí)上只有0個(gè)可滾動(dòng)位置或1個(gè)可滾動(dòng)位置那還叫滾動(dòng)條嗎),
例如設(shè)為2,則拖動(dòng)滾動(dòng)條時(shí)滾動(dòng)條只會(huì)處在最小值的位置和最大值的位置,因?yàn)樗目蓾L動(dòng)位置只有2個(gè),
例如設(shè)為3,則拖動(dòng)滾動(dòng)條時(shí)滾動(dòng)條只會(huì)處在最小值的位置、最大值的位置以及中間位置,因?yàn)樗目蓾L動(dòng)位置只有3個(gè)。
On Value Changed:值改變時(shí)觸發(fā)消息。
- ScrollRect
屬性:
Content —— 滑動(dòng)的內(nèi)容 ( 所有需要滑動(dòng)展示的內(nèi)容 )
Horizontal —— 是否支持左右滑動(dòng)
Vertical —— 是否支持上下滑動(dòng)
MovementType —— 滑動(dòng)類型 ( Unrestricted 不受滑動(dòng)內(nèi)容邊界限制 Elastic 帶邊界回彈的(Elasticity 彈力) clamped 邊界夾緊 )
Inertia —— 是否支持滑動(dòng)慣性( Deceleration Rate 減速率 ,我感覺就是慣性的大小)
scroll sensitivity —— 滾動(dòng)的靈敏度
Viewport —— 視口 ( 一般是Content 的父物體,帶Mask遮罩后的展示區(qū)域)
Horizontar Scrollbar —— 左右的滾動(dòng)條( 連接的滾動(dòng)條必須放在Scroll View下 )
Visibility —— 滾動(dòng)條可見性 ( Permanent 不變的( 只有選擇這個(gè)關(guān)聯(lián)的Scrollbar才能隱藏 ) auto hide自動(dòng)隱藏(如果內(nèi)容不需要滾動(dòng)就可以看到隱藏滾動(dòng)條) Auto Hide and Expand Viewport 自動(dòng)隱藏并擴(kuò)展視圖 ( Spacing 滑動(dòng)區(qū)域和滾動(dòng)條的間距) )

- 引入事件函數(shù)
using UnityEngine.UI;
using UnityEngine;
using UnityEngine.EventSystems;
public class TestOne : MonoBehaviour , IBeginDragHandler,IEndDragHandler, IDragHandler,IDropHandler
{
public ScrollRect sr;
public Text t;
public Scrollbar sb;
void Start () {
sr = GetComponent<ScrollRect>();
t = GetComponentInChildren<Text>();
sr.content = t.rectTransform;
sr.horizontal = false;
sr.vertical = true;
sr.verticalScrollbar = sb;
sr.onValueChanged.AddListener(OnValueChange);
}
public void OnValueChange(Vector2 value)
{
Debug.Log(value);
if (value.y > 0.4)
{
Debug.Log("第一頁");
}
}
// 剛開始拖拽的時(shí)候
public void OnBeginDrag(PointerEventData eventData)
{
Debug.Log("開始拖拽");
// 假設(shè):一個(gè)頁面有太多的數(shù)據(jù),這個(gè)時(shí)候最好通過提前預(yù)加載進(jìn)行展示數(shù)據(jù)
// 加載第二頁的數(shù)據(jù)
// 加載其他內(nèi)容
}
public void OnDrag(PointerEventData eventData)
{
// 當(dāng)拖拽的時(shí)候
Debug.Log("正在拖拽");
}
public void OnDrop(PointerEventData eventData)
{
// 當(dāng)我們不拖拽的時(shí)候,調(diào)用在OnEndDrag之前
}
// 當(dāng)結(jié)束拖拽的時(shí)候
public void OnEndDrag(PointerEventData eventData)
{
Debug.Log("結(jié)束拖拽" + eventData.pressPosition);
// 制作結(jié)束拖拽后的邏輯,可以體視用戶沒有內(nèi)容了
}
小練習(xí):寫個(gè)小框架滑動(dòng)菜單
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class TestThree : MonoBehaviour,IBeginDragHandler, IEndDragHandler
{
private float[] pageArray = new float[] {0,0.5f,1 };
private float targetPosition = 0;
private bool isDrag = false;
public ScrollRect sr;
public Toggle[] tgArray;
public float smooth = 5f;
void Start () {
if (isDrag == false)
{
sr.horizontalNormalizedPosition = Mathf.Lerp(sr.horizontalNormalizedPosition, targetPosition, Time.deltaTime * smooth);
}
}
// Update is called once per frame
void Update () {
}
public void MovePange1(bool isOn)
{
if (isOn == true)
{
targetPosition = pageArray[0];
}
}
public void MovePange2(bool isOn)
{
if (isOn == true)
{
targetPosition = pageArray[2];
}
}
public void MovePange3(bool isOn)
{
if (isOn == true)
{
targetPosition = pageArray[3];
}
}
public void OnBeginDrag(PointerEventData eventData)
{
isDrag = true;
}
public void OnEndDrag(PointerEventData eventData)
{
isDrag = false;
float posX = sr.horizontalNormalizedPosition;
int index = 0;
float offset = Mathf.Abs(pageArray[index] - posX);
for (int i = 0; i < pageArray.Length; i++)
{
float offsetTmp = Mathf.Abs(pageArray[i]-posX);
if (offsetTmp < offset)
{
index = i;
offset = offsetTmp;
}
}
targetPosition = pageArray[index];
tgArray[index].isOn = true;
print(sr.horizontalNormalizedPosition);
}
}
- Scroll View
就是由ScrollRect和ScrollBar等控件組成的,滿足開發(fā)者需求的集合體控件
ScollView 控件下由三個(gè)組成部分,
Viewport 視圖,
Scrollbar Horizontal ,水平滾動(dòng)條,
Scrollbar Vertical ,垂直滾動(dòng)條。
ScrollView的Content不能根據(jù)實(shí)際Content下的游戲物體的多少自動(dòng)改變Content的寬高問題
在實(shí)際使用UGUI開發(fā)的過程中發(fā)現(xiàn)一個(gè)UGUI的BUG:當(dāng)Content下的子物體增加時(shí),ScrollBar下的Handle滑條大小沒有實(shí)時(shí)根據(jù)發(fā)生Content下的子物體數(shù)量發(fā)生變化。(在Hierarchy面板中右鍵創(chuàng)建UI->ScrollView,在子物體中找到Content,需要按行列布置的游戲物體都作為Content的子物體掛在Content下)(以開發(fā)垂直的ScrollView為例)在查找問題的過程中發(fā)現(xiàn):我的這個(gè)項(xiàng)目里Content的高小于遮罩層Viewport的的高,致使ScrollBar滑條的size一直為1的狀態(tài)。調(diào)整Content的高使高大于遮罩層Viewport的的高后又發(fā)現(xiàn)如下問題:在編輯模式下ScrollBar滑條的size只根據(jù)Content與遮罩層Viewport的大小比例進(jìn)行了調(diào)整,而不是根據(jù)Content的子物體數(shù)量進(jìn)行變換,致使了在Content下添加的子物體的總高大于Content設(shè)置的高時(shí)下拉滑條并不能全部顯示的問題,并且在游戲運(yùn)行時(shí)ScrollBar的Size又重新變回1了,無論怎么調(diào)整參數(shù)都無濟(jì)于事。于是自己寫了一個(gè)腳本,根據(jù)Content下的子物體的個(gè)數(shù)來控制Content的寬高(原理是修改RectTransform的sizedelta)
/*
* 說明:掛在UGUI中ScrollView中的Content游戲物體下(在Hierarchy面板中右鍵創(chuàng)建UI->ScrollView,在子物體中找到Content) *
* 功能:解決ScrollView中Content不能根據(jù)實(shí)際Content下的游戲物體的多少自動(dòng)改變Content的寬高問題
* 以至于在Content動(dòng)態(tài)添加需要排序的游戲物體時(shí)ScrollBar滑條變更不正確的問題
* (Content Size Fitter組件是用于文本組件時(shí)自動(dòng)根據(jù)文本變更大小的組件,這里不適用)
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ScrollViewContentTool : MonoBehaviour {
/// <summary>
/// 根據(jù)ScrollBar的類型自動(dòng)調(diào)整Content的寬或高
/// </summary>
public enum ScrollBarType {
Vertical, //為垂直狀態(tài)時(shí)需設(shè)置RectTransform的Anchors為Min(0,1),Max(1,1)
Horizontal, //為水平向右延伸狀態(tài)時(shí)需設(shè)置RectTransform的Anchors為Min(0,0),Max(0,1) HorizontalAndVertical
}
public ScrollBarType m_barType;
/// <summary>
/// 該Content表示實(shí)際寬高(這里寬高大小應(yīng)該為Viewport遮罩層的大小)
/// </summary>
public float m_ContentWidth = 0;
public float m_ContentHeight = 0;
/// <summary>
/// Content下排列的游戲物體X軸和Y軸的間距
/// </summary>
public Vector2 m_Spacing = Vector2.zero;
private RectTransform m_rectTransform = null;
private int m_tempChildCount = 0;
private Vector2 m_ChildSize = Vector2.zero;
//存儲(chǔ)Content子物體的寬高
// Use this for initialization
private void Awake () {
m_rectTransform = this.GetComponent<RectTransform>();
m_tempChildCount = this.transform.childCount;
if (m_tempChildCount > 0)
m_ChildSize = this.transform.GetChild(0).GetComponent<RectTransform>().sizeDelta;
if (m_barType == ScrollBarType.Horizontal)
{
if (m_ContentWidth == 0) Debug.LogError("請(qǐng)?jiān)O(shè)置Content的Width!!");
m_rectTransform.anchorMin = new Vector2(0, 0);
m_rectTransform.anchorMax = new Vector2(0, 1);
m_rectTransform.sizeDelta = new Vector2(m_ContentWidth, 0);
} else if (m_barType == ScrollBarType.Vertical) {
if (m_ContentHeight == 0) Debug.LogError("請(qǐng)?jiān)O(shè)置Content的Height!!");
m_rectTransform.anchorMin = new Vector2(0, 1);
m_rectTransform.anchorMax = new Vector2(1, 1);
m_rectTransform.sizeDelta = new Vector2(0, m_ContentHeight);
} else if (m_barType == ScrollBarType.HorizontalAndVertical)
{
if (m_ContentHeight == 0 || m_ContentWidth == 0) Debug.LogError("請(qǐng)?jiān)O(shè)置Content的Width和Height!!");
m_rectTransform.anchorMin = new Vector2(0, 0);
m_rectTransform.anchorMax = new Vector2(1, 1);
m_rectTransform.sizeDelta = new Vector2(0, 0);
}
//Debug.Log(this.transform.GetChild(0).GetComponent<RectTransform>().sizeDelta);
}
private void Update () {
if (m_tempChildCount != this.transform.childCount)
{
m_tempChildCount = this.transform.childCount;
UpdateContentSize(m_tempChildCount);
}
}
/// <summary>
/// 根據(jù)Content下子物體數(shù)量的變化更新Content的寬高
/// </summary>
private void UpdateContentSize(int _count) {
if (m_barType == ScrollBarType.Horizontal)
{
if (_count * m_ChildSize.x > m_ContentWidth)
{
m_rectTransform.sizeDelta = new Vector2(_count * (m_ChildSize.x + m_Spacing.x), 0);
}
}
else if (m_barType == ScrollBarType.Vertical)
{
if (_count * m_ChildSize.y > m_ContentHeight)
{
m_rectTransform.sizeDelta = new Vector2(0, _count * (m_ChildSize.y + m_Spacing.y));
}
}
//此時(shí)的m_rectTransform.sizeDelta代表往右和往下的增量,為0時(shí)代表Content的初始大小
else if (m_barType == ScrollBarType.HorizontalAndVertical)
{
if (_count * m_ChildSize.x > m_ContentWidth)
{
float width = Mathf.Abs(m_ContentWidth - _count * (m_ChildSize.x + m_Spacing.x));
m_rectTransform.sizeDelta = new Vector2(width, 0);
}
if (_count * m_ChildSize.y > m_ContentHeight)
{
float height = Mathf.Abs(m_ContentHeight - _count * (m_ChildSize.y + m_Spacing.y));
m_rectTransform.sizeDelta = new Vector2(0, -height);
}
}
}
}
- ScrollView無限滾動(dòng)
scrollview理論上是支持無限多個(gè)item單元(即滾動(dòng)的單元條目),但實(shí)際應(yīng)用中,我們?cè)谝婚_始實(shí)例化幾個(gè)或者十幾個(gè)item對(duì)象時(shí)一般是沒問題,但是當(dāng)item非常多時(shí),幾百或者上千時(shí),完全實(shí)例化比較耗時(shí)消耗性能大,也有可能帶來占用手機(jī)內(nèi)存比較高,甚至?xí)寖?nèi)存溢出。
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
[RequireComponent(typeof(GridLayoutGroup))]
[RequireComponent(typeof(ContentSizeFitter))]
public class InfinityGridLayoutGroup : MonoBehaviour
{
[SerializeField]
int minAmount = 0;//實(shí)現(xiàn)無限滾動(dòng),需要的最少的child數(shù)量。屏幕上能看到的+一行看不到的,比如我在屏幕上能看到 2 行,每一行 2 個(gè)。則這個(gè)值為 2行*2個(gè) + 1 行* 2個(gè) = 6個(gè)。
RectTransform rectTransform;
GridLayoutGroup gridLayoutGroup;
ContentSizeFitter contentSizeFitter;
ScrollRect scrollRect;
List<RectTransform> children=new List<RectTransform>();
Vector2 startPosition;
int amount = 0;
public delegate void UpdateChildrenCallbackDelegate(int index, Transform trans);
public UpdateChildrenCallbackDelegate updateChildrenCallback = null;
int realIndex = -1;
int realIndexUp = -1; //從下往上;
bool hasInit = false;
Vector2 gridLayoutSize;
Vector2 gridLayoutPos;
Dictionary<Transform, Vector2> childsAnchoredPosition = new Dictionary<Transform, Vector2>();
Dictionary<Transform, int> childsSiblingIndex = new Dictionary<Transform, int>();
// Use this for initialization
void Start ()
{
//StartCoroutine(InitChildren());
}
IEnumerator InitChildren()
{
yield return 0;
if (!hasInit)
{
//獲取Grid的寬度;
rectTransform = GetComponent<RectTransform>();
gridLayoutGroup = GetComponent<GridLayoutGroup>();
gridLayoutGroup.enabled = false;
contentSizeFitter = GetComponent<ContentSizeFitter>();
contentSizeFitter.enabled = false;
gridLayoutPos = rectTransform.anchoredPosition;
gridLayoutSize = rectTransform.sizeDelta;
//注冊(cè)ScrollRect滾動(dòng)回調(diào);
scrollRect = transform.parent.GetComponent<ScrollRect>();
scrollRect.onValueChanged.AddListener((data) => { ScrollCallback(data); });
//獲取所有child anchoredPosition 以及 SiblingIndex;
for (int index = 0; index < transform.childCount; index++)
{
Transform child=transform.GetChild(index);
RectTransform childRectTrans= child.GetComponent<RectTransform>();
childsAnchoredPosition.Add(child, childRectTrans.anchoredPosition);
childsSiblingIndex.Add(child, child.GetSiblingIndex());
}
}
else
{
rectTransform.anchoredPosition = gridLayoutPos;
rectTransform.sizeDelta = gridLayoutSize;
children.Clear();
realIndex = -1;
realIndexUp = -1;
//children重新設(shè)置上下順序;
foreach (var info in childsSiblingIndex)
{
info.Key.SetSiblingIndex(info.Value);
}
//children重新設(shè)置anchoredPosition;
for (int index = 0; index < transform.childCount; index++)
{
Transform child = transform.GetChild(index);
RectTransform childRectTrans = child.GetComponent<RectTransform>();
if (childsAnchoredPosition.ContainsKey(child))
{
childRectTrans.anchoredPosition = childsAnchoredPosition[child];
}
else
{
Debug.LogError("childsAnchoredPosition no contain "+child.name);
}
}
}
//獲取所有child;
for (int index = 0; index < transform.childCount; index++)
{
Transform trans = transform.GetChild(index);
trans.gameObject.SetActive(true);
children.Add(transform.GetChild(index).GetComponent<RectTransform>());
//初始化前面幾個(gè);
UpdateChildrenCallback(children.Count - 1, transform.GetChild(index));
}
startPosition = rectTransform.anchoredPosition;
realIndex = children.Count - 1;
//Debug.Log( scrollRect.transform.TransformPoint(Vector3.zero));
// Debug.Log(transform.TransformPoint(children[0].localPosition));
hasInit = true;
//如果需要顯示的個(gè)數(shù)小于設(shè)定的個(gè)數(shù);
for (int index = 0; index < minAmount; index++)
{
children[index].gameObject.SetActive(index < amount);
}
if (gridLayoutGroup.constraint == GridLayoutGroup.Constraint.FixedColumnCount)
{
//如果小了一行,則需要把GridLayout的高度減去一行的高度;
int row = (minAmount - amount) / gridLayoutGroup.constraintCount;
if (row > 0)
{
rectTransform.sizeDelta -= new Vector2(0, (gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y) * row);
}
}
else
{
//如果小了一列,則需要把GridLayout的寬度減去一列的寬度;
int column = (minAmount - amount) / gridLayoutGroup.constraintCount;
if (column > 0)
{
rectTransform.sizeDelta -= new Vector2((gridLayoutGroup.cellSize.x + gridLayoutGroup.spacing.x) * column, 0);
}
}
}
// Update is called once per frame
void Update ()
{
}
void ScrollCallback(Vector2 data)
{
UpdateChildren();
}
void UpdateChildren()
{
if (transform.childCount < minAmount)
{
return;
}
Vector2 currentPos = rectTransform.anchoredPosition;
if (gridLayoutGroup.constraint == GridLayoutGroup.Constraint.FixedColumnCount)
{
float offsetY = currentPos.y - startPosition.y;
if (offsetY > 0)
{
//向上拉,向下擴(kuò)展;
{
if (realIndex >= amount - 1)
{
startPosition = currentPos;
return;
}
float scrollRectUp = scrollRect.transform.TransformPoint(Vector3.zero).y;
Vector3 childBottomLeft = new Vector3(children[0].anchoredPosition.x, children[0].anchoredPosition.y - gridLayoutGroup.cellSize.y, 0f);
float childBottom = transform.TransformPoint(childBottomLeft).y;
if (childBottom >= scrollRectUp)
{
//Debug.Log("childBottom >= scrollRectUp");
//移動(dòng)到底部;
for (int index = 0; index < gridLayoutGroup.constraintCount; index++)
{
children[index].SetAsLastSibling();
children[index].anchoredPosition = new Vector2(children[index].anchoredPosition.x, children[children.Count - 1].anchoredPosition.y - gridLayoutGroup.cellSize.y - gridLayoutGroup.spacing.y);
realIndex++;
if (realIndex > amount - 1)
{
children[index].gameObject.SetActive(false);
}
else
{
UpdateChildrenCallback(realIndex, children[index]);
}
}
//GridLayoutGroup 底部加長;
rectTransform.sizeDelta += new Vector2(0, gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y);
//更新child;
for (int index = 0; index < children.Count; index++)
{
children[index] = transform.GetChild(index).GetComponent<RectTransform>();
}
}
}
}
else
{
//Debug.Log("Drag Down");
//向下拉,下面收縮;
if (realIndex + 1 <= children.Count)
{
startPosition = currentPos;
return;
}
RectTransform scrollRectTransform = scrollRect.GetComponent<RectTransform>();
Vector3 scrollRectAnchorBottom = new Vector3(0, -scrollRectTransform.rect.height - gridLayoutGroup.spacing.y, 0f);
float scrollRectBottom = scrollRect.transform.TransformPoint(scrollRectAnchorBottom).y;
Vector3 childUpLeft = new Vector3(children[children.Count - 1].anchoredPosition.x, children[children.Count - 1].anchoredPosition.y, 0f);
float childUp = transform.TransformPoint(childUpLeft).y;
if (childUp < scrollRectBottom)
{
//Debug.Log("childUp < scrollRectBottom");
//把底部的一行 移動(dòng)到頂部
for (int index = 0; index < gridLayoutGroup.constraintCount; index++)
{
children[children.Count - 1 - index].SetAsFirstSibling();
children[children.Count - 1 - index].anchoredPosition = new Vector2(children[children.Count - 1 - index].anchoredPosition.x, children[0].anchoredPosition.y + gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y);
children[children.Count - 1 - index].gameObject.SetActive(true);
UpdateChildrenCallback(realIndex - children.Count - index, children[children.Count - 1 - index]);
}
realIndex -= gridLayoutGroup.constraintCount;
//GridLayoutGroup 底部縮短;
rectTransform.sizeDelta -= new Vector2(0, gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y);
//更新child;
for (int index = 0; index < children.Count; index++)
{
children[index] = transform.GetChild(index).GetComponent<RectTransform>();
}
}
}
}
else
{
float offsetX = currentPos.x - startPosition.x;
if (offsetX < 0)
{
//向左拉,向右擴(kuò)展;
{
if (realIndex >= amount - 1)
{
startPosition = currentPos;
return;
}
float scrollRectLeft = scrollRect.transform.TransformPoint(Vector3.zero).x;
Vector3 childBottomRight = new Vector3(children[0].anchoredPosition.x+ gridLayoutGroup.cellSize.x, children[0].anchoredPosition.y, 0f);
float childRight = transform.TransformPoint(childBottomRight).x;
// Debug.LogError("childRight=" + childRight);
if (childRight <= scrollRectLeft)
{
//Debug.Log("childRight <= scrollRectLeft");
//移動(dòng)到右邊;
for (int index = 0; index < gridLayoutGroup.constraintCount; index++)
{
children[index].SetAsLastSibling();
children[index].anchoredPosition = new Vector2(children[children.Count - 1].anchoredPosition.x + gridLayoutGroup.cellSize.x + gridLayoutGroup.spacing.x, children[index].anchoredPosition.y);
realIndex++;
if (realIndex > amount - 1)
{
children[index].gameObject.SetActive(false);
}
else
{
UpdateChildrenCallback(realIndex, children[index]);
}
}
//GridLayoutGroup 右側(cè)加長;
rectTransform.sizeDelta += new Vector2(gridLayoutGroup.cellSize.x + gridLayoutGroup.spacing.x,0);
//更新child;
for (int index = 0; index < children.Count; index++)
{
children[index] = transform.GetChild(index).GetComponent<RectTransform>();
}
}
}
}
else
{
//Debug.Log("Drag Down");
//向右拉,右邊收縮;
if (realIndex + 1 <= children.Count)
{
startPosition = currentPos;
return;
}
RectTransform scrollRectTransform = scrollRect.GetComponent<RectTransform>();
Vector3 scrollRectAnchorRight = new Vector3(scrollRectTransform.rect.width + gridLayoutGroup.spacing.x, 0, 0f);
float scrollRectRight = scrollRect.transform.TransformPoint(scrollRectAnchorRight).x;
Vector3 childUpLeft = new Vector3(children[children.Count - 1].anchoredPosition.x, children[children.Count - 1].anchoredPosition.y, 0f);
float childLeft = transform.TransformPoint(childUpLeft).x;
if (childLeft >= scrollRectRight)
{
//Debug.LogError("childLeft > scrollRectRight");
//把右邊的一行 移動(dòng)到左邊;
for (int index = 0; index < gridLayoutGroup.constraintCount; index++)
{
children[children.Count - 1 - index].SetAsFirstSibling();
children[children.Count - 1 - index].anchoredPosition = new Vector2(children[0].anchoredPosition.x - gridLayoutGroup.cellSize.x - gridLayoutGroup.spacing.x,children[children.Count - 1 - index].anchoredPosition.y);
children[children.Count - 1 - index].gameObject.SetActive(true);
UpdateChildrenCallback(realIndex - children.Count - index, children[children.Count - 1 - index]);
}
//GridLayoutGroup 右側(cè)縮短;
rectTransform.sizeDelta -= new Vector2(gridLayoutGroup.cellSize.x + gridLayoutGroup.spacing.x, 0);
//更新child;
for (int index = 0; index < children.Count; index++)
{
children[index] = transform.GetChild(index).GetComponent<RectTransform>();
}
realIndex -= gridLayoutGroup.constraintCount;
}
}
}
startPosition = currentPos;
}
void UpdateChildrenCallback(int index,Transform trans)
{
if (updateChildrenCallback != null)
{
updateChildrenCallback(index, trans);
}
}
/// <summary>
/// 設(shè)置總的個(gè)數(shù);
/// </summary>
/// <param name="count"></param>
public void SetAmount(int count)
{
amount = count;
StartCoroutine(InitChildren());
}
}
MCV方式進(jìn)行ScrollView使用,并對(duì)內(nèi)部數(shù)據(jù)進(jìn)行設(shè)置
Model
public class ScrollVItemDataModel{
public int index;
public string name;
public string imageURL;
// 構(gòu)造方法
public ScrollVItemDataModel(int Index, string Name,string ImageURL)
{
index = Index;
name = Name;
imageURL = ImageURL;
}
}
Control
public class ScrollViewItem : MonoBehaviour {
// 獲取Item里面的控件
private Button ItemBtn;
private Text ItemBtnText;
// 數(shù)據(jù)類
public ScrollViewItemData data;
private void Awake()
{
ItemBtn =this.gameObject.GetComponent<Button>();
ItemBtnText = ItemBtn.GetComponentInChildren<Text>();
}
public void SetData(ScrollViewItemData Data)
{
data = Data;
ItemBtnText.text = Data.name;
}
}
View
// 添加數(shù)據(jù)與Item
List<ScrollViewItem> itemList = new List<ScrollViewItem>();
List<ScrollViewItemData> itemDataList = new List<ScrollViewItemData>();
// 獲取網(wǎng)格布局組,進(jìn)行控件大小排布
GridLayoutGroup grid;
// 獲取rect控件
ScrollRect scrollRect;
// 設(shè)置布局大小
ContentSizeFitter fitter;
// 個(gè)數(shù)
private int count = 20;
void Start()
{
// 20條內(nèi)容
for (int i = 0; i < count; i++)
{
itemDataList.Add(new ScrollViewItemData(i, "第" + i + "個(gè)元素", "https://123.com"));
}
// 獲取網(wǎng)格grid,內(nèi)容尺寸fitter,scrollRect
grid = GetComponent<GridLayoutGroup>();
fitter = GetComponent<ContentSizeFitter>();
scrollRect = GetComponentInParent<ScrollRect>();
//監(jiān)聽ScrollRect的回調(diào)
// scrollRect.onValueChanged.AddListener((data) => { ScrollCallback(data); });
// 獲取ScrollView寬高(像素)
Vector2 viewSize = scrollRect.GetComponent<RectTransform>().sizeDelta;
// Debug.Log(viewSize.y);
// Debug.Log(grid.cellSize.y);
// 生成20的預(yù)制體
for (int i = 0; i < count; i++)
{
if (itemDataList.Count <= i)
break;
GameObject itemR = Resources.Load("Prefabs/Item") as GameObject;
GameObject itemObj = Instantiate(itemR, this.transform) as GameObject;
ScrollViewItem item = itemObj.AddComponent<ScrollViewItem>();
itemList.Add(item);
item.SetData(itemDataList[i]);
}
}
}























