using System; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; /// /// Toggle 长按检测器:挂在 Toggle 同一个物体上。 /// - 短按:不干预,Toggle 自己正常翻转(走原有 onValueChanged 逻辑) /// - 长按(按住超过 longPressTime):触发一次 onLongPress,并吞掉松手时的 Toggle 翻转 /// (松手瞬间 Toggle 的 OnPointerClick 因 interactable=false 不会翻转 isOn,下一帧恢复) /// 用法:面板 Start 里 AddComponent 到目标 Toggle 上并订阅 onLongPress。 /// public class ToggleLongPress : MonoBehaviour, IPointerDownHandler, IPointerUpHandler { [Tooltip("长按判定时间(秒):按住超过此时间触发 onLongPress,提前松手不触发")] public float longPressTime = 0.6f; /// 长按达到阈值时触发一次(提前松手不触发) public event Action onLongPress; private Toggle _toggle; private bool _pressing; private float _timer; private bool _fired; private bool _restoreInteractable; private void Awake() { _toggle = GetComponent(); } private void Update() { if (_pressing) { _timer += Time.deltaTime; if (_timer >= longPressTime && !_fired) { _fired = true; _pressing = false; // ⭐ 吞掉松手时的 Toggle 翻转:Toggle.InternalToggle 检查 IsInteractable, // 置 false 后 OnPointerClick 不会翻转 isOn;下一帧恢复 if (_toggle != null && _toggle.interactable) { _toggle.interactable = false; _restoreInteractable = true; } onLongPress?.Invoke(); } } else if (_restoreInteractable && _toggle != null) { // 长按吞掉翻转后,下一帧恢复 interactable _toggle.interactable = true; _restoreInteractable = false; } } public void OnPointerDown(PointerEventData eventData) { if (eventData.button != PointerEventData.InputButton.Left) return; _pressing = true; _timer = 0f; _fired = false; } public void OnPointerUp(PointerEventData eventData) { _pressing = false; _timer = 0f; // 提前松手(未达长按阈值) → 不干预,Toggle 自己处理点击翻转 } }