2024-09-04 16:02:38 +08:00
|
|
|
using System;
|
|
|
|
|
using Framework;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.EventSystems;
|
|
|
|
|
using UnityEngine.UI;
|
|
|
|
|
|
|
|
|
|
public class ButtonUpDrag: MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
|
|
|
|
{
|
|
|
|
|
private bool _isPressed;
|
|
|
|
|
private bool _isLastFramePressed;
|
|
|
|
|
private float _pressedTime;
|
|
|
|
|
private const float MinDelta = 0.01f;
|
|
|
|
|
private const float MinLongPressTime = 0.35f;
|
2024-10-10 15:56:02 +08:00
|
|
|
public static float MinUpDelta = 50f * (Screen.height / 1080f);
|
2024-09-04 16:02:38 +08:00
|
|
|
|
|
|
|
|
private float _maxHorDelta = 0f;
|
|
|
|
|
|
|
|
|
|
private bool _bUpDrag;
|
|
|
|
|
private bool _bLongPress;
|
|
|
|
|
private bool _bOnClick;
|
|
|
|
|
public delegate void OnUpDrag();
|
|
|
|
|
public delegate void OnLongPress();
|
|
|
|
|
public delegate void OnClick();
|
2026-02-04 16:19:21 +08:00
|
|
|
public delegate void OnLongPressCancel();
|
2024-09-04 16:02:38 +08:00
|
|
|
|
|
|
|
|
public delegate void OnPointUp();
|
|
|
|
|
public delegate void OnPointDown();
|
|
|
|
|
public OnPointUp onPointUp;
|
|
|
|
|
public OnPointDown onPointDown;
|
|
|
|
|
|
|
|
|
|
public OnUpDrag onUpDrag;
|
|
|
|
|
public OnLongPress onLongPress;
|
2026-02-04 16:19:21 +08:00
|
|
|
public OnLongPressCancel onLongPressCancel;
|
2024-09-04 16:02:38 +08:00
|
|
|
public OnClick onClick;
|
|
|
|
|
|
2026-04-13 12:17:36 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// 在 InputManager 判定触点已抬起且本组件曾处于按下时调用(与 Unity OnPointerUp 可能不同步,避免误触)。
|
|
|
|
|
/// </summary>
|
|
|
|
|
private Action onPressEndedByInput;
|
|
|
|
|
|
2024-09-04 16:02:38 +08:00
|
|
|
private Vector2 _startPos;
|
|
|
|
|
private Vector2 _curPos;
|
2026-04-13 12:17:36 +08:00
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 非空时:仅当触点移出该 Rect 的屏幕范围才取消长按;为空时沿用 MinDelta 位移判定。
|
|
|
|
|
/// </summary>
|
|
|
|
|
private RectTransform _longPressCancelBounds;
|
2024-09-04 16:02:38 +08:00
|
|
|
|
|
|
|
|
public void AddPointerUp(Action action)
|
|
|
|
|
{
|
|
|
|
|
onPointUp += () =>
|
|
|
|
|
{
|
|
|
|
|
action?.Invoke();
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void AddPointerDown(Action action)
|
|
|
|
|
{
|
|
|
|
|
onPointDown += () =>
|
|
|
|
|
{
|
|
|
|
|
action?.Invoke();
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-09 19:32:50 +08:00
|
|
|
public void AddLongPress(OnLongPress action)
|
|
|
|
|
{
|
|
|
|
|
onLongPress += action;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void AddLongPress<T>(Action<T> action, T param)
|
2024-09-04 16:02:38 +08:00
|
|
|
{
|
|
|
|
|
onLongPress += () =>
|
|
|
|
|
{
|
2024-10-09 19:32:50 +08:00
|
|
|
action?.Invoke(param);
|
2024-09-04 16:02:38 +08:00
|
|
|
};
|
|
|
|
|
}
|
2026-02-04 16:19:21 +08:00
|
|
|
|
|
|
|
|
public void AddLongPressCancel(Action action)
|
|
|
|
|
{
|
|
|
|
|
onLongPressCancel += () =>
|
|
|
|
|
{
|
|
|
|
|
action?.Invoke();
|
|
|
|
|
};
|
|
|
|
|
}
|
2026-04-13 12:17:36 +08:00
|
|
|
|
|
|
|
|
public void SetLongPressCancelBounds(RectTransform bounds)
|
|
|
|
|
{
|
|
|
|
|
_longPressCancelBounds = bounds;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void AddPressEndedByInput(Action action)
|
|
|
|
|
{
|
|
|
|
|
onPressEndedByInput += action;
|
|
|
|
|
}
|
2024-09-04 16:02:38 +08:00
|
|
|
|
|
|
|
|
public void AddUpDrag(Action action)
|
|
|
|
|
{
|
|
|
|
|
onUpDrag += () =>
|
|
|
|
|
{
|
|
|
|
|
action?.Invoke();
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void AddUpDrag<T>(Action<T> action, T param)
|
|
|
|
|
{
|
|
|
|
|
onUpDrag += () =>
|
|
|
|
|
{
|
|
|
|
|
action?.Invoke(param);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void OnPointerDown(PointerEventData eventData)
|
|
|
|
|
{
|
|
|
|
|
_isPressed = true;
|
|
|
|
|
_bLongPress = true;
|
|
|
|
|
_bUpDrag = true;
|
|
|
|
|
_startPos = eventData.pressPosition;
|
2025-07-30 16:45:51 +08:00
|
|
|
|
|
|
|
|
onPointDown?.Invoke();
|
2024-09-04 16:02:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void OnPointerUp(PointerEventData eventData)
|
|
|
|
|
{
|
|
|
|
|
// _isPressed = false;
|
|
|
|
|
// _bLongPress = true;
|
|
|
|
|
// _bUpDrag = true;
|
2025-07-30 16:45:51 +08:00
|
|
|
|
|
|
|
|
onPointUp?.Invoke();
|
2024-09-04 16:02:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void Awake()
|
|
|
|
|
{
|
|
|
|
|
InputManager.Instance.OnFingerUpUI += _OnPutUp;
|
|
|
|
|
InputManager.Instance.OnFingerUp += _OnPutUp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnDestroy()
|
|
|
|
|
{
|
|
|
|
|
if (InputManager.Instance)
|
|
|
|
|
{
|
|
|
|
|
InputManager.Instance.OnFingerUpUI -= _OnPutUp;
|
|
|
|
|
InputManager.Instance.OnFingerUp -= _OnPutUp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Update()
|
|
|
|
|
{
|
|
|
|
|
if (!_isPressed)
|
|
|
|
|
{
|
|
|
|
|
_bOnClick = false;
|
|
|
|
|
_isLastFramePressed = false;
|
|
|
|
|
_pressedTime = 0f;
|
|
|
|
|
_maxHorDelta = 0f;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_isPressed)
|
|
|
|
|
{
|
|
|
|
|
_curPos = InputManager.Instance.GetTouchPosition();
|
|
|
|
|
//长按
|
|
|
|
|
if (_bLongPress)
|
|
|
|
|
{
|
2026-04-13 12:17:36 +08:00
|
|
|
bool cancelByBounds = _longPressCancelBounds != null &&
|
|
|
|
|
!IsScreenPointInsideRect(_longPressCancelBounds, _curPos);
|
|
|
|
|
bool cancelByDelta = _longPressCancelBounds == null &&
|
|
|
|
|
(_curPos - _startPos).sqrMagnitude > MinDelta;
|
|
|
|
|
|
|
|
|
|
if (cancelByBounds || cancelByDelta)
|
2024-09-04 16:02:38 +08:00
|
|
|
{
|
|
|
|
|
_bLongPress = false;
|
|
|
|
|
_bOnClick = false;
|
2026-02-04 16:19:21 +08:00
|
|
|
onLongPressCancel?.Invoke();
|
2024-09-04 16:02:38 +08:00
|
|
|
}
|
2026-04-13 12:17:36 +08:00
|
|
|
else if (_pressedTime > MinLongPressTime)
|
2024-09-04 16:02:38 +08:00
|
|
|
{
|
2026-04-13 12:17:36 +08:00
|
|
|
onLongPress?.Invoke();
|
|
|
|
|
_bLongPress = false;
|
2024-09-04 16:02:38 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//上滑
|
2024-10-09 19:32:50 +08:00
|
|
|
if (!_bLongPress && _bUpDrag)
|
2024-09-04 16:02:38 +08:00
|
|
|
{
|
2024-10-10 15:05:22 +08:00
|
|
|
var disSqrY = Mathf.Sqrt(Mathf.Pow(_curPos.y - _startPos.y, 2));
|
|
|
|
|
var disSqrX = Mathf.Sqrt(Mathf.Pow(_curPos.x - _startPos.x, 2));
|
|
|
|
|
//防止拖过去拖回来少算
|
2024-09-04 16:02:38 +08:00
|
|
|
if (_maxHorDelta < disSqrX)
|
|
|
|
|
{
|
|
|
|
|
_maxHorDelta = disSqrX;
|
|
|
|
|
}
|
2024-10-10 15:05:22 +08:00
|
|
|
//调节水平拖动敏感程度
|
2024-10-10 15:56:02 +08:00
|
|
|
if (_maxHorDelta < MinUpDelta * 4)
|
2024-09-04 16:02:38 +08:00
|
|
|
{
|
2024-10-10 15:05:22 +08:00
|
|
|
if (disSqrY > MinUpDelta)
|
2024-09-04 16:02:38 +08:00
|
|
|
{
|
2024-09-05 14:24:16 +08:00
|
|
|
onUpDrag?.Invoke();
|
2024-09-04 16:02:38 +08:00
|
|
|
_bUpDrag = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_pressedTime += Time.deltaTime;
|
|
|
|
|
if (!_isLastFramePressed)
|
|
|
|
|
{
|
|
|
|
|
_isLastFramePressed = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void _OnPutUp(Vector2 pos)
|
|
|
|
|
{
|
|
|
|
|
if (_isPressed)
|
|
|
|
|
{
|
2026-04-13 12:17:36 +08:00
|
|
|
onPressEndedByInput?.Invoke();
|
2024-09-04 16:02:38 +08:00
|
|
|
_isPressed = false;
|
|
|
|
|
_bLongPress = true;
|
|
|
|
|
_bUpDrag = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RemoveAll()
|
|
|
|
|
{
|
2025-03-13 17:20:55 +08:00
|
|
|
onLongPress = null;
|
|
|
|
|
onPointDown = null;
|
|
|
|
|
onPointUp = null;
|
|
|
|
|
onClick = null;
|
|
|
|
|
onUpDrag = null;
|
2026-04-13 12:17:36 +08:00
|
|
|
onPressEndedByInput = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool IsScreenPointInsideRect(RectTransform rt, Vector2 screenPoint)
|
|
|
|
|
{
|
|
|
|
|
if (rt == null) return true;
|
|
|
|
|
Canvas canvas = rt.GetComponentInParent<Canvas>();
|
|
|
|
|
Camera cam = null;
|
|
|
|
|
if (canvas != null && canvas.renderMode != RenderMode.ScreenSpaceOverlay)
|
|
|
|
|
cam = canvas.worldCamera;
|
|
|
|
|
return RectTransformUtility.RectangleContainsScreenPoint(rt, screenPoint, cam);
|
2024-09-04 16:02:38 +08:00
|
|
|
}
|
|
|
|
|
}
|