赞
踩
想要一个工具,能够同时集成单击、双击、长按的功能
通过IPointerDownHandler, IPointerUpHandler, IPointerClickHandler这三个接口就可以监听点击状态,然后再通过不同的点击状态来处理相应的事件
具体代码如下:
public class ClickEvent : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerClickHandler
{
private List<IClickListener> listenerList = new List<IClickListener>();
private Dictionary<IClickListener, Action> callBackDict = new Dictionary<IClickListener, Action>();
public void OnPointerDown(PointerEventData eventData)
{
for (int i = listenerList.Count - 1; i >= 0; i--)
{
listenerList[i]?.OnPointerDown(eventData);
}
}
public void OnPointerUp(PointerEventData eventData)
{
for (int i = listenerList.Count - 1; i >= 0; i--)
{
listenerList[i]?.OnPointerUp(eventData);
}
}
public void OnPointerClick(PointerEventData eventData)
{
for (int i = listenerList.Count - 1; i >= 0; i--)
{
listenerList[i]?.OnPointerClick(eventData);
}
}
private void Update()
{
for (int i = listenerList.Count - 1; i >= 0; i--)
{
listenerList[i]?.Update();
}
}
public T Add<T>() where T : ClickListener, new()
{
T t = Get<T>();
if (t == null)
{
t = new T();
(t as IClickListener).OnCallBack((success) => OnReceive(success, t));
if (listenerList.Count == 0 || t is ClickButton) listenerList.Add(t);
else listenerList.Insert(listenerList.Count - 1, t);
}
return t;
}
public void Remove<T>() where T : ClickListener
{
if (!Contains<T>()) return;
T t = Get<T>();
if (callBackDict.ContainsKey(t)) callBackDict.Remove(t);
listenerList.Remove(t);
}
public void RemoveAll()
{
listenerList.Clear();
callBackDict.Clear();
}
public T Get<T>() where T : ClickListener
{
if (listenerList.Count == 0) return default;
IClickListener listener = default;
for (int i = listenerList.Count - 1; i >= 0; i--)
{
listener = listenerList[i];
if (listener is T) return (T) listener;
}
return default;
}
public bool Contains<T>() where T : ClickListener
{
if (listenerList.Count == 0) return false;
IClickListener listener = default;
for (int i = listenerList.Count - 1; i >= 0; i--)
{
listener = listenerList[i];
if (listener is T) return true;
}
return false;
}
public bool ContainsCallBack<T>() where T : ClickListener
{
T t = Get<T>();
if (t == null) return false;
if (callBackDict.ContainsKey(t))
{
if (callBackDict[t] == null)
{
callBackDict.Remove(t);
return false;
}
return true;
}
else return false;
}
public Action GetCallBack<T>() where T : ClickListener
{
T t = Get<T>();
if (t == null) return null;
if (callBackDict.ContainsKey(t))
{
Action callBack = callBackDict[t];
if (callBack == null)
{
callBackDict.Remove(t);
return null;
}
return callBack;
}
else return null;
}
public bool HasRuning()
{
bool isRuning = false;
foreach (var lis in listenerList)
{
if (lis.isRuning)
{
isRuning = true;
break;
}
}
return isRuning;
}
public T OnRegister<T>(Action callBack) where T : ClickListener, new()
{
T t = Add<T>();
if (callBackDict.ContainsKey(t)) callBackDict[t] = callBack;
else callBackDict.Add(t, callBack);
return t;
}
private Action clickCallBack = null;
void OnReceive(bool success, IClickListener listener)
{
if (success)
{
if (listener is ClickButton) //单击事件
{
Action cbk = GetCallBack<ClickButton>();
if (cbk == null) return;
if (HasRuning()) //有正在运行的事件检测单击事件滞后分发
{
clickCallBack = cbk;
}
else
{
clickCallBack = null;
ResetOther();
cbk.Invoke();
}
}
else //其他事件
{
clickCallBack = null;
ResetOther();
if (callBackDict.ContainsKey(listener)) callBackDict[listener]?.Invoke();
}
}
else
{
if (!HasRuning())
{
clickCallBack?.Invoke();
clickCallBack = null;
}
}
void ResetOther()
{
foreach (var btn in listenerList)
{
if (btn != listener) btn?.Reset();
}
}
}
#if UNITY_EDITOR
[UnityEditor.CustomEditor(typeof(ClickEvent))]
class ClickEventInspector : UnityEditor.Editor
{
private ClickEvent clickEvent;
private void OnEnable()
{
clickEvent = target as ClickEvent;
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
GUILayout.Label("ClickListeners: ");
IClickListener listener;
for (int i = clickEvent.listenerList.Count - 1; i >= 0; i--)
{
listener = clickEvent.listenerList[i];
GUILayout.Label(" " + listener);
}
}
}
#endif
private interface IClickListener
{
bool isRuning { get; set; }
void OnPointerDown(PointerEventData eventData);
void OnPointerUp(PointerEventData eventData);
void OnPointerClick(PointerEventData eventData);
void Update();
void OnCallBack(Action<bool> callBack);
void Reset();
void Dispose();
}
public abstract class ClickListener : IClickListener
{
bool IClickListener.isRuning
{
get => isRuning;
set { isRuning = value; }
}
protected bool isRuning = false;
protected Action<bool> callBack { get; private set; }
void IClickListener.OnPointerDown(PointerEventData eventData) => OnPointerDown(eventData);
void IClickListener.OnPointerUp(PointerEventData eventData) => OnPointerUp(eventData);
void IClickListener.OnPointerClick(PointerEventData eventData) => OnPointerClick(eventData);
void IClickListener.Update() => Update();
void IClickListener.Reset() => Reset();
void IClickListener.Dispose() => Dispose();
void IClickListener.OnCallBack(Action<bool> callBack)
{
this.callBack = callBack;
}
protected virtual void OnPointerDown(PointerEventData eventData)
{
}
protected virtual void OnPointerUp(PointerEventData eventData)
{
}
protected virtual void OnPointerClick(PointerEventData eventData)
{
}
protected virtual void Update()
{
}
protected abstract void Reset();
protected virtual void Dispose()
{
callBack = null;
}
}
}
//单击按钮
public class ClickButton : ClickEvent.ClickListener
{
protected override void OnPointerDown(PointerEventData eventData)
{
isRuning = true;
}
protected override void OnPointerUp(PointerEventData eventData)
{
if (isRuning)
{
Reset();
callBack?.Invoke(true);
}
}
protected override void Reset()
{
isRuning = false;
}
}
//双击按钮
public class DoubleClickButton : ClickEvent.ClickListener
{
public int maxSpaceTime = 250;
private int clickCount = 0;
private Stopwatch stopWatch;
private float lastPointTime = 0;
public DoubleClickButton()
{
stopWatch = new Stopwatch();
Reset();
}
protected override void OnPointerDown(PointerEventData eventData)
{
isRuning = true;
}
protected override void OnPointerClick(PointerEventData eventData)
{
stopWatch.Start();
clickCount++;
if (clickCount == 2)
{
Reset();
callBack?.Invoke(true);
}
}
protected override void Update()
{
if (!stopWatch.IsRunning) return;
if (stopWatch.ElapsedMilliseconds > maxSpaceTime)
{
Reset();
callBack?.Invoke(false);
}
}
protected override void Reset()
{
isRuning = false;
if (stopWatch.IsRunning) stopWatch.Stop();
stopWatch.Reset();
clickCount = 0;
}
}
//长按按钮
public class PressButton : ClickEvent.ClickListener
{
public int pressMinTime = 2000;
private Stopwatch stopWatch;
public PressButton()
{
stopWatch = new Stopwatch();
}
protected override void OnPointerDown(PointerEventData eventData)
{
isRuning = true;
stopWatch.Start();
}
protected override void OnPointerUp(PointerEventData eventData)
{
Reset();
callBack?.Invoke(false);
}
protected override void Update()
{
if (!stopWatch.IsRunning) return;
if (stopWatch.ElapsedMilliseconds > pressMinTime)
{
Reset();
callBack?.Invoke(true);
}
}
protected override void Reset()
{
isRuning = false;
if (stopWatch.IsRunning) stopWatch.Stop();
stopWatch.Reset();
}
}
public static class GameObjectExpand
{
public static ClickButton OnClick(this GameObject obj, Action callBack)
{
if (obj == null) return null;
ClickEvent clickEvent = GetClickEvent(obj);
ClickButton button = clickEvent.OnRegister<ClickButton>(callBack);
return button;
}
public static DoubleClickButton OnDoubleClick(this GameObject obj, Action callBack)
{
if (obj == null) return null;
ClickEvent clickEvent = GetClickEvent(obj);
DoubleClickButton button = clickEvent.OnRegister<DoubleClickButton>(callBack);
return button;
}
public static PressButton OnPress(this GameObject obj, Action callBack)
{
if (obj == null) return null;
ClickEvent clickEvent = GetClickEvent(obj);
PressButton button = clickEvent.OnRegister<PressButton>(callBack);
return button;
}
static ClickEvent GetClickEvent(GameObject obj)
{
ClickEvent clickEvent = obj.GetComponent<ClickEvent>();
if (clickEvent == null) clickEvent = obj.AddComponent<ClickEvent>();
return clickEvent;
}
}
public GameObject uiObj;
//点击事件注册
uiObj.OnClick(() =>
{
Debug.Log("OnClick");
});
//双击事件注册
uiObj.OnDoubleClick(() =>
{
Debug.Log("OnDoubleClick");
});
//长按事件注册
uiObj.OnPress(() =>
{
Debug.Log("OnPress");
});
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。