ItemView
Overview
While UIBlocks are Nova's building blocks, useful for constructing and styling your content hierarchy, they only get you so far when it comes to creating a dynamic, interactve user interface. Another common aspect of building user interfaces is displaying data objects. e.g. a contact, systems setting, chat message, etc., from the game or application to its users and allowing them to interact with the information presented.
This is where the ItemView component comes in handy. When building content in Nova, you'll create groups of visual elements out of UIBlocks, and the combination of these visual elements within the group becomes a visual representation of a given data object. Nova refers to this conceptual grouping as a view, and the ItemView component is Nova's view type for representing any single data object.
ItemViews act as a common access point to map data elements to visual elements, target events to a custom view type, and can be part of larger views displayed in a List or Grid.
ItemVisuals
Every ItemView component has a Visuals property, holding visual elements used to display each data element of the data object the given ItemView is intended to represent. The Visuals object is something you define by creating a new class which inherits from ItemVisuals.
Setup
Let's look at a concrete example. Here's a data type called Contact
, which stores a UserID
, UserName
, and Photo
:
/// <summary>
/// Data stored for each user contact.
/// </summary>
public class Contact
{
public int UserID;
public string UserName;
public Texture2D Photo;
}
Next we want to display Contact.UserName
and Contact.Photo
in our view. To achieve this goal, we start by creating a new class, ContactVisuals
, which inherits from ItemVisuals, and, for each piece of information from the Contact
object we want to display, we add a corresponding component field to our ContactVisuals
.
/// <summary>
/// Visuals for a user contact.
/// Display User Name and Photo.
/// </summary>
public class ContactVisuals : ItemVisuals
{
public TextBlock UserName;
public UIBlock2D Photo;
}
In this example, Contact.UserID
, while part of our data object, is only important for managing various contacts on the backend. Since the ContactVisuals
doesn't need to present anything related to Contact.UserID
, we can omit a visual element for that particular data element.
Now that we have our ContactVisuals
type created, we can assign it to an ItemView. In Unity, add an ItemView component to a GameObject, and select the ContactVisuals
type from the Visuals dropdown. From there you will be able to see the UserName
and Photo
fields we exposed on our ContactVisuals
type and assign them to a TextBlock
and UIBlock2D
, respectively, in the scene.
When we're ready to display the UserName
and Photo
of a given contact, all we need is a reference to the ItemView we just created, and the Contact
information we want to show.
// Serialize and assign in Unity Editor
public Contact Contact;
public ItemView ContactView;
// ...
// Grab the Visuals, and cast to our ContactVisuals type
ContactVisuals contactVisuals = ContactView.Visuals as ContactVisuals;
// Update the visuals with the details of the Contact
contactVisuals.UserName.Text = Contact.UserName;
contactVisuals.Photo.SetImage(Contact.Photo);
Note
While both of the fields we exposed are UIBlocks, the fields on an ItemVisuals can also be Unity types, custom components, or anything else that the Visuals may need to control or modify.
Gesture Targets
Any ItemVisuals type you create can be used as a Gesture target via AddGestureHandler, allowing you to handle various gestures uniquely for a particular ItemVisuals type.
The Event Target Types section of the Events article has a more in-depth explanation, but as a quick example if we add an Interactable component to the same GameObject as the ItemView we created above, we can then subscribe to and handle Gestures which occur specifically to ItemViews with ContactVisuals
assigned to the Visuals field.
See Input Overview to learn more about input in Nova.
// Subscribe to click events that occur to ContactVisuals
uiBlock.AddGestureHandler<Gesture.OnClick, ContactVisuals>(ContactClicked);
// If we repeat the steps we went through with
// ContactVisuals for a different Visuals type
//
// E.g.
//
// public class FriendVisuals : ItemVisuals { ... }
//
// we could uniquely handle click events for that type as well.
uiBlock.AddGestureHandler<Gesture.OnClick, FriendVisuals>(FriendClicked);
// ...
private void ContactClicked(Gesture.OnClick evt, ContactVisuals contact)
{
string username = contact.UserName.Text;
Debug.Log($"Contact {username} was clicked!");
}
private void FriendClicked(Gesture.OnClick evt, FriendVisuals friend)
{
Debug.Log($"Friend was clicked!");
}
Attributes
While the ItemVisuals editor dropdown is searchable, it may be desirable to further organize the editor UI for custom ItemVisuals types in projects which define a lot of them. For this reason, Nova includes the TypeMenuPathAttribute and TypeMenuNameAttribute.
The following snippet applies two changes:
- Groups
Contact Visuals
into a category calledContacts Menu
within the dropdown list - Displays the word
Contact
instead ofContact Visuals
in the dropdown list
/// <summary>
/// Visuals for a user contact.
/// Display User Name and Photo.
/// </summary>
[TypeMenuPath("Contacts Menu")]
[TypeMenuName("Contact")]
public class ContactVisuals : ItemVisuals
{
public TextBlock UserName;
public UIBlock2D Photo;
}