This commit is contained in:
陈思海 2025-05-30 19:40:12 +08:00
parent 9987d56adf
commit 65f9bbe275
7 changed files with 137 additions and 9 deletions

View File

@ -0,0 +1,71 @@
using UnityEngine;
namespace AlicizaX.UI.RecyclerView
{
public class AlignableLinearLayoutManager : LinearLayoutManager
{
[SerializeField] private float alignmentRatio = 0f; // 对齐比例 (0=顶部, 1=底部, 0.5=居中)
private float CalculateAlignmentOffset()
{
if (direction == Direction.Vertical)
{
// 垂直布局:计算视口高度相关的偏移
float viewportHeight = viewportSize.y;
float itemHeight = lineHeight;
return alignmentRatio * (viewportHeight - itemHeight);
}
else
{
// 水平布局:计算视口宽度相关的偏移
float viewportWidth = viewportSize.x;
float itemWidth = lineHeight; // 注意水平布局中lineHeight表示宽度
return alignmentRatio * (viewportWidth - itemWidth);
}
}
public override Vector2 CalculatePosition(int index)
{
float position;
float alignmentOffset = CalculateAlignmentOffset();
if (direction == Direction.Vertical)
{
position = index * (lineHeight + spacing.y) - ScrollPosition + alignmentOffset;
return new Vector2(0, position + padding.y);
}
position = index * (lineHeight + spacing.x) - ScrollPosition + alignmentOffset;
var a = new Vector2(position + padding.x, 0);
Debug.Log("Calcu" + a);
return a;
}
public override float IndexToPosition(int index)
{
if (index < 0 || index >= adapter.GetItemCount()) return 0;
float len, viewLength, position;
float alignmentOffset = CalculateAlignmentOffset();
if (direction == Direction.Vertical)
{
len = index * (lineHeight + spacing.y) + alignmentOffset - ((lineHeight + spacing.y) * 2);
viewLength = viewportSize.y;
position = len + viewLength > contentSize.y ? contentSize.y - viewportSize.y : len;
}
else
{
len = index * (lineHeight + spacing.x) + alignmentOffset;
viewLength = viewportSize.x;
position = len + viewLength > contentSize.x ? contentSize.x - viewportSize.x : len;
}
Debug.Log($"index:{index} len:{len} view:{viewLength} position:{position}");
return position;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e5cb3f76e0f84a7aa75959e194f524b5
timeCreated: 1748588163

View File

@ -6,7 +6,9 @@ namespace AlicizaX.UI.RecyclerView
{
protected float lineHeight;
public LinearLayoutManager() { }
public LinearLayoutManager()
{
}
public override Vector2 CalculateContentSize()
{
@ -20,6 +22,7 @@ namespace AlicizaX.UI.RecyclerView
position = index * (lineHeight + spacing.y) - spacing.y;
return new Vector2(contentSize.x, position + padding.y * 2);
}
position = index * (lineHeight + spacing.x) - spacing.x;
return new Vector2(position + padding.x * 2, contentSize.y);
}
@ -32,6 +35,7 @@ namespace AlicizaX.UI.RecyclerView
position = index * (lineHeight + spacing.y) - ScrollPosition;
return new Vector2(0, position + padding.y);
}
position = index * (lineHeight + spacing.x) - ScrollPosition;
return new Vector2(position + padding.x, 0);
}
@ -43,6 +47,7 @@ namespace AlicizaX.UI.RecyclerView
{
return new Vector2(0, (len - lineHeight) / 2);
}
return new Vector2((len - lineHeight) / 2, 0);
}
@ -52,6 +57,7 @@ namespace AlicizaX.UI.RecyclerView
{
return new Vector2(0, (viewportSize.y - lineHeight) / 2);
}
return new Vector2((viewportSize.x - lineHeight) / 2, 0);
}

View File

@ -113,6 +113,7 @@ namespace AlicizaX.UI.RecyclerView
private int startIndex, endIndex;
private int currentIndex;
public Scroller Scroller => _scroller;
public int CurrentIndex
{
get => currentIndex;
@ -364,6 +365,7 @@ namespace AlicizaX.UI.RecyclerView
}
}
private void SnapTo()
{
var index = _layoutManager.PositionToIndex(GetScrollPosition());

View File

@ -0,0 +1,15 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using static UnityEngine.Mathf;
namespace AlicizaX.UI.RecyclerView
{
[Serializable]
public class SAOScroller : Scroller
{
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 96b927c6a47e4c088e2fe9bdadd0fab9
timeCreated: 1748589040

View File

@ -9,12 +9,18 @@ namespace AlicizaX.UI.RecyclerView
public class Scroller : MonoBehaviour, IScroller, IBeginDragHandler, IEndDragHandler, IDragHandler, IScrollHandler
{
protected float position;
public float Position { get => position; set => position = value; }
public float Position
{
get => position;
set => position = value;
}
protected float velocity;
public float Velocity => velocity;
protected Direction direction;
public Direction Direction
{
get => direction;
@ -25,6 +31,7 @@ namespace AlicizaX.UI.RecyclerView
/// 内容所需要大小
/// </summary>
protected Vector2 contentSize;
public Vector2 ContentSize
{
get => contentSize;
@ -35,6 +42,7 @@ namespace AlicizaX.UI.RecyclerView
/// 所在 View 的真实大小
/// </summary>
protected Vector2 viewSize;
public Vector2 ViewSize
{
get => viewSize;
@ -42,6 +50,7 @@ namespace AlicizaX.UI.RecyclerView
}
protected float scrollSpeed = 1f;
public float ScrollSpeed
{
get => scrollSpeed;
@ -49,6 +58,7 @@ namespace AlicizaX.UI.RecyclerView
}
protected float wheelSpeed = 30f;
public float WheelSpeed
{
get => wheelSpeed;
@ -56,6 +66,7 @@ namespace AlicizaX.UI.RecyclerView
}
protected bool snap;
public bool Snap
{
get => snap;
@ -66,17 +77,27 @@ namespace AlicizaX.UI.RecyclerView
protected MoveStopEvent moveStopEvent = new();
protected DraggingEvent draggingEvent = new();
public float MaxPosition => direction == Direction.Vertical ?
Mathf.Max(contentSize.y - viewSize.y, 0) :
Mathf.Max(contentSize.x - viewSize.x, 0);
public float MaxPosition => direction == Direction.Vertical ? Mathf.Max(contentSize.y - viewSize.y, 0) : Mathf.Max(contentSize.x - viewSize.x, 0);
public float ViewLength => direction == Direction.Vertical ? viewSize.y : viewSize.x;
public ScrollerEvent OnValueChanged { get => scrollerEvent; set => scrollerEvent = value; }
public ScrollerEvent OnValueChanged
{
get => scrollerEvent;
set => scrollerEvent = value;
}
public MoveStopEvent OnMoveStoped { get => moveStopEvent; set => moveStopEvent = value; }
public MoveStopEvent OnMoveStoped
{
get => moveStopEvent;
set => moveStopEvent = value;
}
public DraggingEvent OnDragging { get => draggingEvent; set => draggingEvent = value; }
public DraggingEvent OnDragging
{
get => draggingEvent;
set => draggingEvent = value;
}
// 停止滑动的时间,但此时并未释放鼠标按键
private float dragStopTime = 0f;
@ -125,7 +146,7 @@ namespace AlicizaX.UI.RecyclerView
OnValueChanged?.Invoke(position);
}
public void OnScroll(PointerEventData eventData)
public virtual void OnScrolled(PointerEventData eventData)
{
StopAllCoroutines();
@ -155,6 +176,7 @@ namespace AlicizaX.UI.RecyclerView
{
rate = Mathf.Max(0, 1 - (Mathf.Abs(position - MaxPosition) / ViewLength));
}
return rate;
}
@ -243,5 +265,11 @@ namespace AlicizaX.UI.RecyclerView
position = targetPos;
OnValueChanged?.Invoke(position);
}
void IScrollHandler.OnScroll(PointerEventData eventData)
{
OnScrolled(eventData);
}
}
}