From 65f9bbe27598c5ac02f8b3aaed3d61144ddbb99d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=80=9D=E6=B5=B7?= <1464576565@qq.com> Date: Fri, 30 May 2025 19:40:12 +0800 Subject: [PATCH] modify --- .../Layout/AlignableLinearLayoutManager.cs | 71 +++++++++++++++++++ .../AlignableLinearLayoutManager.cs.meta | 3 + .../Layout/LinearLayoutManager.cs | 8 ++- Runtime/RecyclerView/RecyclerView.cs | 2 + Runtime/RecyclerView/Scroller/SAOScroller.cs | 15 ++++ .../RecyclerView/Scroller/SAOScroller.cs.meta | 3 + Runtime/RecyclerView/Scroller/Scroller.cs | 44 +++++++++--- 7 files changed, 137 insertions(+), 9 deletions(-) create mode 100644 Runtime/RecyclerView/Layout/AlignableLinearLayoutManager.cs create mode 100644 Runtime/RecyclerView/Layout/AlignableLinearLayoutManager.cs.meta create mode 100644 Runtime/RecyclerView/Scroller/SAOScroller.cs create mode 100644 Runtime/RecyclerView/Scroller/SAOScroller.cs.meta diff --git a/Runtime/RecyclerView/Layout/AlignableLinearLayoutManager.cs b/Runtime/RecyclerView/Layout/AlignableLinearLayoutManager.cs new file mode 100644 index 0000000..bd7fc35 --- /dev/null +++ b/Runtime/RecyclerView/Layout/AlignableLinearLayoutManager.cs @@ -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; + } + } +} diff --git a/Runtime/RecyclerView/Layout/AlignableLinearLayoutManager.cs.meta b/Runtime/RecyclerView/Layout/AlignableLinearLayoutManager.cs.meta new file mode 100644 index 0000000..12a94a1 --- /dev/null +++ b/Runtime/RecyclerView/Layout/AlignableLinearLayoutManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e5cb3f76e0f84a7aa75959e194f524b5 +timeCreated: 1748588163 \ No newline at end of file diff --git a/Runtime/RecyclerView/Layout/LinearLayoutManager.cs b/Runtime/RecyclerView/Layout/LinearLayoutManager.cs index 95e5716..eef057f 100644 --- a/Runtime/RecyclerView/Layout/LinearLayoutManager.cs +++ b/Runtime/RecyclerView/Layout/LinearLayoutManager.cs @@ -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); } diff --git a/Runtime/RecyclerView/RecyclerView.cs b/Runtime/RecyclerView/RecyclerView.cs index 249fa0e..fcbcc5a 100644 --- a/Runtime/RecyclerView/RecyclerView.cs +++ b/Runtime/RecyclerView/RecyclerView.cs @@ -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()); diff --git a/Runtime/RecyclerView/Scroller/SAOScroller.cs b/Runtime/RecyclerView/Scroller/SAOScroller.cs new file mode 100644 index 0000000..9ef05fd --- /dev/null +++ b/Runtime/RecyclerView/Scroller/SAOScroller.cs @@ -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 + { + + } +} diff --git a/Runtime/RecyclerView/Scroller/SAOScroller.cs.meta b/Runtime/RecyclerView/Scroller/SAOScroller.cs.meta new file mode 100644 index 0000000..19edfe7 --- /dev/null +++ b/Runtime/RecyclerView/Scroller/SAOScroller.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 96b927c6a47e4c088e2fe9bdadd0fab9 +timeCreated: 1748589040 \ No newline at end of file diff --git a/Runtime/RecyclerView/Scroller/Scroller.cs b/Runtime/RecyclerView/Scroller/Scroller.cs index d619133..5bec036 100644 --- a/Runtime/RecyclerView/Scroller/Scroller.cs +++ b/Runtime/RecyclerView/Scroller/Scroller.cs @@ -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 /// 内容所需要大小 /// protected Vector2 contentSize; + public Vector2 ContentSize { get => contentSize; @@ -35,6 +42,7 @@ namespace AlicizaX.UI.RecyclerView /// 所在 View 的真实大小 /// 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); + } } }