com.alicizax.unity.ui.exten.../Runtime/RecyclerView/Navigation/RecyclerNavigationController.cs
陈思海 dc8c840d69 RecyclerView 大优化
优化RecycleView 渲染架构
优化RecyclerView 渲染性能 增加 缓存 异步
增加Navagation导航锚点相关
2026-03-31 15:18:50 +08:00

98 lines
3.2 KiB
C#

using UnityEngine;
using UnityEngine.EventSystems;
namespace AlicizaX.UI
{
public sealed class RecyclerNavigationController
{
private readonly RecyclerView recyclerView;
public RecyclerNavigationController(RecyclerView recyclerView)
{
this.recyclerView = recyclerView;
}
public bool TryMove(ViewHolder currentHolder, MoveDirection direction, RecyclerNavigationOptions options)
{
if (recyclerView == null ||
recyclerView.RecyclerViewAdapter == null ||
currentHolder == null)
{
return false;
}
int itemCount = recyclerView.RecyclerViewAdapter.GetItemCount();
int realCount = recyclerView.RecyclerViewAdapter.GetRealCount();
if (itemCount <= 0 || realCount <= 0)
{
return false;
}
int step = GetStep(direction);
if (step == 0)
{
return false;
}
bool isLoopSource = itemCount != realCount;
bool allowWrap = isLoopSource && options.Wrap;
int nextLayoutIndex = currentHolder.Index + step;
if (allowWrap)
{
nextLayoutIndex = WrapIndex(nextLayoutIndex, realCount);
}
else
{
nextLayoutIndex = Mathf.Clamp(nextLayoutIndex, 0, itemCount - 1);
}
if (!allowWrap && nextLayoutIndex == currentHolder.Index)
{
return false;
}
ScrollAlignment alignment = ResolveAlignment(direction, options.Alignment);
return recyclerView.TryFocusIndex(nextLayoutIndex, options.SmoothScroll, alignment);
}
private int GetStep(MoveDirection direction)
{
int unit = Mathf.Max(1, recyclerView.LayoutManager != null ? recyclerView.LayoutManager.Unit : 1);
bool vertical = recyclerView.Direction == Direction.Vertical;
return direction switch
{
MoveDirection.Left => vertical ? -1 : -unit,
MoveDirection.Right => vertical ? 1 : unit,
MoveDirection.Up => vertical ? -unit : -1,
MoveDirection.Down => vertical ? unit : 1,
_ => 0
};
}
private static int WrapIndex(int index, int count)
{
int wrapped = index % count;
return wrapped < 0 ? wrapped + count : wrapped;
}
private ScrollAlignment ResolveAlignment(MoveDirection direction, ScrollAlignment fallback)
{
if (recyclerView == null || recyclerView.LayoutManager == null)
{
return fallback;
}
bool vertical = recyclerView.Direction == Direction.Vertical;
return direction switch
{
MoveDirection.Down when vertical => ScrollAlignment.End,
MoveDirection.Up when vertical => ScrollAlignment.Start,
MoveDirection.Right when !vertical => ScrollAlignment.End,
MoveDirection.Left when !vertical => ScrollAlignment.Start,
_ => fallback
};
}
}
}