291 lines
7.2 KiB
C#
291 lines
7.2 KiB
C#
using System;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
using UnityEngine.EventSystems;
|
||
|
||
|
||
public class UIButtonEx: Button
|
||
{
|
||
private Button m_button;
|
||
|
||
private enum DragState
|
||
{
|
||
None,
|
||
Dragging,
|
||
End
|
||
}
|
||
|
||
private bool _isPressed;
|
||
private float _pressedTime;
|
||
private bool _isCalled = false;
|
||
private bool _isLongPressing;
|
||
private bool _upDragCalled;
|
||
private bool _outDragCalled;
|
||
private DragState _curDragState;
|
||
private Vector2 _mousePos;
|
||
private Vector2 _lastFrameMousePos;
|
||
private Vector2 _startDragPos;
|
||
|
||
private bool _isDraggingUp;
|
||
|
||
private const float MAX_PRESSED_TIME = 0.35f;
|
||
private const float MIN_PRESSED_TIME = 0.15f;
|
||
private const float MIN_DRAG_DISTANCE = 10f;
|
||
private const float MIN_UP_DRAG_DIS = 40f;
|
||
|
||
public delegate void OnLongPressCall();
|
||
|
||
public delegate void OnPointUpCall();
|
||
|
||
public delegate void OnStartDrag();
|
||
public delegate void OnDraging();
|
||
public delegate void OnEndDrag();
|
||
public delegate void OnUpDrag(); //向上拖动
|
||
|
||
public delegate void OnDragOut(); //向外拖动
|
||
|
||
public delegate void OnClick();
|
||
|
||
private OnLongPressCall _OnLongPress;
|
||
private OnPointUpCall _OnPointUp; //长按后抬起
|
||
private OnStartDrag _OnStartDrag;
|
||
private OnDraging _OnDrag;
|
||
private OnEndDrag _OnEndDrag;
|
||
private OnUpDrag _OnUpDrag;
|
||
private OnDragOut _OnDragOut;
|
||
private OnClick _OnClick;
|
||
|
||
public OnUpDrag UpDrag
|
||
{
|
||
get { return _OnUpDrag; }
|
||
}
|
||
|
||
public OnDragOut DragOut
|
||
{
|
||
get { return _OnDragOut; }
|
||
}
|
||
|
||
public OnPointUpCall PointUp
|
||
{
|
||
get { return _OnPointUp; }
|
||
}
|
||
|
||
//测试代码
|
||
private int _count = 0;
|
||
|
||
protected override void Awake()
|
||
{
|
||
base.Awake();
|
||
|
||
m_button = GetComponent<Button>();
|
||
}
|
||
|
||
void Update()
|
||
{
|
||
if (_isPressed)
|
||
{
|
||
_mousePos = InputManager.Instance.GetTouchPosition();
|
||
_pressedTime += Time.deltaTime;
|
||
|
||
//判断是否进入拖拽
|
||
var distance = Vector2.Distance(_startDragPos, _mousePos);
|
||
|
||
if (!_isLongPressing && distance > MIN_DRAG_DISTANCE && _curDragState == DragState.None)
|
||
{
|
||
_EnterDrag();
|
||
}
|
||
|
||
if (_IsDragging() && _lastFrameMousePos != _mousePos)
|
||
{
|
||
_OnDrag?.Invoke();
|
||
if (!_upDragCalled)
|
||
{
|
||
if(Math.Abs(_startDragPos.y - _mousePos.y) > MIN_UP_DRAG_DIS)
|
||
{
|
||
_OnUpDrag?.Invoke();
|
||
_upDragCalled = true;
|
||
}
|
||
}
|
||
|
||
if (!_outDragCalled)
|
||
{
|
||
if (Vector2.Distance(_startDragPos, _mousePos) > MIN_UP_DRAG_DIS)
|
||
{
|
||
_OnDragOut?.Invoke();
|
||
_outDragCalled = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (_pressedTime > MAX_PRESSED_TIME && !_isCalled && !_IsDragging())
|
||
{
|
||
_isCalled = true;
|
||
_isLongPressing = true;
|
||
_OnLongPress?.Invoke();
|
||
}
|
||
|
||
_lastFrameMousePos = _mousePos;
|
||
|
||
//如果是其他组件的拖动导致提前调用了OnPointerUp
|
||
if (_isDraggingUp)
|
||
{
|
||
if (!_upDragCalled)
|
||
{
|
||
if(Math.Abs(_startDragPos.y - _mousePos.y) > MIN_DRAG_DISTANCE)
|
||
{
|
||
_OnUpDrag?.Invoke();
|
||
_upDragCalled = true;
|
||
}
|
||
}
|
||
|
||
_isDraggingUp = false;
|
||
_isPressed = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
private bool _IsDragging()
|
||
{
|
||
return _curDragState == DragState.Dragging && !_isLongPressing;
|
||
}
|
||
|
||
private void _EnterDrag()
|
||
{
|
||
_curDragState = DragState.Dragging;
|
||
_upDragCalled = false;
|
||
_outDragCalled = false;
|
||
_OnStartDrag?.Invoke();
|
||
}
|
||
|
||
private void _ExitDrag()
|
||
{
|
||
_curDragState = DragState.None;
|
||
_upDragCalled = false;
|
||
_outDragCalled = false;
|
||
_OnEndDrag?.Invoke();
|
||
}
|
||
|
||
//按键放下和抬起
|
||
public override void OnPointerDown(PointerEventData data)
|
||
{
|
||
_pressedTime = 0f;
|
||
_isPressed = true;
|
||
_startDragPos = InputManager.Instance.GetTouchPosition();
|
||
_isLongPressing = false;
|
||
_upDragCalled = false;
|
||
}
|
||
|
||
public override void OnPointerUp(PointerEventData data)
|
||
{
|
||
if ((_pressedTime > MIN_PRESSED_TIME && _pressedTime < MAX_PRESSED_TIME || _IsDragging()) && !_isLongPressing)
|
||
{
|
||
_OnPointUp?.Invoke();
|
||
}
|
||
else if(_pressedTime > 0)
|
||
{
|
||
_OnClick?.Invoke();
|
||
}
|
||
|
||
if (!data.dragging)
|
||
{
|
||
if (_IsDragging())
|
||
{
|
||
_ExitDrag();
|
||
}
|
||
|
||
_pressedTime = 0f;
|
||
_isPressed = false;
|
||
_isCalled = false;
|
||
_isLongPressing = false;
|
||
_upDragCalled = false;
|
||
_outDragCalled = false;
|
||
_isDraggingUp = false;
|
||
}
|
||
else
|
||
{
|
||
_pressedTime = 0f;
|
||
//_isPressed = false;
|
||
_isCalled = false;
|
||
_isLongPressing = false;
|
||
//_upDragCalled = false;
|
||
_outDragCalled = false;
|
||
_isDraggingUp = true;
|
||
}
|
||
|
||
// _pressedTime = 0f;
|
||
// _isPressed = false;
|
||
// _isCalled = false;
|
||
// _isLongPressing = false;
|
||
// _upDragCalled = false;
|
||
// _outDragCalled = false;
|
||
}
|
||
|
||
//添加事件监听回调,外部调用接口
|
||
public void AddLongPressListener(OnLongPressCall func)
|
||
{
|
||
_OnLongPress += func;
|
||
}
|
||
|
||
public void AddPointUpListener(OnPointUpCall func)
|
||
{
|
||
_OnPointUp += func;
|
||
}
|
||
|
||
public void AddUpDragListener(OnUpDrag func)
|
||
{
|
||
_OnUpDrag += func;
|
||
}
|
||
|
||
public void AddOutDragListener(OnDragOut func)
|
||
{
|
||
_OnDragOut += func;
|
||
}
|
||
|
||
public void AddStartDragListener(OnStartDrag func)
|
||
{
|
||
_OnStartDrag += func;
|
||
}
|
||
|
||
public void AddOnDragListener(OnDraging func)
|
||
{
|
||
_OnDrag += func;
|
||
}
|
||
|
||
public void AddEndDragListener(OnEndDrag func)
|
||
{
|
||
_OnEndDrag += func;
|
||
}
|
||
|
||
public void AddClickListener(OnClick func)
|
||
{
|
||
_OnClick += func;
|
||
}
|
||
|
||
//移除事件绑定接口,外部调用
|
||
public void RemoveAllListener()
|
||
{
|
||
if (m_button)
|
||
{
|
||
m_button.onClick.RemoveAllListeners();
|
||
}
|
||
|
||
// Delegate[] onLongPressList = OnLongPress.GetInvocationList();
|
||
// Delegate[] onPointUpList = OnPointUp.GetInvocationList();
|
||
// foreach (var deleg in onLongPressList)
|
||
// {
|
||
// OnLongPress -= deleg as OnLongPressCall;
|
||
// }
|
||
// foreach (var deleg in onPointUpList)
|
||
// {
|
||
// OnPointUp -= deleg as OnPointUpCall;
|
||
// }
|
||
}
|
||
|
||
public void RemoveListener<T>(T call)
|
||
{
|
||
if (call is OnLongPressCall pressCall)
|
||
{
|
||
_OnLongPress -= pressCall;
|
||
}
|
||
}
|
||
} |