UGUI源代码之Button—长按按钮

以下内容是根据Unity 2020.1.01f版本进行编写的

UGUI源代码之Button—长按按钮

1、目的

长按按钮应该是很常见也很实用的一个功能了吧,今天我们就来实现这个功能

2、参考

本文参考Unity官方的UGUI源代码
Github地址:https://github.com/Unity-Technologies/uGUI

3、代码阅读

查看Button源代码(部分):

public class Button : 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 Button()
{}
……
}

Button类中继承了Selectable类,增加的只有一个ButtonClickedEvent事件

跳转到Selectable类:

public virtual void OnPointerDown(PointerEventData eventData)
{
    if (eventData.button != PointerEventData.InputButton.Left)
        return;

    // Selection tracking
    if (IsInteractable() && navigation.mode != Navigation.Mode.None && EventSystem.current != null)
        EventSystem.current.SetSelectedGameObject(gameObject, eventData);

    isPointerDown = true;
    EvaluateAndTransitionToSelectionState();
}

public virtual void OnPointerUp(PointerEventData eventData)
{
    if (eventData.button != PointerEventData.InputButton.Left)
        return;

    isPointerDown = false;
    EvaluateAndTransitionToSelectionState();
}

其中,有两个函数OnPointerDown和OnPointerUp,其在鼠标按下和抬起时触发,有这么两个可以override的函数就可以实现按钮长按功能了

4、准备修改UGUI源代码


请看这篇:UGUI源代码之修改源代码的前期准备

已经准备过的同学可以跳过

5、自定义实现长按按钮

这个长按按钮并不复杂,在这里我直接把整段代码复制过来:

using UnityEngine.EventSystems;
using UnityEngine.UI;
using static UnityEngine.UI.Button;

public class LongPressedButton : Selectable
{
    public int frames = 120;
    public ButtonClickedEvent onClick = new ButtonClickedEvent();
    public ButtonClickedEvent onLongPressBegin = new ButtonClickedEvent();
    public ButtonClickedEvent onLongPress = new ButtonClickedEvent();
    public ButtonClickedEvent onLongPressEnd = new ButtonClickedEvent();

    private int timer = 0;
    private bool isDown = false;
    private bool isLongPress = false;
    private bool hasLongPressStart = false;

    public override void OnPointerDown(PointerEventData eventData)
    {                
        if (!isDown && !isLongPress)
        {
            isDown = true;
        }
    }

    public override void OnPointerUp(PointerEventData eventData)
    {
        if(!isLongPress)
        {
            // Selection tracking
            if (IsInteractable() && navigation.mode != Navigation.Mode.None && EventSystem.current != null)
                EventSystem.current.SetSelectedGameObject(gameObject, eventData);
            onClick.Invoke();
        }
        else
        {
            onLongPressEnd.Invoke();
        }
        isDown = false;
        isLongPress = false;
        hasLongPressStart = false;
        timer = 0;
    }

    protected override void Start()
    {
        timer = 0;
        isDown = false;
        isLongPress = false;
        hasLongPressStart = false;
    }

    void Update()
    {
        if(isDown)
        {
            timer++;
            if(timer >= frames)
            {
                isLongPress = true;
                if(!hasLongPressStart)
                {
                    hasLongPressStart = true;
                    onLongPressBegin.Invoke();
                }
                onLongPress.Invoke();
            }
        }
    }
}

frames是控制按钮需要长按多少帧才触发长按的属性
isDown判断是否按下按钮
isLongPress判断是否长按按钮,如果长按的帧数大于设置的帧数,则isLongPress属性为true
hasLongPressStart判断是否执行过一次的开始长按事件,执行过后此属性为false,控制一次长按事件中开始长按事件只触发一次
代码逻辑比较简单,就是增加了4个事件,分别对应点击、长按开始、正在长按、长按结束4个事件
OnPointerDown函数设置isDown为true,此时如果一直长按按钮,updata函数中timer会一直增加,当timer帧数大于设置的frames帧数时,设置isLongPress为true,并且通过invoke函数调用onLongPressBegin函数和onLongPress函数,其中,onLongPressBegin函数调用一次后就不会再调用
OnPointerUp函数接受鼠标抬起的动作,如果此时isLongPress为false,则执行OnClick函数,否则执行onLongPressEnd函数,并将属性再次初始化

6、最终效果

UGUI源代码之Button—长按按钮
UGUI源代码之Button—长按按钮

7、项目工程源代码

待补~~



大佬们找到问题欢迎拍砖~

上一篇:Ubuntu+PyQt5+Python3.6+Qt Designer 实现可视化窗口的编辑


下一篇:如何通过易观Argo,免费快速搭起精细化运营平台?