75 lines
2.9 KiB
C#
75 lines
2.9 KiB
C#
using System;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
using UnityEngine.EventSystems;
|
||
using TMPro;
|
||
|
||
namespace BaseGames.UI
|
||
{
|
||
/// <summary>
|
||
/// 通用可选择行:图标 + 标签 + 选中高亮 + 按钮,适用于菜单项、设置行、存档槽、列表项。
|
||
///
|
||
/// 配合 <see cref="PooledListView{TData,TView}"/> 作 TView,或在面板里直接布局使用。
|
||
/// 选中(手柄/键盘导航或鼠标悬停)时自动切换高亮节点。
|
||
/// </summary>
|
||
[DisallowMultipleComponent]
|
||
public class UISelectableRow : MonoBehaviour, ISelectHandler, IDeselectHandler, IPointerEnterHandler
|
||
{
|
||
[Header("引用")]
|
||
[SerializeField] private Button _button;
|
||
[SerializeField] private TMP_Text _label;
|
||
[Tooltip("行图标(可空)。")]
|
||
[SerializeField] private Image _icon;
|
||
[Tooltip("选中高亮节点(可空,选中时 SetActive(true))。")]
|
||
[SerializeField] private GameObject _selectedHighlight;
|
||
|
||
/// <summary>行被点击(或 Submit)时触发。</summary>
|
||
public event Action Clicked;
|
||
|
||
public Button Button => _button;
|
||
public Selectable Selectable => _button;
|
||
|
||
private void Awake()
|
||
{
|
||
if (_selectedHighlight != null) _selectedHighlight.SetActive(false);
|
||
if (_button != null)
|
||
_button.onClick.AddListener(() => Clicked?.Invoke());
|
||
}
|
||
|
||
// ── 数据填充 ──────────────────────────────────────────────────────────
|
||
public void SetLabel(string text)
|
||
{
|
||
if (_label != null) _label.text = text;
|
||
}
|
||
|
||
public void SetIcon(Sprite sprite)
|
||
{
|
||
if (_icon == null) return;
|
||
_icon.sprite = sprite;
|
||
_icon.enabled = sprite != null;
|
||
}
|
||
|
||
public void SetSelected(bool selected)
|
||
{
|
||
if (_selectedHighlight != null) _selectedHighlight.SetActive(selected);
|
||
}
|
||
|
||
/// <summary>把 EventSystem 焦点设到本行。</summary>
|
||
public void Focus()
|
||
{
|
||
if (_button != null && EventSystem.current != null)
|
||
EventSystem.current.SetSelectedGameObject(_button.gameObject);
|
||
}
|
||
|
||
// ── 选中反馈 ──────────────────────────────────────────────────────────
|
||
public void OnSelect(BaseEventData e) => SetSelected(true);
|
||
public void OnDeselect(BaseEventData e) => SetSelected(false);
|
||
|
||
public void OnPointerEnter(PointerEventData e)
|
||
{
|
||
if (_button != null && _button.interactable && EventSystem.current != null)
|
||
EventSystem.current.SetSelectedGameObject(_button.gameObject);
|
||
}
|
||
}
|
||
}
|