- Home /
Add to list/scroll view in script,Add ui object to listview in code
I'm creating a 2D game with a hud built in UI Toolkit
, and I'd like to add a section of it for communications. In theory It would just be a text box with a scroll bar and new lines added via script in runtime. I've read through the list and scrollview documentation, but I don't know how to dynamically add lines to an existing box. Has anyone made something like this before?
I'm using Unity 2021.1.7f1
and the "com.unity.ui.builder": "1.0.0-preview.14"
, and I've created a 'HUD' for my 2d game. I've like to allow for one section on the Hud to represent communications received, essentially to have a scrollable section of text that I can add to in runtime. I've read the documentation and I just don't get how to add a label to the existing object while the game is running.
Answer by andrew-lukasik · Jun 05, 2021 at 09:16 PM
download source assets
TextListView.cs
using System.Collections.Generic;
using UnityEngine.UIElements;
[UnityEngine.Scripting.Preserve]
public class TextListView : VisualElement
{
ListView _listView;
public List<string> itemsSource {
get => _listView.itemsSource as List<string>;
set => _listView.itemsSource = value;
}
public int itemHeight { get; set; }
public string initialItems { get; set; }
public void ClearItems ()
{
_listView.itemsSource.Clear();
_listView.Refresh();
}
public void AddItem ( string value )
{
_listView.itemsSource.Add( value );
_listView.Refresh();
}
public void RemoveItem ( string value )
{
_listView.itemsSource.Remove( value );
_listView.Refresh();
}
public void RemoveItemAt ( int index )
{
_listView.itemsSource.RemoveAt( index );
_listView.Refresh();
}
public new class UxmlFactory : UxmlFactory<TextListView,UxmlTraits> {}
public new class UxmlTraits : VisualElement.UxmlTraits
{
UxmlIntAttributeDescription _itemHeight = new UxmlIntAttributeDescription{ name="item-height" , defaultValue=32 };
UxmlStringAttributeDescription _initialItems = new UxmlStringAttributeDescription{
name = "initial-items" ,
defaultValue = "Wlazł kotek na płotek i mruga,;piękna to piosneczka niedługa.;Wlazł kurek na murek i pieje;niech się nikt z tych piosnek nie śmieje."
};
public override void Init ( VisualElement ve , IUxmlAttributes bag , CreationContext cc )
{
base.Init( ve , bag , cc );
var ROOT = ve as TextListView;
ROOT.Clear();
ROOT.itemHeight = _itemHeight.GetValueFromBag( bag , cc );
ROOT.initialItems = _initialItems.GetValueFromBag( bag , cc );
var LISTVIEW = new ListView();
LISTVIEW.style.flexGrow = 1;
{
LISTVIEW.itemsSource = new List<string>( ROOT.initialItems.Split(';') );
LISTVIEW.itemHeight = ROOT.itemHeight;
LISTVIEW.makeItem = () => new Label();
LISTVIEW.bindItem = (item,i) =>
{
string entry = (string) LISTVIEW.itemsSource[i];
Label label = (Label) item;
label.text = entry;
};
}
ROOT.Add( LISTVIEW );
ROOT._listView = LISTVIEW;
}
}
}
MyUiController.cs
using System.Collections;
using UnityEngine;
using UnityEngine.UIElements;
public class MyUiController : MonoBehaviour
{
[SerializeField] UIDocument _uiDocument = null;
TextListView _view = null;
void OnEnable ()
{
_view = _uiDocument.rootVisualElement.Q<TextListView>();
StartCoroutine( nameof(Testing) );
}
IEnumerator Testing ()
{
var sec = new WaitForSeconds(1);
_view.ClearItems(); yield return sec;
_view.AddItem("3..."); yield return sec;
_view.AddItem("2..."); yield return sec;
_view.AddItem("1..."); yield return sec;
_view.AddItem("Testing");
}
}
I tried this out but unfortunately I can't get this line to work:
_view = _uiDocument.rootVisualElement.Q<TextListView>();
I've tried to get this working with a few other methods, the most promising is rootVisualElement.Q();, but this doesn't work even though it claims there is a specific cast. It seems so close and I am grateful for you taking the time to answer me, but I cannot figure how to get the actual component.
If you want to use multiple TextListView
instances in a single panel then fill their Name
property in UI Builder
window and then find these individual elements by their names:
_messagesView = _uiDocument.rootVisualElement.Q<TextListView>( "messages" );
_happyThoughtsView = _uiDocument.rootVisualElement.Q<TextListView>( "happy_thoughts" );
Your answer
Follow this Question
Related Questions
Adding value from a clone object to score 4 Answers
UI ToolKit Missing Scripts? 0 Answers
To pass a variable between scenes should I use scriptableobject or static ? 1 Answer
How can I improve my trading script? 1 Answer
How do I make do I make a variable go back to its original value for a spell system 1 Answer