Search Unity

  1. Check out the Unite LA keynote for updates on the Visual Effect Editor, the FPS Sample, ECS, Unity for Film and more! Watch it now!
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  4. Want more efficiency in your development work? Sign up to receive weekly tech and creative know-how from Unity experts.
    Dismiss Notice
  5. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  6. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

ScrollBar Fixed Handle Size

Discussion in 'Unity UI & TextMesh Pro' started by wagenheimer, Jun 25, 2018.

  1. wagenheimer

    wagenheimer

    Joined:
    Jun 1, 2018
    Posts:
    31
    Is it possible to make the handle of a scrollbar fixed size or use a Slider instead of a ScrollBar with a ScrollRect?

    I want to use a simple handle and not the handle that is resized during the use. Is this not possible?
     
  2. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    450
    I just tried some stuff but didin't had much success.

    first I tried to keep the size variable of the Scrollbar at zero. To do this I added an event to OnValueChanged in the Scrollbar component and dragged the scrollbar itself into the target field and selected "Scrollbar.size" from the drop down (not the one on the top - the one somewhere in the middle) and set the value to 0. This works but sometimes it flickers to have the original size.
    I could reduce the flickering by also adding a Event Trigger component and add the exact same (Scrollbar.size -> 0) to the events "Update Selected" and "Drag". Flickering is rare but still happens.

    another approach: adding an aspect ratio fitter to the handle with "Width controls height" and ratio of 1. This keeps the handle at the same size but the calculations not. That means that the area in which the handle can be dragged is not the full size.

    the first approach is better. Maybe you can fix the flickering issue with a custom component where you set the size to 0 in the Update and/or LateUpdate method...
     
  3. FernandoHC

    FernandoHC

    Joined:
    Feb 6, 2018
    Posts:
    257
    Just add a fixed size object child of Handle, as handle doesn't change scale it won't affect its child. Just remember to keep the anchors to not stretch on the child object and it will work as a handle. Then you can simply disable the image from the parent handle to avoid displaying it.
     
  4. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    450
    first I also thought that this is the way to go, but it isn't. It has the same problem as the aspect ratio fitter approach: The min/max position of the handle will change depending on the size of the content. If you anchor it on the top, the lowest position is variable, if you anchor on the bottom the highest position is variable, if you anchor on the middle both positions are variable...
     
  5. FernandoHC

    FernandoHC

    Joined:
    Feb 6, 2018
    Posts:
    257
    Well that's tricky, maybe using the slider with event listeners to the scrollrect dragging position change and update the slider position and vice-versa.
     
  6. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    450
    yeah... that would be like a scroll bar inside a scroll bar :D
     
    FernandoHC likes this.
  7. douglassophies

    douglassophies

    Joined:
    Jun 17, 2012
    Posts:
    59
    What was the solution you went with in the end?
     
  8. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    450
    I did nothing, because I did not have the problem. I just tried to help.
    @wagenheimer can you tell how you ended up?
     
  9. wagenheimer

    wagenheimer

    Joined:
    Jun 1, 2018
    Posts:
    31
    I'm using this code now and everything is working as expected! =)

    It fixes 2 things :
    - Not being able to Drag because of buttons on children.
    - The Handle does not change size anymore.


    Code (csharp):
    1.  
    2. /// Credit CaptainSchnittchen
    3. /// Credit TouchPad (OnScroll function) update - GamesRUs
    4. /// sourced from: http://forum.unity3d.com/threads/scripts-useful-4-6-scripts-collection.264161/page-2#post-2011648
    5.  
    6. /*USAGE:
    7. Simply place the script on the ScrollRect that contains the selectable children we'll be scrolling to
    8. and drag-drop the RectTransform of the options "container" that we'll be scrolling.*/
    9.  
    10. using System;
    11. using UnityEngine.EventSystems;
    12.  
    13. namespace UnityEngine.UI.Extensions
    14. {
    15.  
    16.     [AddComponentMenu("UI/Extensions/ScrollRectEx")]
    17.     public class ScrollRectEx : ScrollRect
    18.     {
    19.         private bool routeToParent = false;
    20.  
    21.         /// <summary>
    22.         /// Do action for all parents
    23.         /// </summary>
    24.         private void DoForParents<T>(Action<T> action) where T : IEventSystemHandler
    25.         {
    26.             Transform parent = transform.parent;
    27.             while (parent != null)
    28.             {
    29.                 foreach (var component in parent.GetComponents<Component>())
    30.                 {
    31.                     if (component is T)
    32.                         action((T) (IEventSystemHandler) component);
    33.                 }
    34.  
    35.                 parent = parent.parent;
    36.             }
    37.         }
    38.  
    39.         /// <summary>
    40.         /// Always route initialize potential drag event to parents
    41.         /// </summary>
    42.         public override void OnInitializePotentialDrag(PointerEventData eventData)
    43.         {
    44.             DoForParents<IInitializePotentialDragHandler>((parent) => { parent.OnInitializePotentialDrag(eventData); });
    45.             base.OnInitializePotentialDrag(eventData);
    46.         }
    47.  
    48.         /// <summary>
    49.         /// Drag event
    50.         /// </summary>
    51.         public override void OnDrag(UnityEngine.EventSystems.PointerEventData eventData)
    52.         {
    53.             if (routeToParent)
    54.                 DoForParents<IDragHandler>((parent) => { parent.OnDrag(eventData); });
    55.             else
    56.                 base.OnDrag(eventData);
    57.         }
    58.  
    59.         /// <summary>
    60.         /// Begin drag event
    61.         /// </summary>
    62.         public override void OnBeginDrag(UnityEngine.EventSystems.PointerEventData eventData)
    63.         {
    64.             if (!horizontal && Math.Abs(eventData.delta.x) > Math.Abs(eventData.delta.y))
    65.                 routeToParent = true;
    66.             else if (!vertical && Math.Abs(eventData.delta.x) < Math.Abs(eventData.delta.y))
    67.                 routeToParent = true;
    68.             else
    69.                 routeToParent = false;
    70.  
    71.             if (routeToParent)
    72.                 DoForParents<IBeginDragHandler>((parent) => { parent.OnBeginDrag(eventData); });
    73.             else
    74.                 base.OnBeginDrag(eventData);
    75.         }
    76.  
    77.         /// <summary>
    78.         /// End drag event
    79.         /// </summary>
    80.         public override void OnEndDrag(UnityEngine.EventSystems.PointerEventData eventData)
    81.         {
    82.             if (routeToParent)
    83.                 DoForParents<IEndDragHandler>((parent) => { parent.OnEndDrag(eventData); });
    84.             else
    85.                 base.OnEndDrag(eventData);
    86.             routeToParent = false;
    87.         }
    88.  
    89.         public override void OnScroll(PointerEventData eventData)
    90.         {
    91.             if (!horizontal && Math.Abs(eventData.scrollDelta.x) > Math.Abs(eventData.scrollDelta.y))
    92.             {
    93.                 routeToParent = true;
    94.             }
    95.             else if (!vertical && Math.Abs(eventData.scrollDelta.x) < Math.Abs(eventData.scrollDelta.y))
    96.             {
    97.                 routeToParent = true;
    98.             }
    99.             else
    100.             {
    101.                 routeToParent = false;
    102.             }
    103.  
    104.             if (routeToParent)
    105.                 DoForParents<IScrollHandler>((parent) => { parent.OnScroll(eventData); });
    106.             else
    107.                 base.OnScroll(eventData);
    108.         }
    109.  
    110.         override protected void LateUpdate()
    111.         {
    112.  
    113.             base.LateUpdate();
    114.  
    115.             if (this.horizontalScrollbar)
    116.             {
    117.  
    118.                 this.horizontalScrollbar.size = 0;
    119.             }
    120.         }
    121.  
    122.         override public void Rebuild(CanvasUpdate executing)
    123.         {
    124.  
    125.             base.Rebuild(executing);
    126.  
    127.             if (this.horizontalScrollbar)
    128.             {
    129.  
    130.                 this.horizontalScrollbar.size = 0;
    131.             }
    132.         }
    133.     }
    134.  
    135. }
    136.