首页 > 代码库 > [UGUI]ListLayoutGroup--可重用的滚动列表
[UGUI]ListLayoutGroup--可重用的滚动列表
为了不生成太多的GameObject,当滚动的时候,需要将出框的item重复利用起来。这个网上已经有了很多例子。我为了项目使用方便,在GridLayoutGroup基础上修改了一下,配合ScrollRect使用
首先在传入数据的时候,需要知道要显示多少数据,为了拖动时看不到突然消失的item,会多显示一个(往前滑动的时候和往后滑动的时候会放在最前面或最后面):
private float GetScrollRectSize() { var rectSize = m_scrollRect.GetComponent<RectTransform> ().rect.size; return m_Constraint = IsVertical ? rectSize.y : rect.y; } private float GetCellSize() { return m_Constraint = IsVertical ? cellSize.y + spacing.y : cellSize.x + spacing.x; } public void SetData<P, D>(ICollection<D> dataList, System.Action<int, P, D> setContentHandler) where P : MonoBehaviour { ........ displayListCount = Mathf.CeilToInt(GetScrollRectSize () / GetCellSize()) + 1; ....... }
在滚动的时候,首先需要知道最左上角的数据index:
public int GetStartIndex() { if (m_dataList == null || m_dataList.Count == 0) return 0; float anchorPosition = IsVertical ? rectTransform.anchoredPosition.y : rectTransform.anchoredPosition.x; if(!IsVertical) anchorPosition *= -1; anchorPosition -= GetCellSize() * 0.5f - GetPadding(); return (int)(anchorPosition / GetCellSize()) * constraintCount; }
为了不产生其他开销,Item的实际顺序不会改动,这就需要在已有的顺序中对其在数据中的实际顺序做映射,举个例子,如果一屏可以显示四个数据,那么对应不同的startIndex,四个item的映射关系如下:
Start Index | Actual Index |
0 | 0 1 2 3 |
1 | 4 1 2 3 |
2 | 4 5 1 2 |
如下公式可得到Actual Index(对于无限滚动的列表,start index可能小于0):
private int GetActualIndex(int startIndex, int index) { var count = GetChildCount; return ((startIndex + (startIndex >= 0 ? (count - index - 1) : -index)) / count * count + index); }
滚动时,可根据Actual Index设置Item的位置,并对比滚动前的Actual Index是否改变,决定是否更新数据:
private void SetCellsAlongAxis (int axis) { ...... for(int i = 0; i < m_childCount; ++i) { var child = m_childList[i]; ... if (IsVertical) { positionX = Mathf.Abs(actualIndex) % cellsPerMainAxis; positionY = actualIndex / cellsPerMainAxis; } else { positionX = actualIndex / cellsPerMainAxis; positionY = Mathf.Abs(actualIndex) % cellsPerMainAxis; } if (cornerX == 1) positionX = actualCellCountX - 1 - positionX; if (cornerY == 1) positionY = actualCellCountY - 1 - positionY;
......
if(actualIndex != previousIndex) { SetItemContent(acutalIndex, child, m_dataList[i]); } SetChildAlongAxis (child, 0, startOffset.x + (cellSize [0] + spacing [0]) * positionX, cellSize [0]); SetChildAlongAxis (child, 1, startOffset.y + (cellSize [1] + spacing [1]) * positionY, cellSize [1]); }
}
[UGUI]ListLayoutGroup--可重用的滚动列表
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。