ListView, TileView and Table

Note

Table is ListView with specific DefaultItem and Table Header (it also provides Table specific methods). Widget with scripts should be created by Widgets Generator.

Note

In case of noticeable artifacts when scrolling (these are caused by rounding during rendering), you can increase the font size to reduce the artifacts.

  • All collections widgets support virtualization: gameobjects created only for the visible items.

  • Different ListView, TileView and Table can display the same list simultaneously.

  • In most cases ToggleGroup and SwitchGroup components used by widgets under DefaultItem hierarchy should be placed outside DefaultItem gameobject. And on value changed callbacks should process all items, not only the current one, since invisible items do not receive callbacks because of the virtualization.

List View Type

../../_images/ListView-fixed-size.png

ListView with Fixed Size.

../../_images/ListView-variable-size.png

ListView with Variable Size.

../../_images/ListView-ellipse.png

ListView with Ellipse layout.

../../_images/TileView-fixed-size.png

TileView with Fixed Size.

../../_images/TileView-variable-size.png

TileView with Variable Size.

../../_images/TileView-staggered.png

TileView Staggered.

Note

Requirements for ListView and TileView with Variable Size:
Instance sizes are stored in the Dictionary<TItem, Vector2> and different instances of the same item should have the same size.
ListView will not work correctly if sizes are different for the instances of the same item.

EasyLayout Settings for the Ellipse Type

  • RectTransform.pivot

    Defines on which side or corner will be the center point.

  • EasyLayout.Ellipse settings

    Width and height usually should be specified, set the same value for the circle.

  • Angle Start

    Base rotation for the first item.

  • Angle Step Auto

    Should be disabled.

  • Angle Step

    Angular distance between items.

  • Fill

    Should be Arc.

  • Arc Length

    Should be 180 if center at the side and 90 if center at the corner.

Options

  • Interactable bool

    Allow users interact with the ListView.

  • Disable ScrollRect bool

    If ListView is disabled then ScrollRect and scrollbars will be disabled too.

  • Virtualization bool

    Enable virtualization. If enabled GameObject instantiated only for the visible items; otherwise for the all items.

  • List Type ListViewType

    Determines how items are displayed.

    • ListViewWithFixedSize

      Works with EasyLayout, Horizontal Layout Group and Vertical Layout Group.

    • ListViewWithVariableSize

      Works with EasyLayout, Horizontal Layout Group and Vertical Layout Group.

    • ListViewEllipse

      Works with EasyLayout. Axis of rotation is RectTransform.pivot.
      It is recommended to use with enabled LoopedList option.
    • TileViewWithFixedSize

      Works with EasyLayout.

    • TileViewWithVariableSize

      Works with EasyLayout.

    • TileViewStaggered

      Works with EasyLayout.

  • ChangeLayoutType bool

    EasyLayout settings will be changed according current list type if this option enabled.

  • StretchToMaxItemSize bool

    This option will stretch ListView to fully display the largest item, and works only with ListViewWithVariableSize.
    Mainly it is used for the Combobox.ListView.
  • PrecalculateItemSizes bool.

    If enabled then item sizes will calculated at the start and provide a precise scroll, the disabled option improves performance.
    Available only for the VariableSize types.
  • Sort bool deprecated

    Available only for ListViewIcons. If enabled items will be sorted by name.
    Deprecated, replaced with DataSource.Comparer.
  • SortFunc Func<IEnumerable<TItem>, IEnumerable<TItem>> deprecated

    Not available in the Inspector window Function to sort items. Deprecated, replaced with DataSource.Comparer.

  • Data Source ObservableList<TItem>

    List of the items. It works the same way as List<T> with some additions.
    Not available in the inspector window if type not specified as serializable.
  • ReversedOrder bool

    If enabled first item will be displayed at the end of the list, initial scroll position also will be at the end.
    Can be used for horizontal lists in cultures with right-to-left writing directions.
  • Selected Index int

    Index of the last selected item.

  • Multiple Select bool

    Allow to select multiple items, otherwise only one.

  • Multiple Select Require Keys bool

    Items selection will work similarly to file explorer if enabled.

  • Range Mode RangeSelectionMode

    Specify range selection mode (multiple items selection with Shift key).

    • StartFromFirst

      Select all items from the first selected item to the newly selected item.

    • StartFromLast

      Select all items from the last selected item to the newly selected item.

  • Selected Indices List<int>

    Not available in the Inspector window List of the selected items indices.

  • Selected Item TItem

    Not available in the Inspector window Last selected item.

  • Selected Items List<TItem>

    Not available in the Inspector window List of the selected items.

  • Direction ListViewDirection

    ListView direction.

    • Horizontal

    • Vertical

  • ScrollRect ScrollRect

    ScrollRect used by ListView. Required for virtualization support.

  • Container Transform

    The container of the instantiated gameobjects used to display items. Should have layout required for the specified List Type.

  • SetContentSizeFitter bool

    If enable changes ContentSizeFitter settings according to the selected direction.

  • Default Item TComponent

    A prefab used to display item.

  • DestroyDefaultItemsCache bool

    If enabled then instances of the previous DefaultItem will be destroyed when DefaultItem or TemplateSelector are changed.

  • Allow Coloring bool

    Change colors of the highlighted and selected items.
    If you want to more precise control on item colors, like different colors depending of item data, then you can override StateDefault(), StateHighlighted(), StateSelected(), and StateDisabled() methods of TComponent class.
  • Coloring Striped bool

    Use different background colors for the odd and even items.
  • Colors

    Colors for the text and background elements of the DefaultItem instances.

    Text and background elements defined with GraphicsForeground and GraphicsBackground properties of the TComponent.

    • Default Color Color

    • Default Background Color Color: only if Coloring Striped disabled

    • Default Odd Background Color Color: only if Coloring Striped enabled

    • Default Even Background Color Color: only if Coloring Striped enabled

    • Highlighted Color Color

    • Highlighted Background Color Color

    • Selected Color Color

    • Selected Background Color Color

    • Disabled Color Color: multiplier for the specified colors if ListView is not interactable, actual color is current color (default, highlighted, selected) * disabled color.

  • Fade Duration float

    Time for a smooth color change when the state of an element changes.

  • Keep Highlight bool

    Keep item highlight on pointer enter until will be selected another gameobject.

  • Only One Highlighted bool

    Allows only one highlighted item. If disabled then two can be highlighted: first from pointer over, second from navigation by keyboard or gamepad.

  • Navigation bool

    Allow to use navigation with keyboard or gamepad.
    ListView should have a Selectable component to navigation work properly.
  • Looped Navigation bool

    Enables/disables navigation from first to last item and vice versa.

  • Require Visible int

    Number of visible items from current item to border on navigation.

  • Style Table bool

    Is ListView will be displayed as a table? Used for correct styles support.

  • Header TableHeader

    Deprecated field and should be used only if legacy styles are enabled.

  • LocalizationSupport bool

    If enabled item names will be translated with Localization.GetTranslation() method if localization is used.
    Available only for the ListViewIcons.
  • Can Select Func<int, bool>

    The function that determines whether the item with the specified index can be selected. Unselectable items cannot be highlighted and skipped by keyboard and gamepad navigation.

  • Can Deselect Func<int, bool>

    The function that determines whether the item with the specified index can be deselected.

Events

  • OnSelect UnityEvent<int, ListViewItem>

    The event raised when item selected.

    Arguments: index of the selected item and DefaultItem instance for the selected item.

  • OnDeselect UnityEvent<int, ListViewItem>

    The event raised when item deselected.

    Arguments: index of the deselected item and DefaultItem instance for the deselected item.
    If an item associated with this index is removed the index can be invalid ( >= DataSouce.Count) or point to different item.
  • OnSelectObject UnityEvent<int>

    The event raised when item selected.

    Arguments: index of the selected item.

  • OnDeselectObject UnityEvent<int>

    The event raised when item deselected.

    Arguments: index of the deselected item. If an item associated with this index is removed the index can be invalid ( >= DataSouce.Count) or point to different item.

  • OnStartScrolling UnityEvent

    The event raised when scrolling starts.

  • OnEndScrolling UnityEvent

    The event raised when after End Scroll Delay from left last scroll event.

  • onSubmit UnityEvent

    The event raised when ListView gameobject has been selected via a “submit” key you specify (default is the return key).

  • onCancel UnityEvent

    The event raised when ListView gameobject has been deselected.

  • onItemSelect UnityEvent

    The event raised when ListView item gameobject has been selected via a “submit” key you specify (default is the return key).

  • onItemCancel UnityEvent

    The event raised when ListView item gameobject has been deselected.

  • OnUpdateView UnityEvent

    The event raised when ListView view was updated.

  • OnFocusIn UnityEvent<BaseEventData>

    The event raised when ListView gameobject received focus.

  • OnFocusOut UnityEvent<BaseEventData>

    The event raised when ListView gameobject lost focus.

  • OnPointerEnterObject UnityEvent<int>

    The event raised when pointer entered on ListView item gameobject.

    Arguments: index of the item.

  • OnPointerExitObject UnityEvent<int>

    The event raised when pointer exited on ListView item gameobject.

    Arguments: index of the item.

  • OnDataSourceChanged UnityEvent<ListViewCustom<TComponent, TItem>>

    The event raised when DataSource replaced with the new list.

    Arguments: ListView instance.

Items Events

It is ListView.ItemsEvents field with list of items events. First argument is item index, second is item instance instance, third is event data.

  • PointerClick UnityEvent<int, ListViewItem, PointerEventData>

    The event raised on every pointer click on item instance.

  • FirstClick UnityEvent<int, ListViewItem, PointerEventData>

    The event raised on first pointer click with left mouse button on item instance.

  • DoubleClick UnityEvent<int, ListViewItem, PointerEventData>

    The event raised on second pointer click with left mouse button on item instance.

  • PointerUp UnityEvent<int, ListViewItem, PointerEventData>

    The event raised on pointer up on item instance.

  • PointerDown UnityEvent<int, ListViewItem, PointerEventData>

    The event raised on pointer down on item instance.

  • PointerEnter UnityEvent<int, ListViewItem, PointerEventData>

    The event raised on pointer enter on item instance.

  • PointerExit UnityEvent<int, ListViewItem, PointerEventData>

    The event raised on pointer exit on item instance.

  • Move UnityEvent<int, ListViewItem, AxisEventData>

    The event raised on move with keyboard or gamepad on item instance.

  • Submit UnityEvent<int, ListViewItem, BaseEventData>

    The event raised on submit on item instance.

  • Cancel UnityEvent<int, ListViewItem, BaseEventData>

    The event raised on cancel on item instance.

  • Select UnityEvent<int, ListViewItem, BaseEventData>

    The event raised when item instance has been selected by EventSystem.

  • Deselect UnityEvent<int, ListViewItem, BaseEventData>

    The event raised when item instance has been deselected by EventSystem.

  • Resize UnityEvent<int, ListViewItem, Vector2>

    The event raised when item instance size was changed.

  • MovedToCache UnityEvent<ListViewItem>

    The event raised before item instance recycled.
    Use this event to clean data, unload sprites, stop instance animations.

ListViewComponent Class

Component to display item.

Fields and properties

  • Index int

    Index of the displayed item. Negative if item not displayed or not used by ListView.

  • Owner ListViewBase

    Reference to ListView.

  • DisableRecycling bool

    Disable recycling of this instance. Used in Drag&Drop or animations (enable at the start of the animation and disable at the end).

  • GraphicsForeground Graphic[]

    References to the foreground objects like Text.

  • GraphicsBackground Graphic[]

    References to the background objects.

  • DisableRecycling bool

    If enabled prevent instance recycling until this option is disabled.

Methods

  • SetData(TItem item)

    Set data to display.
    This method can be called when Index < 0 if ListType is variable size and PrecalculateItemSizes enabled to calculate the exact size of the items
    Check that Index >= 0 if there is need to do some additional actions only if item actually displayed.
  • SelectItem()

    Select current item.

  • DeselectItem()

    Deselect current item.

  • RemoveItem()

    Remove current item from the ListView.DataSource.

  • GraphicsColoring(Color foregroundColor, Color backgroundColor, float fadeDuration)

    Called by ListView to set colors for the GraphicsForeground and GraphicsBackground.

  • MovedToCache()

    Called by ListView when GameObject moved to cache or recycled to unload unused resources like sprites.

  • StateDefault()

    Called by ListView when item in the default state.

  • StateSelected()

    Called by ListView when item selected.

  • StateHighlighted()

    Called by ListView when item highlighted.

  • Vector2 GetInstanceSize(int index)

    Get the size of the instance for the item with the specified index. Used to animate items resize without problems with virtualization.

  • SetInstanceSize(int index, Vector2 size)

    Set the size of the instance for the item with the specified index. UpdateView() should be called after it to apply changes. Used to animate items resize without problems with virtualization.

  • ResetInstanceSize(int index)

    Reset the size to the default for the item with the specified index. UpdateView() should be called after it to apply changes. Used to animate items resize without problems with virtualization.

Auto-Resize DefaultItem Instances on ListView Resize and Keep Aspect Ratio

  • DefaultItem.RectTransform anchors should be set to the horizontal or vertical stretch depending on ListView.Direction

  • Add Aspect Ratio Fitter to the DefaultItem and set Aspect Mode = Width Controls Height or Height Controls Width depending on ListView.Direction

  • Change ListView.ListType to List View With Variable Size or Tile View With Variable Size

  • Make sure that ListView.Container.EasyLayout children size set to Do Nothing.

ListView with Items of Variable Size

ListView and TileView can display items with different heights or widths (it cannot be both at the same time).

  1. ListView.DefaultItem: add layout group component (it can be Horizontal Layout Group, Vertical Layout Group, or EasyLayout)
    • in case of Horizontal Layout Group or Vertical Layout Group: enable Height for Control Child Size, specify Padding and Spacing if needed.

    • in case of EasyLayout: change Children Height to Set Preferred, specify Margin and Spacing if needed.

    If the ListView Direction is Horizontal then use width related options instead of height. LayoutElement component can be to DefaultItem to specify minimal width or height and other options.

    ../../_images/ListView-DefaultItem-LayoutGroup.png
  2. ListView.Container: change Children Height to Set Preferred in EasyLayout component
    ../../_images/ListView-EasyLayout.png
3 ListView: change List Type to List View With Variable Size, Tile View With Variable Size, or Tile View Staggered
../../_images/ListViewType.png

Layout group will resize nested game objects and determine the size of each item. EasyLayout will resize those items and ListView will correctly process items with different sizes.

Multiple DefaultItems

You can create a component with the IListViewTemplateSelector<TComponent, TItem> interface implementation and add this component to the widget.

Note

ListView also has the TemplateSelector property, which can be used to specify template selectors.
But it does not support all functionality (like changing colors and UI Themes support) in the editor.
namespace UIWidgets.Examples
{
        using UnityEngine;

        public class GroupMultipleListViewSelector : MonoBehaviour, IListViewTemplateSelector<GroupMultipleComponent, GroupMultipleItem>
        {
                [SerializeField]
                public GroupMultipleComponent GroupTemplate;

                [SerializeField]
                public GroupMultipleComponent CheckboxTemplate;

                [SerializeField]
                public GroupMultipleComponent ValueTemplate;

                public GroupMultipleComponent[] AllTemplates()
                {
                        return new[] { GroupTemplate, CheckboxTemplate, ValueTemplate };
                }

                public GroupMultipleComponent Select(int index, GroupMultipleItem item)
                {
                        switch (item.Mode)
                        {
                                case GroupMultipleItem.ItemMode.Group:
                                        return GroupTemplate;
                                case GroupMultipleItem.ItemMode.Checkbox:
                                        return CheckboxTemplate;
                                case GroupMultipleItem.ItemMode.Value:
                                        return ValueTemplate;
                        }

                        throw new ArgumentOutOfRangeException(nameof(item), item.Mode, "Unsupported Item Mode");
                }
        }
}

IListViewTemplateSelector Interface

Methods:

  • TComponent[] AllTemplates()

    Get all possible templates.

  • TComponent Select(int index, TItem item);

    Returns template to use for specified item with index.

DefaultItem Instances

// also available .Active and .Cache modes
foreach (var instance in ListView.GetComponentsEnumerator(PoolEnumeratorMode.All))
{
        // do somethind with DefaultItem instance
}

Add Item

var new_item = new ListViewIconsItemDescription()
{
        Icon = sampleIcon,
        Name = "test item",
};
listView.DataSource.Add(new_item);

Get Items

var items = listView.DataSource;

Set Items

var items = new ObservableList<ListViewIconsItemDescription>();
listView.DataSource = items;

var items2 = new List<ListViewIconsItemDescription>();
listView.DataSource = items2.ToObservableList();

Display Same List with ListView, TileView or Table

var items = new ObservableList<ListViewIconsItemDescription>();
listView.DataSource = items;
tileView.DataSource = items;
table.DataSource = items;

Get Last Selected Index

Debug.Log(listView.SelectedIndex);

Get Selected Indices

var indices = listView.SelectedIndices;
Debug.Log(string.Join(", ", indices.ConvertAll(x => x.ToString()).ToArray()));

Last Selected Item

Debug.Log(listView.SelectedItem.Name);

Get Selected Items

var selected_items = listView.SelectedItems;
Debug.Log(string.Join(", ", selected_items.ConvertAll(x => x.Name).ToArray()));

Delete Specified Item

listView.DataSource.Remove(items[0]);

Delete Item by Index

listView.DataSource.RemoveAt(0);

Clear List

listView.DataSource.Clear();

Add Items

var new_items = new List<ListViewIconsItemDescription>()
{
        new_item,
        new_item,
        new_item,
};
listView.DataSource.AddRange(new_items);

Optimization

// Use BeginUpdate() and EndUpdate() to keep widget from updating on each change.
// All changes after BeginUpdate() call will be displayed with EndUpdate() call
// or after value returned by BeginUpdate() was disposed.

void AddItems()
{
        var items = listView.DataSource;
        using var _ = items.BeginUpdate();

        items.Clear();
        items.Add(new_item);
        items.Add(new_item);
        items.Add(new_item);
        items.AddRange(new_items);
        items.RemoveAt(0);

        // widget will be updated at function end
}

void AddItemsV2()
{
        var items = listView.DataSource;
        using (var _ = items.BeginUpdate())
        {
                items.Clear();
                items.Add(new_item);
                items.Add(new_item);
                items.Add(new_item);
                items.AddRange(new_items);
                items.RemoveAt(0);
        } // widget will be updated at end of the 'using' block

        // .., other code
}

Replace Item

listView.DataSource[0] = new ListViewIconsItemDescription()
{
        Name = "new item"
};

Sort

// Sort by LocalizedName or Name in ascending order
Comparison<ListViewIconsItemDescription> ItemsComparisonAsc = (x, y) => x.Name.CompareTo(y.Name);

// sort by LocalizedName or Name in descending order
Comparison<ListViewIconsItemDescription> ItemsComparisonDesc = (x, y) => -(x.Name).CompareTo(y.Name);

// sort items only once
items.Sort(ItemsComparisonAsc);

Enable Permanent Sort

items.Comparison = ItemsComparisonDesc;

Important

Items will be always sorted, but if you use .BeginUpdate() then items will be re-sorted only after .EndUpdate() call or after value returned by BeginUpdate() was disposed.

Disable Permanent Sort

items.Comparison = null;

Set Selected Index

listView.SelectedIndex = 1;

Or:

listView.Select(1);

Behavior is different if you enable MultipleSelect:

  • listView.SelectedIndex = 1 last selected item will be deselected and specified item will be selected.

  • listView.Select(1) new item will be added to selected items.

Deselect

listView.SelectedIndex = -1;

Or:

listView.Deselect(1);

Adding Callbacks to Custom Events of the Components

public class YourListView : ListViewCustom<YourListViewItemComponent, YourListViewItem>
{
         protected override void AddCallback(ListViewItem item)
         {
                       base.AddCallback(item);
                       item.onDoubleClick.AddListener(ProcessDoubleClick);
         }

         protected override void RemoveCallback(ListViewItem item)
         {
                       base.RemoveCallback(item);
                       item.onDoubleClick.RemoveListener(ProcessDoubleClick);
         }

         void ProcessDoubleClick(int index)
         {
                       Debug.Log("double click: " + DataSource[index]);
         }
}

Scroll to Item

listView.ScrollToAnimated(index);

Disable Items

protected virtual void Start()
{
        listView.CanSelect = CanBuy;
}

bool CanBuy(Item item)
{
        return player.Money >= item.Price;
}

Stop Animations

protected virtual void Start()
{
        ListView.ItemsEvents.MovedToCache.AddListener(StopAnimations);
}

void StopAnimations(int index, ListViewItem instance)
{
        instance.StopSelectableAnimations();
        instance.Animator.ResetTrigger("customState");
}

Prevent Instance Recycling

You can prevent instance recycling if some action is running (like drag&drop) and the instance should be available until it ends.

protected override void InitDrag(PointerEventData eventData)
{
        Instance.DisableRecycling = true;
        // ....
}

public override void Dropped(bool success)
{
        Instance.DisableRecycling = false;
        // ...
}

Filter

A ObservableListFilter<T> is available to filter the ObservableList<T>. It accepts the input list and predicate; and provides an output list with items that match the predicate.

using UIWidgets;
using UnityEngine;

public class TestFilter : MonoBehaviour
{
        public ListViewIcons ListView;

        public InputFieldAdapter InputField;

        ObservableListFilter<ListViewIconsItemDescription> Filter;

        void Start()
        {
                Filter = new ObservableListFilter<ListViewIconsItemDescription>(ListView.DataSource, Predicate);
                ListView.DataSource = Filter.Output;
                InputField.onValueChanged.AddListener(InputFieldChanged);
        }

        void OnDestroy()
        {
                if (InputField != null)
                {
                        InputField.onValueChanged.RemoveListener(InputFieldChanged);
                }
        }

        void InputFieldChanged(string ignore) => Filter.Refresh();

        bool Predicate(ListViewIconsItemDescription item)
        {
                var name = item.LocalizedName ?? item.Name;
                return UtilitiesCompare.Contains(name, InputField.Value, false);
        }

        public void Add()
        {
                var name = string.Format("Item {0}", Filter.Input.Count.ToString());
                Filter.Input.Add(new ListViewIconsItemDescription() { Name = name });
        }
}