目录
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;
///
/// 我的自定义Button,继承 Button
///
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 长按
///
/// 处理长按
///
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一样)
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
{
///
/// 自己重写的 Button 按钮
/// 1、单击
/// 2、双击
/// 3、长按
///
public class MyButtonXAN : Selectable, IPointerClickHandler, ISubmitHandler
{
[Serializable]
///
/// Function definition for a button click event.
///
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]
///
/// Function definition for a button click event.
///
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;
}
}
}