【bug】【5795】长按勋章时,极易造成断触

main
Huliang 2026-04-13 12:17:36 +08:00
parent a711491135
commit 82af30818e
2 changed files with 53 additions and 8 deletions

View File

@ -33,8 +33,18 @@ public class ButtonUpDrag: MonoBehaviour, IPointerDownHandler, IPointerUpHandler
public OnLongPressCancel onLongPressCancel;
public OnClick onClick;
/// <summary>
/// 在 InputManager 判定触点已抬起且本组件曾处于按下时调用(与 Unity OnPointerUp 可能不同步,避免误触)。
/// </summary>
private Action onPressEndedByInput;
private Vector2 _startPos;
private Vector2 _curPos;
/// <summary>
/// 非空时:仅当触点移出该 Rect 的屏幕范围才取消长按;为空时沿用 MinDelta 位移判定。
/// </summary>
private RectTransform _longPressCancelBounds;
public void AddPointerUp(Action action)
{
@ -72,6 +82,16 @@ public class ButtonUpDrag: MonoBehaviour, IPointerDownHandler, IPointerUpHandler
action?.Invoke();
};
}
public void SetLongPressCancelBounds(RectTransform bounds)
{
_longPressCancelBounds = bounds;
}
public void AddPressEndedByInput(Action action)
{
onPressEndedByInput += action;
}
public void AddUpDrag(Action action)
{
@ -141,20 +161,21 @@ public class ButtonUpDrag: MonoBehaviour, IPointerDownHandler, IPointerUpHandler
//长按
if (_bLongPress)
{
var disSqr = (_curPos - _startPos).sqrMagnitude;
if (disSqr > MinDelta)
bool cancelByBounds = _longPressCancelBounds != null &&
!IsScreenPointInsideRect(_longPressCancelBounds, _curPos);
bool cancelByDelta = _longPressCancelBounds == null &&
(_curPos - _startPos).sqrMagnitude > MinDelta;
if (cancelByBounds || cancelByDelta)
{
_bLongPress = false;
_bOnClick = false;
onLongPressCancel?.Invoke();
}
else
else if (_pressedTime > MinLongPressTime)
{
if (_pressedTime > MinLongPressTime)
{
onLongPress?.Invoke();
_bLongPress = false;
}
onLongPress?.Invoke();
_bLongPress = false;
}
}
@ -192,6 +213,7 @@ public class ButtonUpDrag: MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
if (_isPressed)
{
onPressEndedByInput?.Invoke();
_isPressed = false;
_bLongPress = true;
_bUpDrag = true;
@ -205,5 +227,16 @@ public class ButtonUpDrag: MonoBehaviour, IPointerDownHandler, IPointerUpHandler
onPointUp = null;
onClick = null;
onUpDrag = null;
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);
}
}

View File

@ -80,6 +80,9 @@ public class DirectDragHandler : MonoBehaviour
/// </summary>
private bool isDraggableEnabled = true;
/// <summary>是否处于长按已触发后的拖拽中(供外部与 ScrollRect 锁定等逻辑配合)。</summary>
public bool IsDragging => isDragging;
private void Awake()
{
rectTransform = GetComponent<RectTransform>();
@ -149,6 +152,15 @@ public class DirectDragHandler : MonoBehaviour
this.onCancelLongPress = cancelLongPress;
}
/// <summary>
/// 长按蓄力阶段:触点移出该 Rect 的屏幕范围时取消长按(由 ButtonUpDrag 处理)。
/// </summary>
public void SetLongPressCancelBounds(RectTransform bounds)
{
if (buttonUpDrag != null)
buttonUpDrag.SetLongPressCancelBounds(bounds);
}
/// <summary>
/// 启用或禁用拖拽功能
/// </summary>