[Unity案例]Button的双击和长按

实现内容:

扩展Unity自带的Button组件,在原有的单击事件的基础上实现双击和长按效果;

替换Button组件,通过单选框选择当前执行哪一种事件
替换Button组件,通过单选框选择当前执行哪一种事件

代码详解:

  1. 单击事件处理:
    • 通过singleClickEnabled开关控制是否启用单击事件。
    • OnPointerClick方法中,根据按钮的激活状态和可交互状态执行单击事件。
    • 使用Unity的Profiler API添加标记,并触发按钮的单击事件回调。
  2. 双击事件处理:
    • 通过doubleClickEnabled开关控制是否启用双击事件。
    • OnPointerClick方法中,记录点击次数,并根据双击时间阈值判断是否触发双击事件。
    • 如果检测到双击,添加Profiler标记,触发双击事件回调,并重置点击计数。
  3. 长按事件处理:
    • 通过longPressEnabled开关控制是否启用长按事件。
    • OnPointerDown方法中,记录按下时间,并标记长按状态。
    • OnPointerUp方法中,重置长按状态。
    • 使用Update方法定期检测长按,如果达到长按时间阈值,则触发长按事件回调。
  4. 事件回调:
    • 使用ButtonClickedEvent类型的事件回调,可在Inspector中配置。
    • 提供了单击、双击和长按的事件回调,可通过Inspector或代码设置。

完整代码如下:

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

public class ButtonExtension : Button
{
    #region 单机双击相关

    public bool singleClickEnabled = true;
    public bool doubleClickEnabled = false;
    public float doubleClickTime = 0.3f;
    
    private float lastClickTime = float.NegativeInfinity;
    private int clickCount = 0;
    
    [FormerlySerializedAs("onDoubleClick")]
    [SerializeField]
    private ButtonClickedEvent doubleClickEvent = new ();
    
    public ButtonClickedEvent onDoubleClick
    {
        get => doubleClickEvent;
        set => doubleClickEvent = value;
    }

    public override void OnPointerClick(PointerEventData eventData)
    {
        if(!IsActive() && !interactable) 
            return;

        if (singleClickEnabled)
        {
            UISystemProfilerApi.AddMarker("Button.onClick", this);
            onClick?.Invoke();
            Debug.LogError("单击");   
        }

        if (doubleClickEnabled)
        {
            clickCount++;
            if (clickCount >= 2)
            {
                if (Time.realtimeSinceStartup - lastClickTime < doubleClickTime)
                {
                    UISystemProfilerApi.AddMarker("Button.onDoubleClick", this);
                    onDoubleClick?.Invoke();
                    Debug.LogError("双击");
                    lastClickTime = float.NegativeInfinity;
                    clickCount = 0;   
                }
                else
                {
                    clickCount = 1;
                    lastClickTime = Time.unscaledTime;
                }
            }
            else
            {
                lastClickTime = Time.unscaledTime;
            }
        }
    }

    #endregion

    #region 长按相关

    public bool longPressEnabled = false;

    private float lastPressTime = 0;
    
    public float minPressTime = 0.5f;

    private bool isPressing = false;
    
    private bool hasInvokedLongPress = false;

    [FormerlySerializedAs("onLongPress")]
    [SerializeField]
    private ButtonClickedEvent longPressEvent = new();
    
    public ButtonClickedEvent onLongPress
    {
        get => longPressEvent;
        set => longPressEvent = value;
    }
    
    public override void OnPointerDown(PointerEventData eventData)
    {
        base.OnPointerDown(eventData);
        if (longPressEnabled)
        {
            hasInvokedLongPress = false;
            isPressing = true;
            lastPressTime = Time.unscaledTime;   
        }
    }

    public override void OnPointerUp(PointerEventData eventData)
    {
        base.OnPointerUp(eventData);
        isPressing = false;
        hasInvokedLongPress = false;
    }

    private void Update()
    {
        DealLongPress();
    }
    
    private void DealLongPress()
    {
        if(hasInvokedLongPress) return;
        if (isPressing)
        {
            if (Time.unscaledTime - lastPressTime >= minPressTime)
            {
                UISystemProfilerApi.AddMarker("Button.onLongPress", this);
                onLongPress?.Invoke();
                hasInvokedLongPress = true;
                Debug.LogError("执行长按事件");
            }
        }
    }

    #endregion
}

将新增的属性添加到Inspector面板,具体代码如下:

using UnityEngine;

namespace UnityEditor.UI
{
    [CustomEditor(typeof(ButtonExtension), true)]
    [CanEditMultipleObjects]
    public class ButtonExInspector : SelectableEditor
    {
        private ButtonExtension buttonExtension;

        SerializedProperty onDoubleClickProperty;
        SerializedProperty onClickProperty;
        SerializedProperty onLongPressProperty;
        
        protected override void OnEnable()
        {
            base.OnEnable();
            onDoubleClickProperty = serializedObject.FindProperty("doubleClickEvent");
            onClickProperty = serializedObject.FindProperty("m_OnClick");
            onLongPressProperty = serializedObject.FindProperty("longPressEvent");
        }

        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();
            serializedObject.Update();
            buttonExtension = (ButtonExtension)target;
            EditorGUILayout.Space();

            buttonExtension.singleClickEnabled = EditorGUILayout.Toggle("启用单击", buttonExtension.singleClickEnabled);
            if (buttonExtension.singleClickEnabled)
            {
                buttonExtension.doubleClickEnabled = false;
                buttonExtension.longPressEnabled = false;
                EditorGUILayout.PropertyField(onClickProperty);  
            }
            
            buttonExtension.doubleClickEnabled = EditorGUILayout.Toggle("启用双击", buttonExtension.doubleClickEnabled);
            if (buttonExtension.doubleClickEnabled)
            {
                buttonExtension.doubleClickTime = EditorGUILayout.FloatField("双击间隔", buttonExtension.doubleClickTime);
                buttonExtension.singleClickEnabled = false;
                buttonExtension.longPressEnabled = false;
                EditorGUILayout.PropertyField(onDoubleClickProperty);
            }
            
            buttonExtension.longPressEnabled = EditorGUILayout.Toggle("启用长按", buttonExtension.longPressEnabled);
            if(buttonExtension.longPressEnabled)
            {
                buttonExtension.minPressTime = EditorGUILayout.FloatField("长按时间", buttonExtension.minPressTime);
                buttonExtension.singleClickEnabled = false;
                buttonExtension.doubleClickEnabled = false;
                EditorGUILayout.PropertyField(onLongPressProperty);
            }
            
            serializedObject.ApplyModifiedProperties();
            if(GUI.changed)
                EditorUtility.SetDirty(target);
        }
    }   
}


  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值