Search Unity

Question How do you use the ScrollView from the UI Toolkit?

Discussion in 'UI Toolkit' started by JamesA24, May 14, 2020.

  1. JamesA24

    JamesA24

    Joined:
    Sep 6, 2018
    Posts:
    28
    I'm encountering issues when trying to make any sense of the ScrollView. There really isn't much information on the best way to work with the additional Views and Windows.

    I'm learning to use some of the more complex features from the toolkit for an editor tool i'm working towards.

    What I have so far is I have a window that contains an empty ScrollView.
    There's two buttons under the ScrollView that can add and remove objects from the ScrollView.

    Here's pseudo code for what i'm trying to do.

    ScrollView _stepBuilder;
    VisualTreeAsset _tree;

    _tree = loaded visual tree asset from path;
    VisualElement step = _tree.CloneTree();

    //_stepBuilder.verticalScroller.contentContainer.Add(step); //Doesn't display in the Viewport at all. But spawns.
    //_stepBuilder.contentViewport.Add(step); Spawns and displays in the view port.
    //_stepBuilder.verticalScroller.Add(step); //Doesn't display in the Viewport at all. But spawns.
    //_stepBuilder.contentContainer.Add(step); Spawns and displays in the view port.



    So for the ScrollView there is a viewport. That is where I would imagine I should place the steps i'm creating in the step builder. I do also get the vertical scroll bar to appear. However, there's no dragger visible, and I can't see a way to modify the dragger so it becomes visible. When I set it to visible in the UIElements Debugger, I can see it but I can't use it still.

    The two things I want to ask for help here is...

    What is the correct method for having something be a child of the ScrollView?
    How can I actually use the Dragger?

    Thank you.
     
  2. uMathieu

    uMathieu

    Unity Technologies

    Joined:
    Jun 6, 2017
    Posts:
    398
    VisualElements specify a contentContainer, ie where children added to their hierarchy will go. In most VisualElements, contentContaienr == this. In the case of the ScrollView however, its contentContainer points to one of its child (which is not the contentViewport).

    In short, ScrollView does the abstraction for you and _stepBuilder.Add() will add elements to the right place. In a case where you need to access the real non-abstracted children, you can do _stepBuilder.hierarchy.Add() and this will physically add the VisualElement as a direct child of the ScrollView instead of its container.
     
    JamesA24 likes this.
  3. JamesA24

    JamesA24

    Joined:
    Sep 6, 2018
    Posts:
    28
    That make sense when trying to populate the view port.
    But how can I then get the dragger within the slider to be visible and allow for me to interact with it?
    I need to be able to drag it vertically to see items in my window as the window gets more steps added to it.
     
  4. exploringunity

    exploringunity

    Joined:
    May 15, 2020
    Posts:
    1
    Hey @JamesAiken,

    Like uMathieu is saying, you should be able to call _stepBuilder.Add(step).
    --------------------------------------------------
    Below is a small, but complete example of using a ScrollView with dynamic content using Unity 2020.1.0b3 -- I think the only change for Unity 2019.1 would be to change Instantiate to CloneTree? Anyway, you should end up with something like this, where you can add and delete items:

    dynamic_items.png
    --------------------------------------------------
    Assets/Editor/ScrollViewTest.uxml
    Code (CSharp):
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <engine:UXML
    3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4.     xmlns:engine="UnityEngine.UIElements"
    5.     xmlns:editor="UnityEditor.UIElements"
    6.     xsi:noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd"
    7. >
    8.   <engine:VisualElement>
    9.     <engine:Style src="ScrollViewTest.uss" />
    10.     <engine:Button name="addItemBtn" text="Add Item" />
    11.     <engine:ScrollView name="itemContainer" />
    12.   </engine:VisualElement>
    13. </engine:UXML>
    --------------------------------------------------

    Assets/Editor/ScrollViewTestItem.uxml
    Code (CSharp):
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <engine:UXML
    3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4.     xmlns:engine="UnityEngine.UIElements"
    5.     xmlns:editor="UnityEditor.UIElements"
    6.     xsi:noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd"
    7. >
    8.   <engine:VisualElement class="horizontalContainer">
    9.     <engine:Label name="itemIdLbl" />
    10.     <engine:Button name="deleteItemBtn" text="X" />
    11.   </engine:VisualElement>
    12. </engine:UXML>
    --------------------------------------------------

    Assets/Editor/ScrollViewTest.uss
    Code (CSharp):
    1. .horizontalContainer { flex-direction: row; }
    2. #itemIdLbl { flex-grow: 1; }
    3. #addItemBtn { margin: 5px 20px; padding: 5px; }
    4. #deleteItemBtn { color: red; }
    --------------------------------------------------

    Assets/Editor/ScrollViewTest.cs
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine.UIElements;
    3.  
    4. public class ScrollViewTest : EditorWindow
    5. {
    6.     ScrollView itemContainer;
    7.     VisualTreeAsset itemTemplate;
    8.  
    9.     [MenuItem("Custom Tools/Scroll View Test %#t")]
    10.     public static void OpenWindow() { GetWindow<ScrollViewTest>(); }
    11.  
    12.     public void OnEnable()
    13.     {
    14.         // Create UI
    15.         var mainTemplate = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/ScrollViewTest.uxml");
    16.         var ui = mainTemplate.Instantiate();
    17.         rootVisualElement.Add(ui);
    18.         // Support dynamic items
    19.         itemTemplate = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/ScrollViewTestItem.uxml");
    20.         itemContainer = ui.Q<ScrollView>("itemContainer");
    21.         var addItemBtn = ui.Q<Button>("addItemBtn");
    22.         addItemBtn.clicked += AddListItem;
    23.     }
    24.  
    25.     void AddListItem()
    26.     {
    27.         var itemUi = itemTemplate.Instantiate();
    28.         var itemIdLbl = itemUi.Q<Label>("itemIdLbl");
    29.         itemIdLbl.text = System.Guid.NewGuid().ToString();
    30.         var deleteItemBtn = itemUi.Q<Button>("deleteItemBtn");
    31.         deleteItemBtn.clicked += () => itemUi.RemoveFromHierarchy();
    32.         itemContainer.Add(itemUi);
    33.     }
    34. }
    --------------------------------------------------
    Hope this helps!
     
  5. uMathieu

    uMathieu

    Unity Technologies

    Joined:
    Jun 6, 2017
    Posts:
    398
    @JamesAiken You can force the display of scrollbars with ScrollView.showHorizontal/showVertical . However, if the ScrollView's contentContainer is larger than the scrollView, they should become visible.

    If you use absolute positioning for your elements however, the contentContainer won't grow to fill the space and you'll need to manually set its size or minimumSize: ScrollView.contentContainer.style.minWidth = 500;
     
    JamesA24 likes this.
  6. JamesA24

    JamesA24

    Joined:
    Sep 6, 2018
    Posts:
    28
    exploringunity and uMathieu like this.
  7. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    I followed the instructions here, and it seems to work, but fails as soon as you enable wrapping.

    Is this a known-bug with ScrollView, that it breaks wrapping?
     
  8. uMathieu

    uMathieu

    Unity Technologies

    Joined:
    Jun 6, 2017
    Posts:
    398
    Please report an issue with Help->Report a bug... with your repro steps.
     
  9. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    Thanks, I figured it out - it doesn't work quite the way that was described in this thread (the thread isn't wrong, but it leaves out some subtleties, and I took this thread too literally).

    But with some guesswork it works fine (TL;DR: for any non-trivial situation, don't just add directly to the ScrollView, the abstraction breaks when you try to configure it. Instead iether make sure you're configuring the ScrollView's internal contentcontainer (untested but I'm guessing this will work fine), or do the easier thing and create your own contentContainer, add that to the ScrollView, configure it, and put your children into it instead of into ScrollView)

    I think this will probably be solved automatically when you write the docs for ScrollView (currently there are none). Nothing for me to log a bug report against at the moment :).
     
  10. ShokWayve

    ShokWayve

    Joined:
    Jan 16, 2013
    Posts:
    136
    This helped out a lot. Thanks!
     
  11. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    863
    How do I do this in the UI Builder?? So I can actually.... See.. what I'm doing? How do I put these inside the content? Also to see the scroll bar, and just in general have some visibility and control in this editor. There is custom content inside a scroll view in a sample project, I've spent so much time trying to figure out how to put mine in. In the sample project I CAN indeed just drag and drop things into content.

    upload_2023-12-22_20-48-58.png
     
  12. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,938
    Drag your visual elements to the ListView and they will be added as children of the visual element's
    contentContainer
    .
     
  13. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    863
    Yeah, the whole issue is that it is not happening. It works with Scroll View (it turns out!) but not with List View. I dragged it on everything including the nongrayed out 'root" object. I should have read the manual first, but what I guessed is the way it works turned out to be correct except it doesn't seem to work. I switched to scroll view.

    @Unity Can I register a complaint by the way? I couldn't believe it's not working. I can't just drag and drop a uxml inside a uxml... I have to go to a special menu and find there the uxml that I can drag and drop only from that special menu.. I's just so unintuitive that it doesn't work from the Project view.

    P.S. Checked again, drag&drop doesn't work for list view. This is pretty confusing for the first time UI Builderusers who naturally assume that it is how all premade UI elements supposed to work and see that tit doesn't.
     
    Last edited: Dec 28, 2023
  14. C-UITools

    C-UITools

    Unity Technologies

    Joined:
    Jun 23, 2021
    Posts:
    31
    Hello @illinar! Which version of the Editor are you using?
     
  15. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    863
    That project is on 2023.3.0.a18

    Thanks. Also some other elements like Tree View and List View are not responding to drag and drop of content on them.
     
  16. cpalma-unity

    cpalma-unity

    Unity Technologies

    Joined:
    Nov 30, 2020
    Posts:
    110
    Hello @illinar! ListView and TreeView are controls designed to show a large collection of items. These items are created exclusively by the controls so they can be reused. This is the reason why you can't add children manually to a ListView or a TreeView.

    That being said, I agree with you that is pretty confusing that you can't add children from the UI Builder. I will bring this issue up to the team so we can find a better way to notify users that items can't be added directly in the UI Builder.
     
    kmowers and illinar like this.