Scroll Rect disable dragging

Is there anyway to disable to click & drag functionality of a scroll rect? I just want it to work with the mouse scroll wheel. I suppose I could just code it myself, but I like the elasticity and scroll bar features.

Inherit from ScrollRect then override the following:
public virtual void OnBeginDrag(PointerEventData eventData);
public virtual void OnDrag(PointerEventData eventData);
public virtual void OnEndDrag(PointerEventData eventData);

Thanks! That wasn’t quite right but it helped me find the solution. Which was inheriting from ScrollRect and then:

public override void OnBeginDrag(PointerEventData eventData) { }
public override void OnDrag(PointerEventData eventData) { }
public override void OnEndDrag(PointerEventData eventData) { }

This post was helpful and I don’t want to necro, but could one of you send me a link on how to inherit from a component in unity? I can’t seem to find a guide anywhere.
PS: I’m a newb :stuck_out_tongue:

Ok so you know how all your scripts start with :

public class MyScript : MonoBehaviour {…

That means it inherits from MonoBehaviour, which is the default in unity (thats why you have access to variables such as “gameObject” or “transform” in your scripts. If you change it to :

public class MyScript : ScrollRect {…

It now inherits from ScrollRect, which means it will have all the funtionality and variables that are defined in ScrollRect (which in turn inherits from MonoBehaviour). But now you have your own “version” of that class and can make adjustments on top of it.

The ScrollRect class has a function “OnDrag” that defines what happens when you drag. If you override this function in your class, the “OnDrag” function in the base ScrollRect class will be ignored, and your function will run instead. In the above case the new function does nothing and thus disables the normal OnDrag behaviour.

Now you can add your new script “MyScript” as a component on your GameObject instead of the regular ScrollRect component and it will act as a regular ScrollRect, but with your adjustments.

Hope that clears it up for you :wink:

5 Likes

Note that you have to add
using UnityEngine.EventSystems;

to your script for this to work, otherwise it doesn’t know about PointerEventData.

So your full script would look like:

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System.Collections;

public class PreventClickDrag : ScrollRect {

    public override void OnBeginDrag(PointerEventData eventData) { }
    public override void OnDrag(PointerEventData eventData) { }
    public override void OnEndDrag(PointerEventData eventData) { }
}
10 Likes

To necro this even further… because it’s one of the first search results on this topic… another way to do this, if you have some content object that wants to handle click/drag (which you probably do, else why not allow the user to scroll the content with the mouse?), is to implement IDragHandler in your content class, and be sure to call eventData.Use().

    public void OnDrag(PointerEventData eventData) {
        // Do whatever drag-handling you need to do, then:
        eventData.Use();
    }
6 Likes

You could disable “Horizontal” or “Vertical” in Scroll Rect component and set Scrollbar component “Interactable” to be false

6 Likes
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System.Collections;

public class NoDragScrollRect : MonoBehaviour, IEndDragHandler, IBeginDragHandler  {

    public ScrollRect EdgesScroll;

    public void OnBeginDrag(PointerEventData data)
    {
        EdgesScroll.StopMovement();
        EdgesScroll.enabled = false;
    }

    public void OnEndDrag(PointerEventData data)
    {
        EdgesScroll.enabled = true;
    }

}
4 Likes

panel.GetComponent().horizontal = false;

3 Likes

Thanks, the 2 custom scripts (PreventClickDrag replacing ScrollRect and NoDragScrollRect as an extra component), as well as unchecking Horizontal/Vertical worked to disable dragging, with the following subtleties:

  1. All solutions are still not perfect regarding button handling: if there is a button in your scrollable content, and you press it, then move the cursor more than a given threshold of distance, the drag event will still be detected (also it will do nothing), cancelling button press; releasing mouse or touch will not register button click. The only workaround I found for this so far is How to disable grab and scroll on UI elements ¡ Issue #32 ¡ ViveSoftware/ViveInputUtility-Unity ¡ GitHub which registers action on mouse press (button down). I have yet to find a solution that preserves true button behaviour on release, even after moving beyond the threshold.
  2. If you choose to uncheck Horizontal/Vertical, you need to set visibility to “Auto Hide” or “Auto Hide and Expand Viewport”. “Permanent” Visibility will make the scrollbar disappear if its corresponding direction is disabled. Which makes sense, but since we’re hacking the Horizontal/Vertical feature to disable dragging, this has side effects. Ideally, we’d want a checkbox specifically to disable dragging!
  3. In addition unchecking Horizontal/Vertical will disable mouse scroll in this direction, so if you need it, it’s not convenient (you’d have to reimplement it manually).

So if you must rely on proper button behaviour and need mouse scroll, you may be better off with a custom solution (just using the Scrollbar component and coding the rest of the behaviour). If you don’t mind the small inconveniences or not use buttons, then you can just use one of those solutions!

Thank you!

The ScrollRect events can be intercepted by adding a script like this

public class ViewportDragHandler : MonoBehaviour, IBeginDragHandler {

    private ScrollRect scrollRect;
    void Awake() {
        this.scrollRect = this.GetComponent<ScrollRect>();
    }

    public void OnBeginDrag(PointerEventData data) {
        // do your stuff here
        this.scrollRect.OnBeginDrag(data); // pass the event to the ScrollRect, if needed
    }

}

What worked for me to disable dragging in a Scroll View is to disable the Horizontal and Vertical checkboxes in the Scroll Rect component and leave the Scrollbar components interactable (in Scrollbar Horizontal and Scrollbar Vertical).

I found disabling the Horizontal and Vertical checkboxes disabled the scroll bars too (they were visible & moved but didn’t have any effect).

I disabled dragging of the scrollview by disabling ‘Raycast Target’ on the image component on the scrollview game object.

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

public class ScrollRectWithoutDrag : ScrollRect {
    public override void OnInitializePotentialDrag(PointerEventData eventData) { }
    public override void OnBeginDrag(PointerEventData eventData) { }
    public override void OnEndDrag(PointerEventData eventData) { }
    public override void OnDrag(PointerEventData eventData) { }


#if UNITY_EDITOR
    [UnityEditor.MenuItem("CONTEXT/ScrollRect/Disable Drag To Scroll")]
    static void ConvertToNoDrag(UnityEditor.MenuCommand command) {
        var og = (ScrollRect) command.context;
        if (og is ScrollRectWithoutDrag) {
            Debug.LogWarning($"Drag is already disabled on {og}");
            return;
        }

        // Cache references
        var gameObject = og.gameObject;
        var content = og.content;
        var viewport = og.viewport;
        var horizontalScrollbar = og.horizontalScrollbar;
        var verticalScrollbar = og.verticalScrollbar;
        var onValueChanged = og.onValueChanged;

        // Cache other settings
        var horizontal = og.horizontal;
        var vertical = og.vertical;
        var movementType = og.movementType;
        var elasticity = og.elasticity;
        var inertia = og.inertia;
        var decelerationRate = og.decelerationRate;
        var scrollSensitivity = og.scrollSensitivity;
        var horizontalScrollbarSpacing = og.horizontalScrollbarSpacing;
        var verticalScrollbarSpacing = og.verticalScrollbarSpacing;

        // Remove the existing component
        UnityEditor.Undo.DestroyObjectImmediate(og);

        // Add the new component and transfer the old values to it
        var newScrollRect = UnityEditor.Undo.AddComponent<ScrollRectWithoutDrag>(gameObject);

        newScrollRect.content = content;
        newScrollRect.viewport = viewport;
        newScrollRect.horizontalScrollbar = horizontalScrollbar;
        newScrollRect.verticalScrollbar = verticalScrollbar;
        newScrollRect.horizontal = horizontal;
        newScrollRect.vertical = vertical;
        newScrollRect.movementType = movementType;
        newScrollRect.elasticity = elasticity;
        newScrollRect.inertia = inertia;
        newScrollRect.decelerationRate = decelerationRate;
        newScrollRect.scrollSensitivity = scrollSensitivity;
        newScrollRect.horizontalScrollbarSpacing = horizontalScrollbarSpacing;
        newScrollRect.verticalScrollbarSpacing = verticalScrollbarSpacing;
        newScrollRect.onValueChanged = onValueChanged;

        UnityEditor.EditorUtility.SetDirty(gameObject);
    }
#endif
}