118 lines
3.4 KiB
C#
118 lines
3.4 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace AlicizaX.UI.RecyclerView
|
|
{
|
|
public class CircleLayoutManager : LayoutManager
|
|
{
|
|
private float radius;
|
|
private float intervalAngle;
|
|
|
|
private new CircleDirection direction;
|
|
[SerializeField]
|
|
private float initalAngle;
|
|
|
|
|
|
public CircleLayoutManager(CircleDirection direction = CircleDirection.Positive)
|
|
{
|
|
this.direction = direction;
|
|
}
|
|
|
|
public CircleLayoutManager()
|
|
{
|
|
}
|
|
|
|
public override Vector2 CalculateContentSize()
|
|
{
|
|
Vector2 size = viewProvider.CalculateViewSize(0);
|
|
radius = (Mathf.Min(viewportSize.x, viewportSize.y) - Mathf.Min(size.x, size.y)) / 2f - Mathf.Max(padding.x, padding.y);
|
|
intervalAngle = adapter.GetItemCount() > 0 ? 360f / adapter.GetItemCount() : 0;
|
|
|
|
return viewportSize;
|
|
}
|
|
|
|
public override Vector2 CalculateContentOffset()
|
|
{
|
|
return Vector2.zero;
|
|
}
|
|
|
|
public override Vector2 CalculateViewportOffset()
|
|
{
|
|
return Vector2.zero;
|
|
}
|
|
|
|
public override void Layout(ViewHolder viewHolder, int index)
|
|
{
|
|
viewHolder.RectTransform.anchoredPosition3D = CalculatePosition(index);
|
|
}
|
|
|
|
public override Vector2 CalculatePosition(int index)
|
|
{
|
|
float angle = index * intervalAngle;
|
|
angle = direction == CircleDirection.Positive ? angle : -angle;
|
|
angle += initalAngle + ScrollPosition;
|
|
float radian = angle * (Mathf.PI / 180f);
|
|
float x = radius * Mathf.Sin(radian);
|
|
float y = radius * Mathf.Cos(radian);
|
|
|
|
return new Vector2(x, y);
|
|
}
|
|
|
|
public override int GetStartIndex()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
public override int GetEndIndex()
|
|
{
|
|
return adapter.GetItemCount() - 1;
|
|
}
|
|
|
|
public override bool IsFullVisibleStart(int index) => false;
|
|
|
|
public override bool IsFullInvisibleStart(int index) => false;
|
|
|
|
public override bool IsFullVisibleEnd(int index) => false;
|
|
|
|
public override bool IsFullInvisibleEnd(int index) => false;
|
|
|
|
public override bool IsVisible(int index) => true;
|
|
|
|
public override float IndexToPosition(int index)
|
|
{
|
|
float position = index * intervalAngle;
|
|
|
|
return -position;
|
|
}
|
|
|
|
public override int PositionToIndex(float position)
|
|
{
|
|
int index = Mathf.RoundToInt(position / intervalAngle);
|
|
return -index;
|
|
}
|
|
|
|
public override void DoItemAnimation()
|
|
{
|
|
List<ViewHolder> viewHolders = viewProvider.ViewHolders;
|
|
for (int i = 0; i < viewHolders.Count; i++)
|
|
{
|
|
float angle = i * intervalAngle + initalAngle;
|
|
angle = direction == CircleDirection.Positive ? angle + ScrollPosition : angle - ScrollPosition;
|
|
float delta = (angle - initalAngle) % 360;
|
|
delta = delta < 0 ? delta + 360 : delta;
|
|
delta = delta > 180 ? 360 - delta : delta;
|
|
float scale = delta < intervalAngle ? (1.4f - delta / intervalAngle) : 1;
|
|
scale = Mathf.Max(scale, 1);
|
|
|
|
viewHolders[i].RectTransform.localScale = Vector3.one * scale;
|
|
}
|
|
}
|
|
}
|
|
|
|
public enum CircleDirection
|
|
{
|
|
Positive,
|
|
Negative
|
|
}
|
|
}
|