Unity UGUI中ScrollRect的拖动事件被Event Trigger拦截

这两天在做聊天功能时遇到一个问题,聊天消息内会包含超链接,方便玩家点击后直达相应的窗口或查看相应信息。如下图,点击[打开窗口]就可以弹出此条消息对应的界面。

聊天频道

这个功能我们用的是Event Trigger实现的,一开始我们是这么做的:

一开始的实现方法

将Event Trigger直接挂载在GameObject上,将响应方法绑定到Pointer Click,用传入的eventData来判断是否点击到了超链接,从而实现跳转。这看起来没有任何问题,事实上做起来也没有什么问题,一切都很顺利,直到多条聊天信息将聊天框填满后,问题出现了:当我们不想点击超链接,而是想拖动视图时,发现视图无法拖动。

很快我们意识到是Event Trigger拦截了Scroll Rect的OnDrag事件,由于我们只绑定了Event Trigger的Pointer Click回调,并没有处理OnDrag的回调,而ScrollRect的拖动也是由OnDrag来处理的,因此在Unity看来我们并不需要拖动,只需要处理点击事件即可。那么问题变得简单了,我们只需要写一个脚本,自行处理OnDrag事件,代码很短也很好写,很快我写了以下的这些代码:

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

// EmojiText为我们自己写的图文混排脚本,可根据自己的情况改
[RequireComponent(typeof(EmojiText))]
public class ChatLinkListener : MonoBehaviour, IPointerClickHandler, IDragHandler
{
    public ScrollRect Scroll;
    private EmojiText _emojiText;

    private void Start()
    {
        _emojiText = GetComponent();
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        _emojiText.OnClick(eventData);
    }

    public void OnDrag(PointerEventData eventData)
    {
        Scroll.OnDrag(eventData);
    }
}

将它挂在Event Trigger同级的GameObject下,将ScrollRect的GameObject拖到Scroll上,并取消掉之前Event Trigger绑定的事件,简单!轻松!分分钟的事!


变成这样

然而,这样做却依然存在问题!在实际调试中,我们发现这样做确实可以拖动也可以点击,但由于我们没有实现OnBeginDrag、OnEndDrag这两个事件,对于ScrollRect来说,只有每次在拖动中的时候它才会响应,而在哪开始、在哪结束ScrollRect是完全不知道的,所以在拖动过程中ScrollRect会不断的抖动。并且即便我们将Content拖动到最下方,在松开后再次点击拖动时,ScrollRect会强行滚动到最上方开始重新拖动,因为对ScrollRect来说,由于没有实现OnEndDrag,ScrollRect并不知道最后结束滚动的位置,对它来说它的位置从来没有变过。因此还需要实现OnBeginDrag、OnEndDrag:

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

// EmojiText为我们自己写的图文混排脚本,可根据自己的情况改
[RequireComponent(typeof(EmojiText))]
public class ChatLinkListener : MonoBehaviour, IPointerClickHandler, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    public ScrollRect Scroll;
    private EmojiText _emojiText;

    private void Start()
    {
        _emojiText = GetComponent();
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        _emojiText.OnClick(eventData);
    }

    public void OnDrag(PointerEventData eventData)
    {
        Scroll.OnDrag(eventData);
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        Scroll.OnBeginDrag(eventData);
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        Scroll.OnEndDrag(eventData);
    }
}

到这里就可以实现点击+拖动同时存在的需求。这个功能并不复杂,代码也很简单,但还是有几个需要注意的点容易被忽略,导致效果不够理想。因此,即便是开发简单的需求,依然需要考虑到不同组件间的相互影响,避免由于B需求导致A需求出错,节约排查及修复的时间。

你可能感兴趣的:(Unity UGUI中ScrollRect的拖动事件被Event Trigger拦截)