using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; /// /// Tab键导航系统 /// 自动管理InputField之间的Tab键切换 /// public class TabNavigationSystem : MonoBehaviour { [Header("导航设置")] public List NavigationOrder = new List(); // 导航顺序 public bool AutoDetectInputFields = true; // 自动检测InputField public bool WrapNavigation = true; // 是否循环导航 public bool EnableShiftReverse = true; // 是否支持Shift+Tab反向导航 [Header("调试")] public bool ShowDebugInfo = false; private int _currentIndex = -1; private EventSystem _eventSystem; void Start() { Initialize(); } void Update() { HandleTabInput(); } private void Initialize() { _eventSystem = EventSystem.current; if (AutoDetectInputFields) { AutoDetectNavigationElements(); } // 设置初始焦点 if (NavigationOrder.Count > 0) { SetFocus(0); } if (ShowDebugInfo) { Debug.Log($"TabNavigationSystem: 初始化完成,找到 {NavigationOrder.Count} 个可导航元素"); } } /// /// 自动检测可导航元素 /// private void AutoDetectNavigationElements() { NavigationOrder.Clear(); // 查找所有InputField var inputFields = FindObjectsOfType(); foreach (var inputField in inputFields) { if (inputField.interactable && inputField.gameObject.activeInHierarchy) { NavigationOrder.Add(inputField); } } // 查找所有传统InputField var legacyInputFields = FindObjectsOfType(); foreach (var inputField in legacyInputFields) { if (inputField.interactable && inputField.gameObject.activeInHierarchy) { NavigationOrder.Add(inputField); } } // 根据层级顺序排序 NavigationOrder.Sort((a, b) => { // 先按Y坐标排序(从上到下) var posA = a.transform.position; var posB = b.transform.position; if (Mathf.Abs(posA.y - posB.y) > 0.1f) { return posB.y.CompareTo(posA.y); // Y坐标大的在前(上面的先) } // Y坐标相近时按X坐标排序(从左到右) return posA.x.CompareTo(posB.x); }); } /// /// 处理Tab键输入 /// private void HandleTabInput() { if (NavigationOrder.Count == 0) return; // 检查Tab键 if (Input.GetKeyDown(KeyCode.Tab)) { bool reverse = EnableShiftReverse && (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)); if (reverse) { NavigatePrevious(); } else { NavigateNext(); } } // 检查Enter键(移动到下一个) if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter)) { // 如果当前焦点是InputField,则移动到下一个 var currentSelection = _eventSystem?.currentSelectedGameObject; if (currentSelection != null) { var inputField = currentSelection.GetComponent(); var legacyInputField = currentSelection.GetComponent(); if (inputField != null || legacyInputField != null) { NavigateNext(); } } } } /// /// 导航到下一个元素 /// public void NavigateNext() { if (NavigationOrder.Count == 0) return; _currentIndex++; if (WrapNavigation) { _currentIndex %= NavigationOrder.Count; } else { _currentIndex = Mathf.Min(_currentIndex, NavigationOrder.Count - 1); } SetFocus(_currentIndex); } /// /// 导航到上一个元素 /// public void NavigatePrevious() { if (NavigationOrder.Count == 0) return; _currentIndex--; if (WrapNavigation) { if (_currentIndex < 0) { _currentIndex = NavigationOrder.Count - 1; } } else { _currentIndex = Mathf.Max(_currentIndex, 0); } SetFocus(_currentIndex); } /// /// 设置焦点到指定索引的元素 /// public void SetFocus(int index) { if (index < 0 || index >= NavigationOrder.Count) return; if (_eventSystem == null) return; var target = NavigationOrder[index]; if (target == null || !target.interactable || !target.gameObject.activeInHierarchy) { // 跳过不可用的元素 if (WrapNavigation) { NavigateNext(); } return; } _currentIndex = index; // 设置选中 _eventSystem.SetSelectedGameObject(target.gameObject); // 如果是InputField,激活输入 var inputField = target.GetComponent(); if (inputField != null) { inputField.Select(); inputField.ActivateInputField(); } else { var legacyInputField = target.GetComponent(); if (legacyInputField != null) { legacyInputField.Select(); legacyInputField.ActivateInputField(); } } if (ShowDebugInfo) { Debug.Log($"TabNavigationSystem: 焦点切换到 {target.name} (索引: {index})"); } } /// /// 手动添加导航元素 /// public void AddNavigationElement(Selectable element) { if (element != null && !NavigationOrder.Contains(element)) { NavigationOrder.Add(element); } } /// /// 移除导航元素 /// public void RemoveNavigationElement(Selectable element) { if (NavigationOrder.Contains(element)) { int index = NavigationOrder.IndexOf(element); NavigationOrder.Remove(element); // 调整当前索引 if (_currentIndex >= index && _currentIndex > 0) { _currentIndex--; } } } /// /// 刷新导航列表 /// public void RefreshNavigation() { if (AutoDetectInputFields) { AutoDetectNavigationElements(); } } /// /// 获取当前焦点元素 /// public Selectable GetCurrentElement() { if (_currentIndex >= 0 && _currentIndex < NavigationOrder.Count) { return NavigationOrder[_currentIndex]; } return null; } /// /// 获取当前焦点索引 /// public int GetCurrentIndex() { return _currentIndex; } /// /// 跳转到指定元素 /// public void FocusElement(Selectable element) { int index = NavigationOrder.IndexOf(element); if (index >= 0) { SetFocus(index); } } } /// /// Tab导航辅助组件 /// 可以附加到单独的InputField上,提供更精细的控制 /// public class TabNavigationHelper : MonoBehaviour { [Header("导航设置")] public Selectable NextElement; // 下一个元素 public Selectable PreviousElement; // 上一个元素 public bool SkipThisElement = false; // 是否跳过此元素 private Selectable _thisSelectable; void Start() { _thisSelectable = GetComponent(); } void Update() { if (SkipThisElement) return; // 检查是否是当前选中的元素 if (EventSystem.current?.currentSelectedGameObject == gameObject) { if (Input.GetKeyDown(KeyCode.Tab)) { bool reverse = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift); if (reverse && PreviousElement != null) { FocusElement(PreviousElement); } else if (!reverse && NextElement != null) { FocusElement(NextElement); } } } } private void FocusElement(Selectable element) { if (element != null && element.interactable && element.gameObject.activeInHierarchy) { EventSystem.current?.SetSelectedGameObject(element.gameObject); var inputField = element.GetComponent(); if (inputField != null) { inputField.Select(); inputField.ActivateInputField(); } else { var legacyInputField = element.GetComponent(); if (legacyInputField != null) { legacyInputField.Select(); legacyInputField.ActivateInputField(); } } } } }