I’m trying to create a list of players that can be re-ordered. I was using the basic ScrollRect to get the basic scrolling for the list if it goes off the screen. Then on the right side of the player there is a Button that if you click and hold, it will move the player up or down to be able to reorder the list of players. I’m using OnPointerDown to trigger that. Unfortunately, it seems that if the Button is a child of the ScrollRect, the OnPointerDown triggers properly but as soon as I move my mouse, the OnPointerUp triggers as well. I’ve only tested it with the mouse but if my Button is outside the ScrollRect, it works perfectly (albeit without the ScrollRect functionality I want). Inside the ScrollRect, it’s broken. I’ve even tried programmably removing and re-adding the ScrollRect Component and it still doesn’t work.
I have similar problem… It’s impossible to click button by finger on touch screen if button is child of scrollrect because button moves at this moment and loses focus.
Basically when we start a drag you can register an interface for callback to fetch the DragThreshold (default for all dragging is 5 pixels, overridden and customizable in ScrollRect @ 15).
Hello folks, I’d just like to drop my homebrew solution for this issue.
When the pointer begins, you climb up the transform parent tree and find the first active scroll rect.
(If none is found then the solution falls through without interference.)
You then cache the scroll rect and disable the component.
When your pointer leaves or finishes you re-enable the scroll rect and dump your reference.
Simple as pie, I hope you can repurpose the code or concept for your particular scenario.
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class ScrollFix : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler
{
////////////////////////////////
private ScrollRect m_parentScrollRect;
////////////////////////////////
public void OnPointerDown(PointerEventData eventData)
{
Transform query = this.transform;
do
{
this.m_parentScrollRect = query.GetComponent<ScrollRect>();
if ((null != this.m_parentScrollRect) && this.m_parentScrollRect && this.m_parentScrollRect.enabled)
{
break;
}
query = query.parent;
}
while ((null != query) && query && (null != query.parent) && query.parent);
if ((null != this.m_parentScrollRect) && this.m_parentScrollRect)
{
this.m_parentScrollRect.enabled = false;
}
return;
}
////////////////////////////////
public void OnPointerUp(PointerEventData eventData)
{
this.OnPointerExit(eventData);
return;
}
////////////////////////////////
public void OnPointerExit(PointerEventData eventData)
{
if ((null != this.m_parentScrollRect) && this.m_parentScrollRect)
{
this.m_parentScrollRect.enabled = true;
// This is for Touch based input, ScrollRect needs to be notified for elastic movement.
this.m_parentScrollRect.OnEndDrag(eventData);
this.m_parentScrollRect = null;
}
return;
}
////////////////////////////////
}
Thanks for this, and I’m from the future (unity 2019.4.20)…
I had problem with holding down cards to trigger an event, the cards are in a scroll rect obviously so it’s nearly impossible to not trigger a OnPointerUp with a finger, your solution works with me.