using UnityEngine; namespace AlicizaX.UI.RecyclerView { public class MixedLayoutManager : LayoutManager { public MixedLayoutManager() { } public override Vector2 CalculateContentSize() { int index = adapter.GetItemCount(); float position = 0; for (int i = 0; i < index; i++) { position += GetLength(i); } return direction == Direction.Vertical ? new Vector2(contentSize.x, position - spacing.y + padding.y * 2) : new Vector2(position - spacing.x + padding.x * 2, contentSize.y); } public override Vector2 CalculatePosition(int index) { // TODO 优化点,将 position 定义成全局变量 float position = 0; for (int i = 0; i < index; i++) { position += GetLength(i); } position -= ScrollPosition; return direction == Direction.Vertical ? new Vector2(0, position + padding.y) : new Vector2(position + padding.x, 0); } public override Vector2 CalculateContentOffset() { Vector2 size = viewProvider.CalculateViewSize(0); float len = GetFitContentSize(); if (direction == Direction.Vertical) { return new Vector2(0, (len - size.y) / 2); } return new Vector2((len - size.x) / 2, 0); } public override Vector2 CalculateViewportOffset() { Vector2 size = viewProvider.CalculateViewSize(0); if (direction == Direction.Vertical) { return new Vector2(0, (viewportSize.y - size.y) / 2); } return new Vector2((viewportSize.x - size.x) / 2, 0); } public override int GetStartIndex() { float position = 0; float contentPosition = ScrollPosition; int itemCount = adapter.GetItemCount(); for (int i = 0; i < itemCount; i++) { position += GetLength(i); if (position > contentPosition) { return Mathf.Max(0, i); } } return 0; } public override int GetEndIndex() { float position = 0; float viewLength = direction == Direction.Vertical ? viewportSize.y : viewportSize.x; int itemCount = adapter.GetItemCount(); for (int i = 0; i < itemCount; i++) { position += GetLength(i); if (position > ScrollPosition + viewLength) { return Mathf.Min(i, adapter.GetItemCount() - 1); ; } } return itemCount - 1; } private float GetLength(int index) { Vector2 size = viewProvider.CalculateViewSize(index); if (index < adapter.GetItemCount() - 1) { size += spacing; } float len = direction == Direction.Vertical ? size.y : size.x; return len; } public override float IndexToPosition(int index) { Vector2 position = CalculatePosition(index); if (direction == Direction.Vertical) { position.y = Mathf.Max(0, position.y); position.y = Mathf.Min(position.y, contentSize.y - viewportSize.y); return position.y; } else { position.x = Mathf.Max(0, position.x); position.x = Mathf.Min(position.x, contentSize.x - viewportSize.x); return position.x; } } public override int PositionToIndex(float position) { float len = 0; int itemCount = adapter.GetItemCount(); for (int i = 0; i < itemCount; i++) { len += GetLength(i); if (len >= position) { return i; } } return 0; } } }