From 33b03719a1fe0bf9e61d551e788c3b3756fd1a2c Mon Sep 17 00:00:00 2001 From: BobSong <605277374@qq.com> Date: Thu, 30 Oct 2025 23:54:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=97=E8=A1=A8=E9=80=89=E6=8B=A9=E5=99=A8?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Scripts/UI/Common/List/ClassifyList.cs | 45 +++-- Assets/Scripts/UI/Common/List/ListSelector.cs | 158 ++++++++++++++++++ .../UI/Common/List/ListSelector.cs.meta | 3 + 3 files changed, 183 insertions(+), 23 deletions(-) create mode 100644 Assets/Scripts/UI/Common/List/ListSelector.cs create mode 100644 Assets/Scripts/UI/Common/List/ListSelector.cs.meta diff --git a/Assets/Scripts/UI/Common/List/ClassifyList.cs b/Assets/Scripts/UI/Common/List/ClassifyList.cs index c8f385b6a..96347af3c 100644 --- a/Assets/Scripts/UI/Common/List/ClassifyList.cs +++ b/Assets/Scripts/UI/Common/List/ClassifyList.cs @@ -21,10 +21,13 @@ namespace NBF private int _columnsCount; + public ListSelector _selector; + private void OnInited() { Game.Input.OnUICanceled += OnUICanceled; List.onClickItem.Add(OnClickListItem); + _selector = new ListSelector(List, typeof(ListTitleItem)); } public override void Dispose() @@ -37,49 +40,43 @@ namespace NBF { if (action == InputDef.UI.Right) { - SetListSelected(List.selectedIndex + 1); + _selector.Right(); } else if (action == InputDef.UI.Left) { - SetListSelected(List.selectedIndex - 1); + _selector.Left(); } else if (action == InputDef.UI.Up) { - SetListSelected(List.selectedIndex - _columnsCount); + _selector.Up(); } else if (action == InputDef.UI.Down) { - if (List.selectedIndex < 0) - { - SetListSelected(0); - } - else - { - SetListSelected(List.selectedIndex + _columnsCount); - } + _selector.Down(); } } - private void SetListSelected(int selectedIndex) - { - if (selectedIndex >= 0 && selectedIndex < _listData.Count) - { - var count = List.numChildren; - List.selectedIndex = selectedIndex; - List.ScrollToView(selectedIndex); - } - } + // private void SetListSelected(int selectedIndex) + // { + // if (selectedIndex >= 0 && selectedIndex < _listData.Count) + // { + // var count = List.numChildren; + // List.selectedIndex = selectedIndex; + // List.ScrollToView(selectedIndex); + // } + // } public void SetListData(List listData, ListSelectionMode selectionMode = ListSelectionMode.Single) { List.selectedIndex = -1; _listData.Clear(); - + foreach (var obj in listData) { _listData.Add(obj); } + List.RemoveChildrenToPool(); List.defaultItem = ListTitleItem.URL; List.itemProvider = GetListItemResource; @@ -92,10 +89,11 @@ namespace NBF } catch (Exception e) { - Log.Error(e); + Log.Error(e); } - + _columnsCount = 6; + _selector.Refresh(); } void OnClickListItem(EventContext context) @@ -136,6 +134,7 @@ namespace NBF { return BagItem.URL; } + if (itemData is ClassifyListTitleData titleData) { return ListTitleItem.URL; diff --git a/Assets/Scripts/UI/Common/List/ListSelector.cs b/Assets/Scripts/UI/Common/List/ListSelector.cs new file mode 100644 index 000000000..9dd3ac5d1 --- /dev/null +++ b/Assets/Scripts/UI/Common/List/ListSelector.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using FairyGUI; +using UnityEngine; + +namespace NBF +{ + public class ListSelector + { + private GList _list; + private readonly List _ignores = new List(); + // private readonly List _items = new List(); + + private float itemWidth = 200f; + private float itemHeight = 180f; + + public ListSelector(GList list, params Type[] ignores) + { + _list = list; + if (ignores != null && _ignores.Count > 0) + { + _ignores.AddRange(_ignores); + } + } + + #region 数据刷新 + + public void Refresh() + { + var children = _list.GetChildren(); + foreach (var item in children) + { + if (_ignores.Contains(item.GetType())) continue; + itemWidth = item.width; + itemHeight = item.height; + break; + } + } + + #endregion + + #region 操作 + + public void Up() + { + Move(Vector2.up); + } + + public void Down() + { + Move(Vector2.down); + } + + public void Right() + { + Move(Vector2.right); + } + + public void Left() + { + Move(Vector2.left); + } + + public void Move(Vector2 direction) + { + if (_list.selectedIndex == -1) + { + // 首次选择第一个可选中项 + SelectFirstSelectable(); + return; + } + + var currentPos = GetItemPosition(_list.selectedIndex); + var nearestIndex = FindNearestSelectableItem(currentPos, direction); + + if (nearestIndex != -1) + { + SetSelection(nearestIndex); + } + } + + #endregion + + #region 内部方法 + + private Vector2 GetItemPosition(int index) + { + var item = _list.GetChildAt(index); + return item.position; + } + + private int FindNearestSelectableItem(Vector2 fromPos, Vector2 direction) + { + var bestIndex = -1; + var bestDistance = float.MaxValue; + + for (var i = 0; i < _list.numItems; i++) + { + if (!IsSelectableItem(i)) continue; + + var targetPos = GetItemPosition(i); + var diff = targetPos - fromPos; + + // 检查方向匹配度 + if (IsDirectionMatch(direction, diff)) + { + var distance = Vector2.Distance(fromPos, targetPos); + if (distance < bestDistance && distance > 0.1f) + { + bestDistance = distance; + bestIndex = i; + } + } + } + + return bestIndex; + } + + private bool IsDirectionMatch(Vector2 direction, Vector2 diff) + { + if (direction == Vector2.up) + return diff.y < 0 && Mathf.Abs(diff.x) < itemWidth; // 修正:向上应该是Y值更小 + if (direction == Vector2.down) + return diff.y > 0 && Mathf.Abs(diff.x) < itemWidth; // 修正:向下应该是Y值更大 + if (direction == Vector2.left) + return diff.x < 0 && Mathf.Abs(diff.y) < itemHeight; + if (direction == Vector2.right) + return diff.x > 0 && Mathf.Abs(diff.y) < itemHeight; + return false; + } + + private bool IsSelectableItem(int index) + { + var item = _list.GetChildAt(index); + return !_ignores.Contains(item.GetType()); + } + + private void SelectFirstSelectable() + { + for (var i = 0; i < _list.numItems; i++) + { + if (IsSelectableItem(i)) + { + SetSelection(i); + break; + } + } + } + + private void SetSelection(int index) + { + _list.selectedIndex = index; + // selection.position = items[index].position; + } + + #endregion + } +} \ No newline at end of file diff --git a/Assets/Scripts/UI/Common/List/ListSelector.cs.meta b/Assets/Scripts/UI/Common/List/ListSelector.cs.meta new file mode 100644 index 000000000..fb27c3d2a --- /dev/null +++ b/Assets/Scripts/UI/Common/List/ListSelector.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 48f217b6f1dd4dc98d1b6e1c61f9ed65 +timeCreated: 1761838465 \ No newline at end of file