国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Unity 單擊、雙擊、長按事件處理

這篇具有很好參考價(jià)值的文章主要介紹了Unity 單擊、雙擊、長按事件處理。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

需求

想要一個(gè)工具,能夠同時(shí)集成單擊、雙擊、長按的功能

思路

通過IPointerDownHandler, IPointerUpHandler, IPointerClickHandler這三個(gè)接口就可以監(jiān)聽點(diǎn)擊狀態(tài),然后再通過不同的點(diǎn)擊狀態(tài)來處理相應(yīng)的事件

遇到的問題

  • 由于可能同時(shí)存在多個(gè)事件,實(shí)際開發(fā)過程中會(huì)出現(xiàn)多余事件通知,如下:
    • 同時(shí)擁有單擊和雙擊事件,點(diǎn)擊雙擊的同時(shí)會(huì)響應(yīng)兩次單擊
    • 同時(shí)擁有單擊事件和長按事件時(shí),當(dāng)長按事件響應(yīng)的時(shí)候會(huì)同時(shí)響應(yīng)單擊事件
    • 同時(shí)擁有單擊雙擊和長按事件時(shí)點(diǎn)擊雙擊時(shí)會(huì)同時(shí)響應(yīng)兩次單擊,長按事件響應(yīng)時(shí)會(huì)同時(shí)響應(yīng)單擊事件

解決問題

  • 由于我們無法預(yù)測用戶的具體行為,所以當(dāng)需要響應(yīng)單擊事件時(shí),檢測其他事件有沒有在安全時(shí)效內(nèi)的檢測體,例如,單擊響應(yīng)的時(shí)候如果有其他事件正在檢測過程中我們忽略這次的事件響應(yīng),并把事件存起來,等待所有事件的安全時(shí)效結(jié)束時(shí)響應(yīng)這次單擊事件?;蛘呤堑却^程中有其他事件成功響應(yīng)那么我們就舍棄這次的單擊事件而響應(yīng)對應(yīng)的雙擊或者長按事件。那么這樣就完美解決了上述所有問題。

具體代碼如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-512392.html

ClickEvent

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()) //有正在運(yùn)行的事件檢測單擊事件滯后分發(fā)
                    {
                        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;
            }
        }
    }

Buttons

 //單擊按鈕
    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();
        }
    }

GameObjectExpand

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;
//點(diǎn)擊事件注冊
uiObj.OnClick(() =>
{
    Debug.Log("OnClick");
});
//雙擊事件注冊
uiObj.OnDoubleClick(() =>
{
    Debug.Log("OnDoubleClick");
});
//長按事件注冊
uiObj.OnPress(() =>
{
    Debug.Log("OnPress");
});

到了這里,關(guān)于Unity 單擊、雙擊、長按事件處理的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 按鍵狀態(tài)機(jī)(實(shí)現(xiàn)單擊,長按,雙擊)的模塊分享

    按鍵狀態(tài)機(jī)(實(shí)現(xiàn)單擊,長按,雙擊)的模塊分享

    目錄 一、相關(guān)說明 二、分析 三、模塊代碼 三、代碼講解 四、作者的話 ??????? 1.需要的資源:一個(gè)定時(shí)器,一個(gè)按鍵。 ??????? 2.相關(guān)設(shè)置:利用定時(shí)器計(jì)時(shí)中斷,10ms進(jìn)行一次按鍵掃描。 ??????? 3.使用說明:定時(shí)器中斷的優(yōu)先級要設(shè)置高一點(diǎn),相關(guān)的宏定義可以

    2024年02月07日
    瀏覽(87)
  • STM32獨(dú)立按鍵實(shí)現(xiàn)單擊雙擊長按功能

    目錄 前言 一、按鍵功能定義 二、使用步驟 1.按鍵初始化 2.按鍵掃描函數(shù)(重點(diǎn)) 總結(jié) 在使用STM32或其他單片機(jī)開發(fā)項(xiàng)目時(shí),經(jīng)常需要用到獨(dú)立按鍵進(jìn)行控制。 通常一個(gè)獨(dú)立按鍵需要使用一個(gè)IO口,如果項(xiàng)目需要按鍵實(shí)現(xiàn)多個(gè)功能,往往需要使用到多個(gè)按鍵,需要使用到多個(gè)

    2023年04月17日
    瀏覽(90)
  • 「Python|Selenium|場景案例」如何模擬鼠標(biāo)單擊、雙擊、右擊、長按和拖拽等操作?

    「Python|Selenium|場景案例」如何模擬鼠標(biāo)單擊、雙擊、右擊、長按和拖拽等操作?

    本文主要介紹如何在使用selenium進(jìn)行自動(dòng)化測試的時(shí)候模擬各種鼠標(biāo)操作。 在進(jìn)行自動(dòng)化測試的時(shí)候,我們可能會(huì)需要需要進(jìn)行鼠標(biāo)操作的場景,比如: 測試右擊,查看是否網(wǎng)頁是否屏蔽了右鍵菜單 面對滑塊式登錄驗(yàn)證方式,模擬拖拽 模擬前進(jìn)或后退等鼠標(biāo)擴(kuò)展操作 ……

    2023年04月08日
    瀏覽(31)
  • 【藍(lán)橋杯嵌入式】定時(shí)器實(shí)現(xiàn)按鍵單擊,雙擊,消抖以及長按的代碼實(shí)現(xiàn)

    【藍(lán)橋杯嵌入式】定時(shí)器實(shí)現(xiàn)按鍵單擊,雙擊,消抖以及長按的代碼實(shí)現(xiàn)

    ??【藍(lán)橋杯嵌入式】專題正在持續(xù)更新中,原理圖解析?,各模塊分析?以及歷年真題講解?都在這兒哦,歡迎大家前往訂閱本專題,獲取更多詳細(xì)信息哦?????? ??本系列專欄 - ?藍(lán)橋杯嵌入式_勾欄聽曲_0的博客 ??歡迎大家 ??? ?點(diǎn)贊?? ?評論?? ?收藏?? ??個(gè)人主

    2024年01月17日
    瀏覽(20)
  • antd table的單擊事件和雙擊事件沖突

    問題:當(dāng)table上同時(shí)有onClick和onDoubleClick時(shí),雙擊會(huì)一直觸發(fā)單擊事件。 解決方法:使用延遲定時(shí)器-setTimeout ??????????????????單擊事件延遲執(zhí)行,如果檢測到連續(xù)點(diǎn)擊,則是雙擊事件,不再執(zhí)行單擊事件。 代碼實(shí)現(xiàn):

    2024年01月25日
    瀏覽(84)
  • 微信小程序長按與單擊事件觸發(fā)

    方式一 wxml 片段 js 片段 解析 tap 觸摸事件采用 catch 阻止事件冒泡 1.5.0之后支持 longpress 事件,手指觸摸后,超過350ms再離開,如果指定了事件回調(diào)函數(shù)并觸發(fā)了這個(gè)事件,tap事件將不被觸發(fā) 方式二(不推薦) longtap 事件,但在觸發(fā)時(shí)會(huì)同時(shí)觸發(fā)單擊事件,需配合 touchstart 和

    2024年02月12日
    瀏覽(21)
  • 小程序更多的手勢事件(左右滑動(dòng)、放大縮小、雙擊、長按)

    小程序更多的手勢事件(左右滑動(dòng)、放大縮小、雙擊、長按)

    微信小程序提供的原生事件有:觸摸開始(bindtouchstart)、移動(dòng)觸摸點(diǎn)(bindtouchmove)、觸摸結(jié)束(bindtouchend)以及長按事件(bindlongtap)和單擊事件(bindtap)。通過以上原生事件可設(shè)計(jì)制作衍生出更多的手勢事件; 文章記錄小程序中組件 “左右滑動(dòng)、放大縮小、雙擊” 事件

    2024年02月09日
    瀏覽(18)
  • 【RuoYi移動(dòng)端】uni-app中的單擊和雙擊事件

    ?@click=\\\"enterpriseSelect\\\" ?@touchend=\\\"userinfo\\\"

    2024年02月08日
    瀏覽(20)
  • [Unity案例]Button的雙擊和長按

    [Unity案例]Button的雙擊和長按

    實(shí)現(xiàn)內(nèi)容: 擴(kuò)展Unity自帶的Button組件,在原有的單擊事件的基礎(chǔ)上實(shí)現(xiàn)雙擊和長按效果; 替換Button組件,通過單選框選擇當(dāng)前執(zhí)行哪一種事件 代碼詳解: 單擊事件處理: 通過 singleClickEnabled 開關(guān)控制是否啟用單擊事件。 在 OnPointerClick 方法中,根據(jù)按鈕的激活狀態(tài)和可交互

    2024年04月26日
    瀏覽(24)
  • Unity3D實(shí)現(xiàn)UI的單擊、雙擊、拖動(dòng)狀態(tài)判斷

    Unity3D實(shí)現(xiàn)UI的單擊、雙擊、拖動(dòng)狀態(tài)判斷

    這篇文章就來實(shí)現(xiàn)UI的單擊、雙擊、按壓、拖動(dòng)的不同狀態(tài)判斷。不定時(shí)更新Unity開發(fā)技巧,覺得有用記得一鍵三連哦。 示例、 判斷單擊和雙擊,主要是判斷點(diǎn)擊的次數(shù)。 UI的點(diǎn)擊事件,需要繼承UI的點(diǎn)擊事件接口,重寫點(diǎn)擊事件即可。 UI點(diǎn)擊事件接口: 3-1-1 所引用的命名空

    2024年01月20日
    瀏覽(95)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包