Search Unity

Buttons within scroll rect are difficult to press on mobile

Discussion in 'UGUI & TextMesh Pro' started by nventimiglia, Aug 31, 2014.

  1. longdrecom123

    longdrecom123

    Joined:
    Mar 2, 2017
    Posts:
    1
    it's working for me. Thank you!
     
    GameJob2017 likes this.
  2. Autoface

    Autoface

    Joined:
    Sep 23, 2013
    Posts:
    112
    I had the same issue. It appears that when pressing a button on a mobile device your finger might move a tiny tiny bit which starts the drag and interrupts the on click.

    I only noticed the issue when I tried to implement the functionality of holding a button down for 1 second and then triggering an event.

    To fix it I went to the EventSystem in my scene which gets created when you make a canvas. Inside the EventSystem there is an option called "Drag Threshold". Change the value to about 32 and see if it improves.

     
    GameDevMig likes this.
  3. hexagonius

    hexagonius

    Joined:
    Mar 26, 2013
    Posts:
    98
    That's not a good solution. Every device has a different pixel density and you don't want to change the Drag threshold for every single one. That's why the optimal solution is taking the devices dpi into account, define the threshold per inch(cm) and it works for all
    devices.
     
    MasterZuh and BadSeedProductions like this.
  4. ibrahimhashmi

    ibrahimhashmi

    Joined:
    Jun 5, 2017
    Posts:
    1
    Thanks ALot For This Solutions. Its 100% working
     
    AthenaDevops likes this.
  5. GimpMaster

    GimpMaster

    Joined:
    Mar 30, 2017
    Posts:
    7
    Hello, just wanted to say thanks for this post and for the code Johannski. I'm very surprised Unity after 3 years of this being reported has not addressed it on their own.
     
    VirtualPierogi and codestage like this.
  6. tng2903mm

    tng2903mm

    Joined:
    May 17, 2018
    Posts:
    16
    just encounter this gimmick today, on 2017.4.4f1, nice work Unity
     
    VirtualPierogi likes this.
  7. PeterPam

    PeterPam

    Joined:
    Nov 9, 2015
    Posts:
    18
    Version 2018.1.7f1 and the issue continues here.
    This solutions was good for me!
    Thanks!
     
  8. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Is there any way to use a different drag threshold for touch input as compared to mouse input?
     
  9. AthenaDevops

    AthenaDevops

    Joined:
    Oct 22, 2018
    Posts:
    1
    @Johannski solution works perfectly for me. Unity 2017. Thanks a lot!
     
  10. Saulius

    Saulius

    Joined:
    Aug 10, 2010
    Posts:
    21
    Same thing on Unity 2019.1.4f1. Used Johannski script and that helped.
     
    MasterZuh likes this.
  11. jesusluvsyooh

    jesusluvsyooh

    Joined:
    Jan 10, 2012
    Posts:
    377
    Hi, i thought i would come back here and post my solution, as this thread helped me.
    Just pop this onto your Canvas Parent, no need to set variables, it uses canvas scaling and not DPI.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.EventSystems;
    3.  
    4. public class DragThreshold : MonoBehaviour
    5. {
    6.     private Canvas myCanvas;
    7.     private int defaultDrag = 0;
    8.     void Start()
    9.     {
    10.         defaultDrag = EventSystem.current.pixelDragThreshold;
    11.         myCanvas = this.GetComponent<Canvas>();
    12.         EventSystem.current.pixelDragThreshold = (int)(defaultDrag * myCanvas.scaleFactor);
    13.        // Above way recommend by poster below.
    14.        // EventSystem.current.pixelDragThreshold = defaultDrag * (int)myCanvas.scaleFactor;
    15.     }
    16. }
     
    Last edited: Apr 1, 2020
  12. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    You should really replace this line:
    Code (CSharp):
    1. EventSystem.current.pixelDragThreshold = defaultDrag * (int)myCanvas.scaleFactor;
    with this:
    Code (CSharp):
    1. EventSystem.current.pixelDragThreshold = (int)(defaultDrag * myCanvas.scaleFactor);
    Otherwise you are only allowing the threshold to change in integer multiples of the original threshold. For example, if the original threshold was 5 pixels, then you are only allowing values of 10, 15, 20, ... and not, for example, 6. If you have to change the threshold downward, it can only snap between 5 and 0.
     
    mmmshuddup and MasterZuh like this.
  13. jesusluvsyooh

    jesusluvsyooh

    Joined:
    Jan 10, 2012
    Posts:
    377
    Good catch, i did not notice that.
    *Editing original post for those copy n pasters out there.
     
  14. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    838
    This problem is occurring when I'm using a VR pointer with the UI. Setting the drag threshold to max int (or 0) does not seem to resolve the issue (buttons are being selected, but onClick is not firing).
     
    VirtualPierogi likes this.
  15. Karsten

    Karsten

    Joined:
    Apr 8, 2012
    Posts:
    187
    This issue is still there in 2020.3.19f1 , cant scroll the ScrolView when the content has children that are selectable/clickable/interactable when implementing IPointerClickHandler for the content elements they cant be clicked but scrollview works ,if using the EventTrigger component on the content items they are clickable but the scrollView cant be moved. Why you do this Unity Technologies?

    Edit: Instead of only IPointerClickHandler also Up and Down MUST be implemented even if the method body stays empty, docs dont tell this.
     
    Last edited: Oct 9, 2021
  16. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    EventTrigger captures all the listed events (thereby preventing them from reaching parent objects).

    This is probably the only way EventTrigger could work, given that Unity relies on interfaces to determine which events a component should capture, and interfaces cannot be changed at runtime.

    I would not expect this to change.
     
    Last edited: Oct 11, 2021
  17. Brother_77

    Brother_77

    Joined:
    Feb 8, 2019
    Posts:
    233
    2022 and this post is from 2014, please can someone from Unity team @phil-Unity, or anyone, share their thoughts on this topic ? This issue seems to be fixed by the community but

    would you say I should go with the (Johannski's) answer that many are supporting or is the (jesusluvsyooh) a better approach ?

    Johannski:

    Code (CSharp):
    1. public class AdaptingEventSystemDragThreshold : MonoBehaviour
    2.     {
    3.         [SerializeField] private EventSystem eventSystem;
    4.         [SerializeField] private int referenceDPI = 100;
    5.         [SerializeField] private float referencePixelDrag = 8f;
    6.         [SerializeField] private bool runOnAwake = true;
    7.         void Awake()
    8.         {
    9.             if (runOnAwake)
    10.             {
    11.                 UpdatePixelDrag(Screen.dpi);
    12.             }
    13.         }
    14.         public void UpdatePixelDrag(float screenDpi)
    15.         {
    16.             if (eventSystem == null)
    17.             {
    18.                 Debug.LogWarning("Trying to set pixel drag for adapting to screen dpi, " +
    19.                                "but there is no event system assigned to the script", this);
    20.             }
    21.             eventSystem.pixelDragThreshold = Mathf.RoundToInt(screenDpi/ referenceDPI*referencePixelDrag);
    22.         }
    23.         void Reset()
    24.         {
    25.             if (eventSystem == null)
    26.             {
    27.                 eventSystem = GetComponent<EventSystem>();
    28.             }
    29.         }
    30.     }

    OR

    jesusluvsyooh:

    "Hi, i thought i would come back here and post my solution, as this thread helped me.
    Just pop this onto your Canvas Parent, no need to set variables, it uses canvas scaling and not DPI."

    Code (CSharp):
    1. public class DragThreshold : MonoBehaviour
    2. {
    3.     private Canvas myCanvas;
    4.     private int defaultDrag = 0;
    5.     void Start()
    6.     {
    7.         defaultDrag = EventSystem.current.pixelDragThreshold;
    8.         myCanvas = this.GetComponent<Canvas>();
    9.         EventSystem.current.pixelDragThreshold = (int)(defaultDrag * myCanvas.scaleFactor);
    10.     }
    11. }