LongPressBtn.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using Fort23.UTool;
  5. using UnityEngine;
  6. using UnityEngine.EventSystems;
  7. public class LongPressBtn : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler,
  8. IPointerClickHandler, IDragHandler, IBeginDragHandler, IEndDragHandler, IPointerEnterHandler
  9. {
  10. private float _time;
  11. public float startTime = 0.5f;
  12. public float intervalTime = 0.05f;
  13. public Action onClick;
  14. /// <summary>
  15. /// 连按
  16. /// </summary>
  17. public Action longPress;
  18. /// <summary>
  19. /// 长按结束
  20. /// </summary>
  21. public Action longPressEnd;
  22. /// <summary>
  23. /// 是否按下状态
  24. /// </summary>
  25. [HideInInspector] public bool isPressd;
  26. private bool _isTriggerLongPress;
  27. /// <summary>
  28. /// 是否触发了长按
  29. /// </summary>
  30. public bool IsTriggerLongPress => _isTriggerLongPress;
  31. // 拖拽相关变量
  32. private bool _isDragging;
  33. private Vector2 _dragStartPosition;
  34. /// <summary>
  35. /// 拖拽阈值(像素),超过这个距离才认为是拖拽
  36. /// </summary>
  37. public float dragThreshold = 10f;
  38. /// <summary>
  39. /// 拖拽开始事件
  40. /// </summary>
  41. public Action<PointerEventData> onDragStart;
  42. /// <summary>
  43. /// 拖拽进行中事件
  44. /// </summary>
  45. public Action<PointerEventData> onDrag;
  46. /// <summary>
  47. /// 拖拽结束事件
  48. /// </summary>
  49. public Action<PointerEventData> onDragEnd;
  50. public Action<PointerEventData> onPointerEnter;
  51. public Action<PointerEventData> onPointerExit;
  52. void OnPress(bool pressed)
  53. {
  54. if (pressed) // 按下
  55. {
  56. isPressd = true;
  57. _isDragging = false; // 重置拖拽状态
  58. }
  59. else // 松开或离开
  60. {
  61. if (isPressd)
  62. {
  63. if (_isTriggerLongPress && !_isDragging) // 触发了长按且不是拖拽,执行 longPressEnd
  64. {
  65. longPressEnd?.Invoke();
  66. _isTriggerLongPress = false;
  67. }
  68. }
  69. isPressd = false;
  70. _time = 0;
  71. }
  72. }
  73. private void Update()
  74. {
  75. // 如果正在拖拽,不执行长按逻辑
  76. if (_isDragging) return;
  77. if (isPressd && !_isTriggerLongPress)
  78. {
  79. _time += Time.deltaTime;
  80. if (_time >= startTime)
  81. {
  82. _isTriggerLongPress = true;
  83. _time -= intervalTime;
  84. longPress?.Invoke();
  85. }
  86. }
  87. else if (isPressd && _isTriggerLongPress)
  88. {
  89. _time += Time.deltaTime;
  90. if (_time >= intervalTime)
  91. {
  92. _time -= intervalTime;
  93. longPress?.Invoke();
  94. }
  95. }
  96. }
  97. /// <summary>
  98. /// 终止
  99. /// </summary>
  100. public void Terminated()
  101. {
  102. if (isPressd)
  103. {
  104. isPressd = false;
  105. if (_isTriggerLongPress)
  106. {
  107. longPressEnd?.Invoke();
  108. }
  109. _isTriggerLongPress = false;
  110. _time = 0;
  111. }
  112. _isDragging = false; // 同时终止拖拽状态
  113. }
  114. public void OnPointerDown(PointerEventData eventData)
  115. {
  116. _dragStartPosition = eventData.position;
  117. OnPress(true);
  118. }
  119. public void OnPointerUp(PointerEventData eventData)
  120. {
  121. // 如果正在拖拽,先触发拖拽结束
  122. if (_isDragging)
  123. {
  124. OnEndDrag(eventData);
  125. }
  126. OnPress(false);
  127. }
  128. public void OnPointerExit(PointerEventData eventData)
  129. {
  130. onPointerExit?.Invoke(eventData);
  131. // 如果正在拖拽,不处理退出事件(拖拽过程中允许离开按钮区域)
  132. if (!_isDragging)
  133. {
  134. OnPress(false);
  135. }
  136. }
  137. public void OnPointerEnter(PointerEventData eventData)
  138. {
  139. onPointerEnter?.Invoke(eventData);
  140. }
  141. public void OnPointerClick(PointerEventData eventData)
  142. {
  143. // 如果发生了拖拽,不触发点击事件
  144. if (_isDragging || _isTriggerLongPress) return;
  145. onClick?.Invoke();
  146. isPressd = false;
  147. }
  148. // ========== 拖拽相关方法 ==========
  149. public void OnBeginDrag(PointerEventData eventData)
  150. {
  151. // 检查是否达到拖拽阈值
  152. if (Vector2.Distance(eventData.position, _dragStartPosition) >= dragThreshold && !_isDragging)
  153. {
  154. _isDragging = true;
  155. // 开始拖拽时终止长按逻辑
  156. if (_isTriggerLongPress)
  157. {
  158. longPressEnd?.Invoke();
  159. _isTriggerLongPress = false;
  160. }
  161. onDragStart?.Invoke(eventData);
  162. }
  163. }
  164. public void OnDrag(PointerEventData eventData)
  165. {
  166. if (_isDragging)
  167. {
  168. onDrag?.Invoke(eventData);
  169. }
  170. else
  171. {
  172. // 如果还没有正式开始拖拽,检查是否达到阈值
  173. if (Vector2.Distance(eventData.position, _dragStartPosition) >= dragThreshold)
  174. {
  175. OnBeginDrag(eventData);
  176. }
  177. }
  178. }
  179. public void OnEndDrag(PointerEventData eventData)
  180. {
  181. if (_isDragging)
  182. {
  183. onDragEnd?.Invoke(eventData);
  184. _isDragging = false;
  185. }
  186. }
  187. /// <summary>
  188. /// 检查是否正在拖拽
  189. /// </summary>
  190. public bool IsDragging => _isDragging;
  191. /// <summary>
  192. /// 强制结束拖拽
  193. /// </summary>
  194. public void ForceEndDrag()
  195. {
  196. if (_isDragging)
  197. {
  198. _isDragging = false;
  199. onDragEnd?.Invoke(null);
  200. }
  201. }
  202. }