Unity UGUI 之 实现按钮 Button 长按和双击的功能效果

 

目录

Unity UGUI 之 实现按钮 Button 长按和双击的功能效果

一、简单介绍

二、实现原理

三、注意事项

四、效果预览

五、实现步骤

六、关键代码

七、自己完全重写 Button (面板有 onClick, onLongPress, onDoubleClick 事件添加)


 

一、简单介绍

UGUI,是Unity自带的 GUI 系统,有别于 NGUI;使用 UGUI 也能制作出比较酷炫的效果 。

本节简单介绍实现 UGUI 按钮的 长按功能,以及Double Click 的功能。

 

二、实现原理

1、继承原有的UGUI 的 Button,组件

2、在 Button 的上面实现长按和双击事件

 

三、注意事项

1、长按和双击事件实现和原有的单击事件方法类似(目前不能显示的面板中,估计还有注意什么,知道的朋友可以留言啊(可能是继承 Button 子类已经有 UnityEvent (还是奇怪)),后面脚本有完全重写的Button 中面板有 onClick, onLongPress, onDoubleClick 事件)

2、触发双击的时候,可能总是会触发一次单击事件,顺序是先触发单击事件,之后双击事件触发(尝试了一些方法暂时没有方法在取消双击前的单击,知道的朋友留言哈)

 

四、效果预览

 

五、实现步骤

1、打开Unity,新建空工程

 

2、在场景中,简单布局场景,方便测试

 

3、新建脚本 MuButton,继承 Button,代码实现长按和双击效果的逻辑,并添加一个测试脚本,测试 MyButton 效果

 

4、移除Button 上的Button组件,添加 MyButton

 

5、添加测试脚本 TestMyButton

 

6、运行场景,测试效果如上

 

六、关键代码

1、MyButton.cs

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

/// <summary>
/// 我的自定义Button,继承 Button
/// </summary>
public class MyButton : Button
{
   // 构造函数
    protected MyButton()
    {
        my_onDoubleClick = new ButtonClickedEvent();
        my_onLongPress = new ButtonClickedEvent();
    }

    // 长按
    public ButtonClickedEvent my_onLongPress;
    public ButtonClickedEvent OnLongPress
    {
        get { return my_onLongPress; }
        set { my_onLongPress = value; }
    }

    // 双击
    public ButtonClickedEvent my_onDoubleClick;
    public ButtonClickedEvent OnDoubleClick
    {
        get { return my_onDoubleClick; }
        set { my_onDoubleClick = value; }
    }

    // 长按需要的变量参数
    private bool my_isStartPress = false;
    private float my_curPointDownTime = 0f;
    private float my_longPressTime = 0.6f;
    private bool my_longPressTrigger = false;
  

    void Update()
    {
        CheckIsLongPress();
    }

    #region 长按

    /// <summary>
    /// 处理长按
    /// </summary>
    void CheckIsLongPress() {
        if (my_isStartPress && !my_longPressTrigger)
        {
            if (Time.time > my_curPointDownTime + my_longPressTime)
            {
                my_longPressTrigger = true;
                my_isStartPress = false;
                if (my_onLongPress != null)
                {
                    my_onLongPress.Invoke();
                }
            }
        }
    }

    public override void OnPointerDown(PointerEventData eventData)
    {
        // 按下刷新當前時間
        base.OnPointerDown(eventData);
        my_curPointDownTime = Time.time;
        my_isStartPress = true;
        my_longPressTrigger = false;
    }

    public override void OnPointerUp(PointerEventData eventData)
    {
        // 指針擡起,結束開始長按
        base.OnPointerUp(eventData);
        my_isStartPress = false;
        
    }

    public override void OnPointerExit(PointerEventData eventData)
    {
        // 指針移出,結束開始長按,計時長按標志
        base.OnPointerExit(eventData);
        my_isStartPress = false;
       
    }

    #endregion

    #region 双击(单击)

    public override void OnPointerClick(PointerEventData eventData)
    {
        //(避免已經點擊進入長按后,擡起的情況)
        if (!my_longPressTrigger)
        {
            // 正常單擊 
            if (eventData.clickCount == 2 )
            {
              
                if (my_onDoubleClick != null)
                {
                    my_onDoubleClick.Invoke();
                }
                
            }// 雙擊
            else if (eventData.clickCount == 1)
            {
                onClick.Invoke();
            }
        }
    }
    #endregion


}

 

2、TestMyButton.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestMyButton : MonoBehaviour
{
    public MyButton myButton;

    // Start is called before the first frame update
    void Start()
    {
        myButton.onClick.AddListener(()=> {
            Debug.Log(" myButton.onClick");
        });

        myButton.OnDoubleClick.AddListener(() => {
            Debug.Log(" myButton.OnDoubleClick");
        });

        myButton.OnLongPress.AddListener(() => {
            Debug.Log(" myButton.OnLongPress");
        });
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

 

七、自己完全重写 Button (面板有 onClick, onLongPress, onDoubleClick 事件添加)

(注意:使用方法原有的Button一样)

1、样式

 

2、代码

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
using UnityEngine.Serialization;
using UnityEngine;

namespace XANTools
{
    /// <summary>
    /// 自己重写的 Button 按钮
    /// 1、单击
    /// 2、双击
    /// 3、长按
    /// </summary>    
    public class MyButtonXAN : Selectable, IPointerClickHandler, ISubmitHandler
    {
        [Serializable]
        /// <summary>
        /// Function definition for a button click event.
        /// </summary>
        public class ButtonClickedEvent : UnityEvent { }

        // Event delegates triggered on click.
        [FormerlySerializedAs("onClick")]
        [SerializeField]
        private ButtonClickedEvent m_OnClick = new ButtonClickedEvent();

        protected MyButtonXAN()
        { }

      
        public ButtonClickedEvent onClick
        {
            get { return m_OnClick; }
            set { m_OnClick = value; }
        }

        private void Press()
        {
            if (!IsActive() || !IsInteractable())
                return;

            UISystemProfilerApi.AddMarker("Button.onClick", this);
            m_OnClick.Invoke();
        }


        [Serializable]
        /// <summary>
        /// Function definition for a button click event.
        /// </summary>
        public class ButtonLongPressEvent : UnityEvent { }

        [FormerlySerializedAs("onLongPress")]
        [SerializeField]
        private ButtonLongPressEvent m_onLongPress = new ButtonLongPressEvent();
        public ButtonLongPressEvent onLongPress
        {
            get { return m_onLongPress; }
            set { m_onLongPress = value; }
        }

        [FormerlySerializedAs("OnDoubleClick")]
        public ButtonClickedEvent m_onDoubleClick = new ButtonClickedEvent();
        public ButtonClickedEvent OnDoubleClick
        {
            get { return m_onDoubleClick; }
            set { m_onDoubleClick = value; }
        }

        private bool my_isStartPress = false;

        private float my_curPointDownTime = 0f;

        private float my_longPressTime = 0.6f;

        private bool my_longPressTrigger = false;


        void Update()
        {
            CheckIsLongPress();
        }

        void CheckIsLongPress()
        {
            if (my_isStartPress && !my_longPressTrigger)
            {
                if (Time.time > my_curPointDownTime + my_longPressTime)
                {
                    my_longPressTrigger = true;
                    my_isStartPress = false;
                    if (m_onLongPress != null)
                    {
                        m_onLongPress.Invoke();
                    }
                }
            }
        }



        public virtual void OnPointerClick(PointerEventData eventData)
        {
            //(避免已經點擊進入長按后,擡起的情況)
            if (!my_longPressTrigger)
            {
                // 正常單擊 
                if (eventData.clickCount == 2)
                {

                    if (m_onDoubleClick != null)
                    {
                        m_onDoubleClick.Invoke();
                    }

                }// 雙擊
                else if (eventData.clickCount == 1)
                {
                    onClick.Invoke();
                }
            }
        }

        

        public virtual void OnSubmit(BaseEventData eventData)
        {
            Press();

            // if we get set disabled during the press
            // don't run the coroutine.
            if (!IsActive() || !IsInteractable())
                return;

            DoStateTransition(SelectionState.Pressed, false);
            StartCoroutine(OnFinishSubmit());
        }

        private IEnumerator OnFinishSubmit()
        {
            var fadeTime = colors.fadeDuration;
            var elapsedTime = 0f;

            while (elapsedTime < fadeTime)
            {
                elapsedTime += Time.unscaledDeltaTime;
                yield return null;
            }

            DoStateTransition(currentSelectionState, false);
        }

        public override void OnPointerDown(PointerEventData eventData)
        {
            // 按下刷新當前時間
            base.OnPointerDown(eventData);
            my_curPointDownTime = Time.time;
            my_isStartPress = true;
            my_longPressTrigger = false;
        }

        public override void OnPointerUp(PointerEventData eventData)
        {
            // 指針擡起,結束開始長按
            base.OnPointerUp(eventData);
            my_isStartPress = false;

        }

        public override void OnPointerExit(PointerEventData eventData)
        {
            // 指針移出,結束開始長按,計時長按標志
            base.OnPointerExit(eventData);
            my_isStartPress = false;

        }
    }
}

 

 

 

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐