Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Padding under/inside a ListView

Discussion in 'UI Toolkit' started by vallis_unity, Feb 17, 2023.

  1. vallis_unity

    vallis_unity

    Joined:
    Apr 14, 2022
    Posts:
    69
    This is a bit of a difficult one to explain, so I've put together a contrived example to try and strip things down to the basics. Given a (dynamic) ListView in the background and an element which is positioned over the top of (and partly occludes) the bottom of the ListView, how can you pad the bottom of the ListView area so that you can scroll to a point where the final item in the ListView is revealed?

    The example: a single UIDocument in it with the following UXML:

    Code (Boo):
    1. <ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
    2.     <ui:ListView selection-type="None" virtualization-method="DynamicHeight" />
    3.     <ui:VisualElement name="VisualElement" style="position: absolute; bottom: 0; left: 40%; right: 40%; height: 50px; background-color: rgb(22, 171, 47);" />
    4. </ui:UXML>
    Then a script to drive some test data into the ListView:

    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UIElements;
    5.  
    6. public class ListViewMargin : MonoBehaviour
    7. {
    8.     void Start()
    9.     {
    10.         var document = GetComponent<UIDocument>();
    11.         var listview = document.rootVisualElement.Q<ListView>();
    12.  
    13.         var list = new List<string>();
    14.         for (var i = 0; i < 200; ++i)
    15.         {
    16.             var guid = Guid.NewGuid();
    17.             list.Add($"{guid}");
    18.         }
    19.         listview.itemsSource = list;
    20.  
    21.         listview.makeItem = () =>
    22.         {
    23.             var label = new Label();
    24.             label.style.unityTextAlign = TextAnchor.MiddleCenter;
    25.             return label;
    26.         };
    27.  
    28.         listview.bindItem = (item, index) =>
    29.         {
    30.             item.Q<Label>().text = list[index];
    31.         };
    32.     }
    33. }
    This produces the following output. To be clear, this is exactly how it should look when scrolled to the top: the green box should appear over the content and partly occlude it.

    top.png

    Scrolling down to the bottom of the ListView still occludes the final items though:

    bottom.png

    I have attempted to add padding and margins to various elements but can't seem to find a combination which allows scrolling past the green box at the bottom, while retaining the way it partially occludes items not at the bottom of the list.

    As in this example, the height of the green box is static and known ahead of time, if that helps.
     
  2. vallis_unity

    vallis_unity

    Joined:
    Apr 14, 2022
    Posts:
    69
    To rephrase the original question, what I'm looking for is a way to get the ScrollView inside the ListView to "overscroll" (at the bottom only) by the fixed height of the green box so that you can scroll "past" the end and see all the GUIDs.
     
  3. vallis_unity

    vallis_unity

    Joined:
    Apr 14, 2022
    Posts:
    69
    The closest I've managed to get with this is using margins on the list items:
    • Give each item as much margin-bottom as needed (in the example above, enough to clear the green box)
    • Give each item enough negative margin-top as needed to eat the above on everything but the bottom item
    This totally gets me where I want to be at the bottom of the screen, but sadly a similar issue now manifests at the top where the first item in the list has a bunch of negative margin and nothing to eat so it gets clipped.

    I thought I'd be able to fix this with some padding on the ListView's ".unity-scroll-view__content-container--vertical" element, but frustratingly its top padding gets reset to zero as soon as you scroll. If I change the value in the debugger, I can see everything looking exactly as I need it to be... but as soon as you scroll the content container the padding is reset the the first list item gets clipped again.

    This would all be so very easy with a :last-child pseudo-class.
     
  4. cnsjjj

    cnsjjj

    Joined:
    Aug 13, 2022
    Posts:
    23
    I have the same needs. Have you solved it?
     
  5. vallis_unity

    vallis_unity

    Joined:
    Apr 14, 2022
    Posts:
    69
    No, if you find anything workable please do post it here.

    What we really need is a
    :last-child
    pseudo class. I've tried to ask Unity if this is on the roadmap but haven't received any response.