UI布局是这样滴:
具体的关于滑动列表的设置可以参考
这里
,其中Image的Scroll Rect组件的Content赋值为Content,在这里,我们的Content是一个空物体,它的大小就是上图那个方框的大小。这里有两点很重要:
1.Content的Pivot的Y必须设置为Y的最大值,就像这样:
这是为什么呢?其实动态滑动列表的原理主要就是动态改变Content的Height,当中心点处于最顶的位置时,就能保证顶部位置不变,只有下部的位置在变化。假如中心点处于中间位置,那么改变Height,两边都会变化。
2.列表项的设置,要注意列表项预制体的Anchor Presets和Pivot,因为它们都会影响预制体实例化的位置,这里为了方便计算,我设置Anchor Presets为top-center,Pivot为(0.5,1)
最后给出代码:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class TaskPanel : MonoBehaviour {
public static TaskPanel instance;
public List<GameObject> items = new List<GameObject>();
public GameObject content;//内容
public Vector2 contentSize;//内容的原始高度
public GameObject item;//列表项
public float itemHeight;
public Vector3 itemLocalPos;
void Awake()
{
if (!instance)
instance = this;
else
Destroy(this);
}
void Start()
{
content = GameObject.Find("Content");
contentSize = content.GetComponent<RectTransform>().sizeDelta;
item = Resources.Load("Item") as GameObject;
itemHeight = item.GetComponent<RectTransform>().rect.height;
itemLocalPos = item.transform.localPosition;
}
//添加列表项
public void AddItem()
{
GameObject a = Instantiate(item) as GameObject;
a.transform.parent = content.transform;
a.transform.localPosition = new Vector3(itemLocalPos.x, itemLocalPos.y - items.Count * itemHeight, 0);
items.Add(a);
if (contentSize.y <= items.Count * itemHeight)//增加内容的高度
{
content.GetComponent<RectTransform>().sizeDelta = new Vector2(contentSize.x, items.Count * itemHeight);
}
}
//移除列表项
public void RemoveItem(GameObject t)
{
int index = items.IndexOf(t);
items.Remove(t);
Destroy(t);
for (int i = index; i < items.Count; i++)//移除的列表项后的每一项都向前移动
{
items[i].transform.localPosition += new Vector3(0, itemHeight, 0);
}
if (contentSize.y <= items.Count * itemHeight)//调整内容的高度
content.GetComponent<RectTransform>().sizeDelta = new Vector2(contentSize.x, items.Count * itemHeight);
else
content.GetComponent<RectTransform>().sizeDelta = contentSize;
}
}
效果图:
///
后面改进了一下:
设置一下Content的描点、中心点和宽高:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class ScrollPanelVerticalLayout : MonoBehaviour {
private List<Transform> items = new List<Transform>();
private RectTransform contentRectTra;//内容
private VerticalLayoutGroup group;//用于计算内容的高度
private float itemHeight;//子项的高度
void Awake ()
{
contentRectTra = transform.FindChild("Content").GetComponent<RectTransform>();
contentRectTra.sizeDelta = new Vector2(contentRectTra.sizeDelta.x, 0);
group = contentRectTra.GetComponent<VerticalLayoutGroup>();
}
//添加列表项
public void AddItem(Transform t)
{
if (itemHeight == 0f) itemHeight = t.GetComponent<RectTransform>().rect.height;
t.SetParent(contentRectTra.transform);
t.localScale = Vector3.one;
items.Add(t);
contentRectTra.sizeDelta = new Vector2(contentRectTra.sizeDelta.x,
group.padding.top + group.padding.bottom + items.Count * itemHeight + (items.Count - 1) * group.spacing);
}
//移除列表项
public void RemoveItem(Transform t)
{
//Debug.Log(t.gameObject.name);
int index = items.IndexOf(t);
items.Remove(t);
Destroy(t.gameObject);
contentRectTra.sizeDelta = new Vector2(contentRectTra.sizeDelta.x,
group.padding.top + group.padding.bottom + items.Count * itemHeight + (items.Count - 1) * group.spacing);
}
}
使用起来也很方便:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class Test : MonoBehaviour {
public ScrollPanelVerticalLayout scrollPanel;
private int index = 0;
public void Add()
{
GameObject go = Instantiate(Resources.Load("Item")) as GameObject;
go.name = index.ToString();
go.transform.FindChild("Text").GetComponent<Text>().text = index.ToString();
go.transform.FindChild("Button").GetComponent<Button>().onClick.AddListener
(
() =>
{
Remove(go.transform);
}
);
scrollPanel.AddItem(go.transform);
index++;
}
void Remove(Transform t)
{
scrollPanel.RemoveItem(t);
}
}
版权声明:本文为lyh916原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。