U3D 实现UGUI循环列表
在项目开发中,列表滚动是很常用的功能,比如展示玩家排名,聊天信息等。
这里我们实现一个循环列表功能。
首先我们创建个ScrollRect,移除掉Content里面的布局组件。如下
然后在List_View上放上如下代码
LoopListViewer.cs
:
/** Created By Zhaotao On 2019-3-22* Desc:循环列表*/using System;
using System.Collections;
using System.Collections.Generic;
using DigiskyUnity;
using LuaInterface;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SocialPlatforms;
using UnityEngine.UI;public class LoopListViewer : MonoBehaviour
{private enum LayoutDir{NEGATIVE = -1,POSITIVE = 1,}//滚动区域组件[SerializeField] private ScrollRect ScrollView;//Item父对象[SerializeField] private GameObject Content;//list的Item 控件[SerializeField] private GameObject ItemBase;//上下的缓冲[SerializeField] private float BufferDis = 20;//排列器[SerializeField] private LoopItemArranger Arranger;//默认Item的个数[SerializeField] private int DefaultCount = 10;//是否是垂直滚动[SerializeField] private bool IsVertical = true;//滚动方向 1 为正滚动,-1为反方向滚动[SerializeField] private LayoutDir Direction = LayoutDir.POSITIVE;//Item 列表private List _ItemList = new List();private int _TopIndex = -1;private int _EndIndex = -1;//Item的个数private int _TotalCount = 0;//Content 的尺寸private Vector2 _ContentSize = Vector2.zero;//ViewPort的尺寸private Vector2 _ViewPortSize = Vector2.zero;private LoopListUpdateCallBack _ChangeCallBack = null;private Vector2 _LastPos = Vector2.zero;//滚动到的索引private int _ScrollToIndex = 0;//滚动速度private float _ScrollSpeed = 0;private void Awake(){if (Content != null){_ContentSize = Content.GetComponent().sizeDelta;}if (ScrollView != null){_ViewPortSize = ScrollView.GetComponent().sizeDelta;ScrollView.onValueChanged.AddListener(ScrollCallBack);}Arranger.SetIsVertical(IsVertical);Arranger.SetDir((int)Direction);AdjustPovit();}private void Start(){AddCount(DefaultCount);Content.GetComponent().anchoredPosition = Vector2.zero;}private void Update(){if (_ScrollToIndex > 0 && _ScrollSpeed > 0){var head = Arranger.GetHeadItem();var tail = Arranger.GetTailItem();if (_ScrollToIndex < head.GetIndex()){//项下滚动if (IsVertical){SpeedScroll(-_ScrollSpeed * (int)Direction);}else{SpeedScroll(_ScrollSpeed * (int)Direction); }}else if (_ScrollToIndex > tail.GetIndex()){//项上滚动if (IsVertical){SpeedScroll(_ScrollSpeed * (int)Direction);}else{SpeedScroll(-_ScrollSpeed * (int)Direction); }}else{//在可见项之间ILoopItemArrange itemArrange = Arranger.GetItemArrangeByIndex(_ScrollToIndex);if (itemArrange != null){if (IsVertical){float conY = Content.GetComponent().anchoredPosition.y;float iY = itemArrange.GetCurrentItem().GetPosition().y * (int) Direction;float offY = conY * (int) Direction + iY + Arranger.GetSpaceOff();if (Math.Abs(offY) < _ScrollSpeed){SpeedScroll(-offY * (int)Direction); _ScrollToIndex = 0;_ScrollSpeed = 0;ScrollView.enabled = true;}else if(Math.Abs(offY) > _ScrollSpeed){SpeedScroll(-offY/Math.Abs(offY) * _ScrollSpeed * (int)Direction);}else{_ScrollToIndex = 0;_ScrollSpeed = 0;ScrollView.enabled = true;}}else{float conX = Content.GetComponent().anchoredPosition.x;float iX = itemArrange.GetCurrentItem().GetPosition().x * (int) Direction;float offX = conX * (int) Direction + iX - Arranger.GetSpaceOff();if (Math.Abs(offX) < _ScrollSpeed){SpeedScroll(-offX * (int)Direction); _ScrollToIndex = 0;_ScrollSpeed = 0;ScrollView.enabled = true;}else if(Math.Abs(offX) > _ScrollSpeed){SpeedScroll(-offX/Math.Abs(offX) * _ScrollSpeed * (int)Direction); }else{_ScrollToIndex = 0;_ScrollSpeed = 0;ScrollView.enabled = true;}}}else{LogHelper.Warning("dont find "+_ScrollToIndex +" Item");}}}}/// /// 调整锚点方向/// private void AdjustPovit(){var Rt = Content.GetComponent();var Rtb = ItemBase.GetComponent();if (Direction == LayoutDir.POSITIVE && IsVertical){Rt.anchorMin = new Vector2(0,1);Rt.anchorMax = new Vector2(1,1);Rt.pivot = new Vector2(0.5f,1);Rt.anchoredPosition = Vector2.zero;Rtb.pivot = new Vector2(0.5f,1);Rtb.anchoredPosition = Vector2.zero;}else if (Direction == LayoutDir.NEGATIVE && IsVertical){Rt.anchorMin = new Vector2(0,0);Rt.anchorMax = new Vector2(1,0);Rt.pivot = new Vector2(0.5f,0);Rt.anchoredPosition = Vector2.zero;Rtb.pivot = new Vector2(0.5f,0);Rtb.anchoredPosition = Vector2.zero;}else if(Direction == LayoutDir.POSITIVE && !IsVertical){Rt.anchorMin = new Vector2(0,0);Rt.anchorMax = new Vector2(0,1);Rt.pivot = new Vector2(0,0.5f);Rt.anchoredPosition = Vector2.zero;Rtb.pivot = new Vector2(0,0.5f);Rtb.anchoredPosition = Vector2.zero;}else if(Direction == LayoutDir.NEGATIVE && !IsVertical){Rt.anchorMin = new Vector2(1,0);Rt.anchorMax = new Vector2(1,1);Rt.pivot = new Vector2(1,0.5f);Rt.anchoredPosition = Vector2.zero;Rtb.pivot = new Vector2(1,0.5f);Rtb.anchoredPosition = Vector2.zero;}}/// /// 添加Item数据更新回调/// /// 回调函数public void AddItemChangeCallBack(UnityAction e){if (_ChangeCallBack == null){_ChangeCallBack = new LoopListUpdateCallBack();_ChangeCallBack.AddListener(e);}else{_ChangeCallBack.AddListener(e);}}/// /// 关闭消息监听/// public void Close(){if (_ChangeCallBack != null){_ChangeCallBack.RemoveAllListeners();}_ChangeCallBack = null;}/// /// 添加Item的个数/// /// public void AddCount(int i){_TotalCount += i;RefreshItemCount();RefreshContentSize();}/// /// 获取视口区域的高度或者宽度 更加垂直还是水平/// /// private float GetViewPortSize(){if (IsVertical){return _ViewPortSize.y;}return _ViewPortSize.x;}/// /// 刷新需要最少Item个数/// private void RefreshItemCount(){while (_TotalCount > Arranger.GetCount() && Arranger.GetSize() < GetViewPortSize() + BufferDis * 2){LoopListItem item = new LoopListItem(Instantiate(ItemBase, Content.transform));item.SetIndex(Arranger.GetCount() + 1);InvokeUpdate(item, item.GetIndex());Arranger.AddArrangeItem(item, item); }}/// /// 刷新内容容器的大小/// public void RefreshContentSize(){if (IsVertical){Content.GetComponent().sizeDelta = new Vector2(_ContentSize.x, GetContentSize());}else{Content.GetComponent().sizeDelta = new Vector2(GetContentSize(), _ContentSize.y);}}/// /// 获取当前内容容器的大小/// /// 更具垂直于水平对应返回宽度和高度 public float GetContentSize(){if (IsVertical){if (Arranger.GetTailItem() == null){return _ViewPortSize.y;}return Mathf.Abs(Arranger.GetTailItem().GetPosition().y) + Mathf.Abs(Arranger.GetTailItem().GetHeight()) +Arranger.GetBottomOff();}else{if (Arranger.GetTailItem() == null){return _ViewPortSize.x;}return Mathf.Abs(Arranger.GetTailItem().GetPosition().x) + Arranger.GetTailItem().GetWidth() + Arranger.GetRightOff();}}/// /// 滚动发生时的回调函数/// /// public void ScrollCallBack(Vector2 v){if (_LastPos == Vector2.zero){_LastPos = Content.GetComponent().anchoredPosition;}//当在最上面 v是1,当在最下面v是0if (IsVertical){float off = Content.GetComponent().anchoredPosition.y - _LastPos.y;_LastPos = Content.GetComponent().anchoredPosition;if (off * (int)Direction < 0){//在往下滑动//当最后面一个大于可视加缓冲范围,就交换 ILoopItem head = Arranger.GetHeadItem();ILoopItem tail = Arranger.GetTailItem();float conY = Mathf.Abs(Content.GetComponent().anchoredPosition.y);while (Mathf.Abs(tail.GetPosition().y) > conY + _ViewPortSize.y + BufferDis && head.GetIndex() > 1){InvokeUpdate(tail, head.GetIndex() - 1);Arranger.SwapToHead(tail.GetLoopItemArrange());tail.SetIndex(head.GetIndex() - 1);RefreshContentSize();head = Arranger.GetHeadItem();tail = Arranger.GetTailItem();conY = Mathf.Abs(Content.GetComponent().anchoredPosition.y);}if (Mathf.Abs(head.GetPosition().y) + head.GetHeight() > conY - BufferDis && head.GetIndex() > 1){//最上一个小于可视空间,需要创建个新的LoopListItem item = new LoopListItem(Instantiate(ItemBase, Content.transform));item.SetIndex(head.GetIndex() - 1);InvokeUpdate(item, head.GetIndex() - 1);Arranger.AddArrangeItem(item, item);RefreshContentSize();}}else if (off * (int)Direction > 0){//在往上滑动//当最上面一个小雨可视加缓冲范围,就交换ILoopItem head = Arranger.GetHeadItem();ILoopItem tail = Arranger.GetTailItem();float conY = Mathf.Abs(Content.GetComponent().anchoredPosition.y);while (Mathf.Abs(head.GetPosition().y) + head.GetHeight() < conY - BufferDis &&tail.GetIndex() < _TotalCount){InvokeUpdate(head, tail.GetIndex() + 1);Arranger.SwapToTail(head.GetLoopItemArrange());head.SetIndex(tail.GetIndex() + 1);RefreshContentSize();head = Arranger.GetHeadItem();tail = Arranger.GetTailItem();conY = Mathf.Abs(Content.GetComponent().anchoredPosition.y);}if (Mathf.Abs(tail.GetPosition().y) < conY + _ViewPortSize.y + BufferDis &&tail.GetIndex() < _TotalCount){Debug.Log("skak:"+tail.GetIndex()+","+_TotalCount);//最下面一个小于可视空间,需要创建个新的LoopListItem item = new LoopListItem(Instantiate(ItemBase, Content.transform));item.SetIndex(tail.GetIndex() + 1);InvokeUpdate(item, tail.GetIndex() + 1);Arranger.AddArrangeItem(item, item);RefreshContentSize();}}}else{float off = Content.GetComponent().anchoredPosition.x - _LastPos.x;_LastPos = Content.GetComponent().anchoredPosition;if (off * (int)Direction < 0){//往左滑动//当最左边的Item小于可视缓冲范围,就交换ILoopItem head = Arranger.GetHeadItem();ILoopItem tail = Arranger.GetTailItem();float conX = Mathf.Abs(Content.GetComponent().anchoredPosition.x);if (Mathf.Abs(head.GetPosition().x) + head.GetWidth() < Mathf.Abs(conX) - BufferDis &&tail.GetIndex() < _TotalCount){InvokeUpdate(head,tail.GetIndex() + 1);Arranger.SwapToTail(head.GetLoopItemArrange());head.SetIndex(tail.GetIndex() + 1);RefreshContentSize();}else if (Mathf.Abs(tail.GetPosition().x) < Mathf.Abs(conX) + _ViewPortSize.y + BufferDis &&tail.GetIndex() < _TotalCount){//最下面一个小于可视空间,需要创建个新的LoopListItem item = new LoopListItem(Instantiate(ItemBase, Content.transform));item.SetIndex(tail.GetIndex() + 1);InvokeUpdate(item, tail.GetIndex() + 1);Arranger.AddArrangeItem(item, item);RefreshContentSize();}}else if (off * (int)Direction > 0){//在往右滑动//当最后面一个大于可视加缓冲范围,就交换 ILoopItem head = Arranger.GetHeadItem();ILoopItem tail = Arranger.GetTailItem();float conX = Mathf.Abs(Content.GetComponent().anchoredPosition.x);if (Mathf.Abs(tail.GetPosition().x) > Mathf.Abs(conX) + _ViewPortSize.y + BufferDis && head.GetIndex() > 1){InvokeUpdate(tail, head.GetIndex() - 1);Arranger.SwapToHead(tail.GetLoopItemArrange());tail.SetIndex(head.GetIndex() - 1);RefreshContentSize();}else if (Mathf.Abs(head.GetPosition().x) + head.GetWidth() > Mathf.Abs(conX) - BufferDis && head.GetIndex() > 1){//最上一个小于可视空间,需要创建个新的LoopListItem item = new LoopListItem(Instantiate(ItemBase, Content.transform));item.SetIndex(head.GetIndex() - 1);InvokeUpdate(item, head.GetIndex() - 1);Arranger.AddArrangeItem(item, item);RefreshContentSize();}}}}/// /// 调用Lua回调/// /// Item对象/// 当前索引public void InvokeUpdate(ILoopItem item, int index){LoopListItemData data = new LoopListItemData(item, index);if (_ChangeCallBack != null){_ChangeCallBack.Invoke(data);}}/// /// 滚动到索引/// /// public void ScrollToIndex(int i,float speed){if (i > _TotalCount || speed <= 0 || i <= 0){return;}_ScrollToIndex = i;_ScrollSpeed = speed;ScrollView.enabled = false;}/// /// 滚动到底部/// /// 滚动速度public void ScrollToBottom(float speed){ScrollToIndex(_TotalCount, speed);}/// /// 滚动到顶部/// /// 滚动速度public void ScrollToTop(float speed){ScrollToIndex(1, speed);}private void SpeedScroll(float off){if (IsVertical){var Rt = Content.GetComponent();Rt.anchoredPosition = new Vector2(Rt.anchoredPosition.x, Rt.anchoredPosition.y + off);if (off * (int)Direction < 0){//在往下滑动//当最后面一个大于可视加缓冲范围,就交换 ILoopItem head = Arranger.GetHeadItem();ILoopItem tail = Arranger.GetTailItem();float conY = Mathf.Abs(Content.GetComponent().anchoredPosition.y);while (Mathf.Abs(tail.GetPosition().y) > conY + _ViewPortSize.y + BufferDis && head.GetIndex() > 1){InvokeUpdate(tail, head.GetIndex() - 1);Arranger.SwapToHead(tail.GetLoopItemArrange());tail.SetIndex(head.GetIndex() - 1);RefreshContentSize();head = Arranger.GetHeadItem();tail = Arranger.GetTailItem();conY = Mathf.Abs(Content.GetComponent().anchoredPosition.y);}while (Mathf.Abs(head.GetPosition().y) + head.GetHeight() > conY - BufferDis && head.GetIndex() > 1){//最上一个小于可视空间,需要创建个新的LoopListItem item = new LoopListItem(Instantiate(ItemBase, Content.transform));item.SetIndex(head.GetIndex() - 1);InvokeUpdate(item, head.GetIndex() - 1);Arranger.AddArrangeItem(item, item);head = Arranger.GetHeadItem();conY = Mathf.Abs(Content.GetComponent().anchoredPosition.y);}RefreshContentSize();}else if (off * (int)Direction > 0){//在往上滑动//当最上面一个小雨可视加缓冲范围,就交换ILoopItem head = Arranger.GetHeadItem();ILoopItem tail = Arranger.GetTailItem();float conY = Mathf.Abs(Content.GetComponent().anchoredPosition.y);while (Mathf.Abs(head.GetPosition().y) + head.GetHeight() < conY - BufferDis &&tail.GetIndex() < _TotalCount){InvokeUpdate(head, tail.GetIndex() + 1);Arranger.SwapToTail(head.GetLoopItemArrange());head.SetIndex(tail.GetIndex() + 1);RefreshContentSize();head = Arranger.GetHeadItem();tail = Arranger.GetTailItem();conY = Mathf.Abs(Content.GetComponent().anchoredPosition.y);}while (Mathf.Abs(tail.GetPosition().y) < conY + _ViewPortSize.y + BufferDis && tail.GetIndex() < _TotalCount){//最下面一个小于可视空间,需要创建个新的LoopListItem item = new LoopListItem(Instantiate(ItemBase, Content.transform));item.SetIndex(tail.GetIndex() + 1);InvokeUpdate(item, tail.GetIndex() + 1);Arranger.AddArrangeItem(item, item);tail = Arranger.GetTailItem();conY = Mathf.Abs(Content.GetComponent().anchoredPosition.y);}RefreshContentSize();}}else{var Rt = Content.GetComponent();Rt.anchoredPosition = new Vector2(Rt.anchoredPosition.x + off, Rt.anchoredPosition.y);if (off * (int)Direction < 0){//往左滑动//当最左边的Item小于可视缓冲范围,就交换ILoopItem head = Arranger.GetHeadItem();ILoopItem tail = Arranger.GetTailItem();float conX = Mathf.Abs(Content.GetComponent().anchoredPosition.x);while (Mathf.Abs(head.GetPosition().x) + head.GetWidth() < Mathf.Abs(conX) - BufferDis &&tail.GetIndex() < _TotalCount){InvokeUpdate(head, tail.GetIndex() + 1);Arranger.SwapToTail(head.GetLoopItemArrange());head.SetIndex(tail.GetIndex() + 1);RefreshContentSize();head = Arranger.GetHeadItem();tail = Arranger.GetTailItem();conX = Mathf.Abs(Content.GetComponent().anchoredPosition.x);}while (Mathf.Abs(tail.GetPosition().x) < Mathf.Abs(conX) + _ViewPortSize.y + BufferDis &&tail.GetIndex() < _TotalCount){//最下面一个小于可视空间,需要创建个新的LoopListItem item = new LoopListItem(Instantiate(ItemBase, Content.transform));item.SetIndex(tail.GetIndex() + 1);InvokeUpdate(item, tail.GetIndex() + 1);Arranger.AddArrangeItem(item, item);tail = Arranger.GetTailItem();conX = Mathf.Abs(Content.GetComponent().anchoredPosition.x);}RefreshContentSize();}else if (off * (int)Direction > 0){//在往右滑动//当最后面一个大于可视加缓冲范围,就交换 ILoopItem head = Arranger.GetHeadItem();ILoopItem tail = Arranger.GetTailItem();float conX = Mathf.Abs(Content.GetComponent().anchoredPosition.x);while (Mathf.Abs(tail.GetPosition().x) > Mathf.Abs(conX) + _ViewPortSize.y + BufferDis && head.GetIndex() > 1){InvokeUpdate(tail, head.GetIndex() - 1);Arranger.SwapToHead(tail.GetLoopItemArrange());tail.SetIndex(head.GetIndex() - 1);RefreshContentSize();head = Arranger.GetHeadItem();tail = Arranger.GetTailItem();conX = Mathf.Abs(Content.GetComponent().anchoredPosition.x);}while (Mathf.Abs(head.GetPosition().x) + head.GetWidth() > Mathf.Abs(conX) - BufferDis &&head.GetIndex() > 1){//最上一个小于可视空间,需要创建个新的LoopListItem item = new LoopListItem(Instantiate(ItemBase, Content.transform));item.SetIndex(head.GetIndex() - 1);InvokeUpdate(item, head.GetIndex() - 1);Arranger.AddArrangeItem(item, item);head = Arranger.GetHeadItem();conX = Mathf.Abs(Content.GetComponent().anchoredPosition.x);}RefreshContentSize();}}}public class LoopListItemData{public ILoopItem Item;public int Index;public GameObject Obj;public LoopListItemData(ILoopItem item, int index){Item = item;Index = index;}}public class LoopListUpdateCallBack : UnityEvent{}
}
LoopItemArranger.cs
/** Created By Zhaotao On 2019-3-22* Desc:循环列表的排列器*/using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public interface ILoopItemArrange
{ILoopItem GetFrontItem();ILoopItem GetNextItem();ILoopItem GetCurrentItem();
}[Serializable]
public class LoopItemArranger
{//顶,下,左,右 偏移[SerializeField] private float TopOff;[SerializeField] private float BotttomOff;[SerializeField] private float LeftOff;[SerializeField] private float RightOff;//Item之间间隙[SerializeField] private float SpaceOff;private Dictionary _ArrangeDict = new Dictionary();private ILoopItem _HeadItem;private ILoopItem _TailItem;private bool _IsVertical = true;private int _Dir = 1;/// /// 设置是不是垂直/// /// 是垂直吗public void SetIsVertical(bool v){_IsVertical = v;}/// /// 设置方向/// /// 方向public void SetDir(int d){_Dir = d;}/// /// 添加Item/// /// ILoopItem /// ILoopItemArrangepublic void AddArrangeItem(ILoopItem key, ILoopItemArrange value){if (_ArrangeDict.ContainsKey(key)){return;}_ArrangeDict.Add(key, value);if (_HeadItem == null){_HeadItem = key;}else if (_TailItem == null){_TailItem = key;_TailItem.SetFrontItem(_HeadItem);_HeadItem.SetNextItem(_TailItem);}else if(key.GetIndex() < _HeadItem.GetIndex()){key.SetFrontItem(null);key.SetNextItem(_HeadItem);_HeadItem.SetFrontItem(key);_HeadItem = key;}else{key.SetFrontItem(_TailItem);key.SetNextItem(null);_TailItem.SetNextItem(key);_TailItem = key;}if (key == _HeadItem){UpdateArrangeByNext(value);}else{UpdateArrangeByFront(value);}}/// /// 根据前面点获取下面点的位置/// /// 前面Item/// private Vector2 GetNewPosByFront(ILoopItem front){Vector2 off = Vector2.zero;if (_IsVertical){if (front != null){off += new Vector2(LeftOff, front.GetPosition().y * _Dir - front.GetHeight() - SpaceOff);}else{off += new Vector2(LeftOff, -TopOff);}}else{if (front != null){off += new Vector2(front.GetPosition().x * _Dir + front.GetWidth() + SpaceOff, -TopOff);}else{off += new Vector2(LeftOff, -TopOff);}}return off;}/// /// 根据下面Item,获得上面Item的位置/// /// 下面Item/// private Vector2 GetNewPosByNext(ILoopItem next){Vector2 off = Vector2.zero;if (_IsVertical){if (next != null){off += new Vector2(LeftOff, next.GetPosition().y * _Dir + next.GetHeight() + SpaceOff);}else{off += new Vector2(LeftOff, -TopOff);}}else{if (next != null){off += new Vector2(next.GetPosition().x *_Dir - next.GetWidth() - SpaceOff, -TopOff);}else{off += new Vector2(LeftOff, -TopOff);}}return off;}/// /// 更加Item,刷新Item以及之后Item的位置/// /// 当前Itemprivate void UpdateArrangeByFront(ILoopItemArrange item){var front = item.GetFrontItem();item.GetCurrentItem().SetPosition(GetNewPosByFront(front) * _Dir);var next = item.GetNextItem();if (next != null){UpdateArrangeByFront(_ArrangeDict[next]);}}/// /// 更加Item,刷新Item以及之前Item的位置/// /// 当前Itemprivate void UpdateArrangeByNext(ILoopItemArrange item){var next = item.GetNextItem();item.GetCurrentItem().SetPosition(GetNewPosByNext(next) * _Dir);var front = item.GetFrontItem();if (front != null){UpdateArrangeByNext(_ArrangeDict[front]);}}/// /// 刷新全部可见Item/// public void UpdateVisibleItems(){UpdateArrangeByFront(_ArrangeDict[_HeadItem]);}/// /// 把当前Item变成Tail/// /// public void SwapToTail(ILoopItemArrange item){if (_HeadItem != null && _TailItem != null){if (_HeadItem == item.GetCurrentItem()){_HeadItem = item.GetNextItem();}item.GetCurrentItem().SetFrontItem(_TailItem);item.GetCurrentItem().SetNextItem(null);_TailItem.SetNextItem(item.GetCurrentItem());_TailItem = item.GetCurrentItem();UpdateArrangeByFront(_TailItem.GetLoopItemArrange());}}/// /// 把当前Item变成Head/// /// public void SwapToHead(ILoopItemArrange item){if (_HeadItem != null && _TailItem != null){if (_TailItem == item.GetCurrentItem()){_TailItem = item.GetFrontItem();}item.GetCurrentItem().SetNextItem(_HeadItem);item.GetCurrentItem().SetFrontItem(null);_HeadItem.SetFrontItem(item.GetCurrentItem());_HeadItem = item.GetCurrentItem();UpdateArrangeByNext(_HeadItem.GetLoopItemArrange());}}/// /// 根据垂直和水平获得高度或宽度/// /// public float GetSize(){if (_HeadItem == null || _TailItem == null){return 0;}if (_IsVertical){return Mathf.Abs(_HeadItem.GetPosition().y * _Dir - _TailItem.GetPosition().y * _Dir) + _TailItem.GetHeight() + TopOff +BotttomOff;}return Mathf.Abs(_HeadItem.GetPosition().x * _Dir - _TailItem.GetPosition().x * _Dir) + _TailItem.GetWidth() + LeftOff +RightOff;;}/// /// 获得Head Item/// /// public ILoopItem GetHeadItem(){return _HeadItem;}/// /// 获得tail Item/// /// public ILoopItem GetTailItem(){return _TailItem;}/// /// 获得底部间隙/// /// public float GetBottomOff(){return BotttomOff;}/// /// 获得右部间隙/// /// public float GetRightOff(){return RightOff;}public float GetSpaceOff(){return SpaceOff;}/// /// 获得当前创建的Item数量/// /// public int GetCount(){return _ArrangeDict.Count;}/// /// 获取Index的Item/// /// 索引/// public ILoopItemArrange GetItemArrangeByIndex(int idx){foreach (var item in _ArrangeDict){if (item.Key.GetIndex() == idx){return item.Value;}}return null;}}
LoopListItem.cs
/** Created By Zhaotao On 2019-3-22* Desc:循环列表Item内容块*/using System.Collections;
using System.Collections.Generic;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine;///
/// 循环列表Item接口
///
public interface ILoopItem
{#region InterfaceFunction/// /// 设置高度/// /// 高度值void SetHeight(float h);/// /// 返回Item的高度/// /// 高度值 float GetHeight();/// /// 设置宽度/// /// 宽度值void SetWidth(float w);/// /// 返回Item的宽度/// /// 宽度值 float GetWidth();/// /// 获得Item的坐标/// /// 坐标值 Vector2 GetPosition();/// /// 设置坐标/// /// 坐标值void SetPosition(Vector2 pos);/// /// 设置前一个Item/// /// 前一个Itemvoid SetFrontItem(ILoopItem item);/// /// 设置后一个Item/// /// 后一个Itemvoid SetNextItem(ILoopItem item);/// /// 获取排序器/// /// 返回排序器 ILoopItemArrange GetLoopItemArrange();/// /// 设置当前Index索引/// /// 索引值void SetIndex(int idx);/// /// 获得当前Item的索引/// /// 索引值 int GetIndex();/// /// 获取当前Item捆绑的GameObject/// /// 返回绑定的对象 GameObject GetGameObject();#endregion
}public class LoopListItem : ILoopItem, ILoopItemArrange
{private ILoopItem _FrontItem;private ILoopItem _NextItem;private GameObject _ItemObj;private float _ItemHeight;private float _ItemWidth;private Vector2 _Pos = Vector2.zero;private int _Index;public LoopListItem(GameObject go){_ItemObj = go;if (go != null){RectTransform rect = go.GetComponent();_ItemHeight = rect.sizeDelta.y;_ItemWidth = rect.sizeDelta.x;_Pos = rect.anchoredPosition;}}public void SetIndex(int idx){_Index = idx;}public int GetIndex(){return _Index;}public void SetHeight(float h){_ItemHeight = h;}public float GetHeight(){return _ItemHeight;}public void SetWidth(float w){_ItemWidth = w;}public float GetWidth(){return _ItemWidth;}public Vector2 GetPosition(){return _Pos;}public void SetPosition(Vector2 pos){_Pos = pos;_ItemObj.GetComponent().anchoredPosition = _Pos;}public void SetFrontItem(ILoopItem item){_FrontItem = item;}public void SetNextItem(ILoopItem item){_NextItem = item;}public ILoopItemArrange GetLoopItemArrange(){return this;}public GameObject GetGameObject(){return _ItemObj;}public ILoopItem GetFrontItem(){return _FrontItem;}public ILoopItem GetNextItem(){return _NextItem;}public ILoopItem GetCurrentItem(){return this;}
}
这样就实现了一个 正反方向 垂直水平的循环列表。支持不等高Item
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
