【Unity】UI添加监听事件

1,255 阅读3分钟

UI的点击、拖拽等事件可以用UnityEngine.EventSystems中的接口的方法来实现,或者用已经实现了IPointerEnterHandler、IPointerExitHandler等所有UI事件的类EventTrigger来选择实现。

这里用一个通用类,使用静态方法为UI组件添加EventListener组件,并设置组件的委托方法等,在OnPointerClick等UI方法中实现方法。

1.简单的点击和双击监听

using UnityEngine;
using UnityEngine.EventSystems;

public class UIClickListener : MonoBehaviour, UnityEngine.EventSystems.IPointerClickHandler
{
    public delegate void VoidDelegate(GameObject go, PointerEventData eventData);
    public VoidDelegate mOnPointerClick = null; //单击
    public VoidDelegate mOnDoublePointerClick = null;  //双击

    public void OnPointerClick(PointerEventData eventData)
    {
        if (mOnPointerClick != null && eventData.clickCount == 1)
        {
            mOnPointerClick(gameObject, eventData);
        }

        if (mOnDoublePointerClick != null && eventData.clickCount == 2)
        {
            mOnDoublePointerClick(gameObject, eventData);
        }
    }

    static public UIClickListener Get(GameObject go)
    {
        UIClickListener listener = go.GetComponent<UIClickListener>();
        if (listener == null) listener = go.AddComponent<UIClickListener>();
        return listener;
    }
}

2.包含实现UI全部的点击事件的类,使用委托声明方法,可为GameObject或Transform或其子物体添加

using UnityEngine;
using UnityEngine.EventSystems;

[AddComponentMenu("UIExt/Event Listener")]
public class UIEventListener : UnityEngine.EventSystems.EventTrigger
{
    public delegate void VoidEventDelegate();
    public delegate void VoidDelegate(GameObject go, PointerEventData eventData);
    public delegate void BaseEventDelegate(GameObject go, BaseEventData eventData);
    public delegate void AxisEventDelegate(GameObject go, AxisEventData eventData);
    public delegate void BoolDelegate(GameObject go, bool press);

    public VoidDelegate mOnPointerEnter = null;
    public VoidDelegate mOnPointerExit = null;
    public VoidDelegate mOnPointerDown = null;
    public VoidDelegate mOnPointerUp = null;
    public VoidDelegate mOnPointerClick = null;
    public VoidDelegate mOnDoublePointerClick = null;
    public VoidEventDelegate mOnClick = null;
    public BoolDelegate mOnPress = null;

    public VoidDelegate mOnDrag = null;
    public VoidDelegate mOnDrop = null;
    public VoidDelegate mOnBeginDrag = null;
    public VoidDelegate mOnEndDrag = null;
    public VoidDelegate mOnScroll = null;

    public BaseEventDelegate mOnSelect = null;
    public BaseEventDelegate mOnDeselect = null;

    public AxisEventDelegate mOnMove = null;
    public BaseEventDelegate mOnUpdateSelected = null;
    public VoidDelegate mOnInitializePotentialDrag = null;

    public BaseEventDelegate mOnSubmit = null;
    public BaseEventDelegate mOnCancel = null;

    override public void OnPointerEnter(PointerEventData eventData)
    {
        if (mOnPointerEnter != null)
        {
            mOnPointerEnter(gameObject, eventData);
        }
    }

    override public void OnPointerExit(PointerEventData eventData)
    {
        if (mOnPointerExit != null)
        {
            mOnPointerExit(gameObject, eventData);
        }
    }

    override public void OnPointerDown(PointerEventData eventData)
    {
        if (mOnPointerDown != null)
        {
            mOnPointerDown(gameObject, eventData);
        }

        if (mOnPress != null)
        {
            mOnPress(gameObject, true);
        }
    }

    override public void OnPointerUp(PointerEventData eventData)
    {
        if (mOnPointerUp != null)
        {
            mOnPointerUp(gameObject, eventData);
        }

        if (mOnPress != null)
        {
            mOnPress(gameObject, false);
        }
    }

    override public void OnPointerClick(PointerEventData eventData)
    {
        if (mOnPointerClick != null && eventData.clickCount == 1)
        {
            mOnPointerClick(gameObject, eventData);
        }

        if (mOnDoublePointerClick != null && eventData.clickCount == 2)
        {
            mOnDoublePointerClick(gameObject, eventData);
        }

        if (mOnClick != null)
        {
            mOnClick();
        }
    }

    override public void OnDrag(PointerEventData eventData)
    {
        if (mOnDrag != null)
        {
            mOnDrag(gameObject, eventData);
        }
    }

    override public void OnBeginDrag(PointerEventData eventData)
    {
        if (mOnBeginDrag != null)
        {
            mOnBeginDrag(gameObject, eventData);
        }
    }

    override public void OnEndDrag(PointerEventData eventData)
    {
        if (mOnEndDrag != null)
        {
            mOnEndDrag(gameObject, eventData);
        }
    }

    override public void OnDrop(PointerEventData eventData)
    {
        if (mOnDrop != null)
        {
            mOnDrop(gameObject, eventData);
        }
    }

    override public void OnScroll(PointerEventData eventData)
    {
        if (mOnScroll != null)
        {
            mOnScroll(gameObject, eventData);
        }
    }

    override public void OnSelect(BaseEventData eventData)
    {
        if (mOnSelect != null)
        {
            mOnSelect(gameObject, eventData);
        }
    }

    override public void OnDeselect(BaseEventData eventData)
    {
        if (mOnDeselect != null)
        {
            mOnDeselect(gameObject, eventData);
        }
    }

    override public void OnUpdateSelected(BaseEventData eventData)
    {
        if (mOnUpdateSelected != null)
        {
            mOnUpdateSelected(gameObject, eventData);
        }
    }

    override public void OnMove(AxisEventData eventData)
    {
        if (mOnMove != null)
        {
            mOnMove(gameObject, eventData);
        }
    }

    override public void OnSubmit(BaseEventData eventData)
    {
        if (mOnSubmit != null)
        {
            mOnSubmit(gameObject, eventData);
        }
    }

    override public void OnCancel(BaseEventData eventData)
    {
        if (mOnCancel != null)
        {
            mOnCancel(gameObject, eventData);
        }
    }

    override public void OnInitializePotentialDrag(PointerEventData eventData)
    {
        if (mOnInitializePotentialDrag != null)
        {
            mOnInitializePotentialDrag(gameObject, eventData);
        }
    }

    static public UIEventListener Get(GameObject go)
    {
        UIEventListener listener = go.GetComponent<UIEventListener>();
        if (listener == null) listener = go.AddComponent<UIEventListener>();
        return listener;
    }

    static public UIEventListener Get(Transform parent, string childName)
    {
        Transform tran = FindChild(parent, childName);
        return Get(tran.gameObject);
    }

    static private Transform FindChild(Transform parent, string childName)
    {
        if (childName.Contains("/"))
        {
            return parent.Find(childName);
        }

        Transform child = parent.Find(childName);
        if (child != null)
        {
            return child;
        }

        Transform[] tranArray = parent.GetComponentsInChildren<Transform>(true);
        for (int i = 0; i < tranArray.Length; ++i)
        {
            Transform tran = tranArray[i];
            if (tran.name == childName)
            {
                return tran;
            }
        }

        return null;
    }
}

3.UI点击事件会出现的问题就是和ScrollRect的拖拽冲突,还有短时间内多次重复点击会使响应慢的事件多次调用,因此要对这两方面做处理

using System;
using System.Linq;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class EventTriggerListener : EventTrigger
{
    public Action<GameObject> OnClickCallback;
    public ScrollRect ScrollRect;
    public bool IsDragging { get; private set; }
    public event Action<GameObject> OnClick;
    public event Action<GameObject> OnClickDown;
    public object[] objects { get; set; }
    public bool IsDelay = true;
    private DateTime clickTime;
    private int clickNums;
    private const float CLICK_DELTATIME = 0.5f;
    private const float CLICK_TIMES = 3;

    public EventTriggerListener Get(Transform transform)
    {
        var listener = transform.GetComponent<EventTriggerListener>();
        if (listener == null) listener = transform.gameObject.AddComponent<EventTriggerListener>();
        if (listener.ScrollRect == null)
            listener.ScrollRect = transform.gameObject.GetComponentsInParent<ScrollRect>(true).FirstOrDefault();
        return listener;
    }

    public static EventTriggerListener Get(GameObject go)
    {
        var listener = go.GetComponent<EventTriggerListener>();
        if (listener == null) listener = go.AddComponent<EventTriggerListener>();
        if (listener.ScrollRect == null)
            listener.ScrollRect = go.GetComponentsInParent<ScrollRect>(true).FirstOrDefault();
        return listener;
    }

    public void SetObjects(params object[] args)
    {
        objects = args;
    }

    private void Awake()
    {
        clickTime = DateTime.Now;
    }

    public override void OnPointerClick(PointerEventData eventData)
    {
        base.OnPointerClick(eventData);

        if (IsDragging) return;
        if (IsDelay)
        {
            long ts1 = ConvertDateTimeToShortLong(DateTime.Now) - ConvertDateTimeToShortLong(clickTime);
            if (ts1 > CLICK_DELTATIME)
            {
                clickNums = 0;
                OnClick?.Invoke(gameObject);
                OnClickCallback?.Invoke(gameObject);
            }
            else
            {
                clickNums++;
                if (clickNums > CLICK_TIMES)
                {
                    //TipManager.Instance.Toast("点击太频繁,请稍后再点击");
                }
            }
            clickTime = DateTime.Now;
        }
    }

    public override void OnPointerDown(PointerEventData eventData)
    {
        base.OnPointerDown(eventData);
        if (IsDragging) return;
        OnClickDown?.Invoke(gameObject);
    }

    public override void OnBeginDrag(PointerEventData eventData)
    {
        IsDragging = true;
        if (ScrollRect == null) return;
        ScrollRect.OnBeginDrag(eventData);
    }

    public override void OnDrag(PointerEventData eventData)
    {
        IsDragging = true;
        if (ScrollRect == null) return;
        ScrollRect.OnDrag(eventData);
    }

    public override void OnEndDrag(PointerEventData eventData)
    {
        IsDragging = false;
        if (ScrollRect == null) return;
        ScrollRect.OnEndDrag(eventData);
    }
        public long ConvertDateTimeToShortLong(DateTime dt)
        {
            var dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            var toNow = dt.Subtract(dtStart);
            var timeStamp = toNow.Ticks;
            timeStamp = long.Parse(timeStamp.ToString().Substring(0, timeStamp.ToString().Length - 7));
            return timeStamp;
        }

}

如未注明 , 均为原创丨欢迎转载,转载请注明原文链接。