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 }; } } }