Skip to main content

Virtual List

Also known as the "infinite list," this list allows you to add large-scale data without significantly affecting performance.

MilListView maintains an object pool of list item objects. During the Awake phase, it determines the size of list items, then automatically reuses the list item objects and controllers through related calculations. In other words, not every piece of data has a dedicated list item object and controller bound to it. Instead, based on the portion of the list currently visible, the data for that portion is dynamically assigned to a limited number of list item objects and controllers, which then render them in the scene.

Virtual List Items

First, you need to implement a list item controller by extending the abstract class MilListViewItem, which handles the appearance logic and interaction logic of list items.

Animation Settings

Override the list item's Default state (optional, defaults to empty):

protected override IEnumerable<MilStateParameter> ConfigDefaultState()
=> MAni.States(() =>
...
);

Override the list item's Selected state (optional, defaults to empty):

protected override IEnumerable<MilStateParameter> ConfigSelectedState()
=> MAni.States(() =>
...
);
info

If no UI animation is needed for the list item, both methods can simply return null.

You can also configure the click animation of the list item by implementing the ConfigClickAnimation method. The configured animation will play when the list item is clicked; if not needed, return null.

protected override MilInstantAnimator ConfigClickAnimation()
=> ...;

Updating Appearance

For example, if the list item data is a string, implement the logic:

public override void UpdateAppearance()
{
if (Binding is string str)
{
text.text = str;
}
}

Here, Binding is the data currently bound to the list item, assigned by MilListView.

Milease also provides a control function to adjust the appearance based on the current position of the list item. The parameter pos ranges from [0,1][0, 1], representing the relative position of the list item within the entire list.

For example, to make the text color most red at the center of the list:

public override void AdjustAppearance(float pos)
{
var p = 1f - Mathf.Abs(pos - 0.5f) / 0.5f;
text.color = Color.Lerp(Color.black, Color.red, p);
}

Event Handling

// Select the current list item
public override void OnSelect(PointerEventData eventData)
{

}

// Initialization event
protected override void OnInitialize()
{

}

// Termination event
protected override void OnTerminate()
{

}
warning

The Awake and OnDestroy methods are occupied by MilListViewItem. Instead, you can write related logic in the provided OnInitialize and OnTerminate events.

Other Properties

  • Index: The index of the data bound to the current list item within the Items of MilListView.

  • ParentListView: The MilListView to which the current list item belongs.

  • DefaultTransition: Duration of the transition to the Default state.

  • HoverTransition: Duration of the transition to the Hover and Selected states.

  • OnSelectEvent: You can additionally bind methods here to be called when the list item is selected.

Setting Up the Virtual List

Since the virtual list needs to receive UI events, the raycast of the UI it belongs to must be enabled to respond to clicks, scrolls, and other interactions.

You can add a MilListView component on an Image, then create your list item objects as children of this Image (the root object of the list item must implement a concrete class derived from MilListViewItem).

Then, drag your list item object into the ItemPrefab field of the MilListView.

Properties

Interaction part:

  • Interactable: Whether to handle selection events. If disabled, clicking a list item will not trigger the OnSelect function.
  • Scrollable: Whether the list can be scrolled.
  • Mouse Scroll Sensitivity: Scroll sensitivity (also applies to mobile scrolling sensitivity).

Appearance part:

  • Vertical: Whether the list layout is vertical; otherwise, it is horizontal.
  • Spacing: The spacing between list items.
  • Start Padding: Distance from the first list item to the list boundary.
  • End Padding: Distance from the last list item to the list boundary.
  • Indentation: Indentation size of list items.
  • Align: Alignment of list items.

Extended options:

  • LoopList: Whether to enable the "looping list". When enabled, the last item connects to the first, allowing infinite scrolling.
  • Scrollbar: The scrollbar component of the list.

Events:

  • OnScrollDone: Triggered when scrolling ends.

Using the Virtual List

Data Operations

Add data to the virtual list:

listView.Add(obj);

The data can be of any type; it will be automatically assigned to a MilListViewItem, i.e., the Binding property you encounter when implementing MilListViewItem.

Remove data from the virtual list:

listView.Remove(index);
// or
listView.Remove(obj);

Clear the data in the virtual list:

listView.Clear();

Update a specific item’s data:

// Replace the data at index with obj and update the item's appearance
listView.UpdateItem(index, obj);
info

Performing add, remove, or update operations on the list data within the OnSelect event works properly. You can even delete the currently selected list item data.

Interaction

Select a specific list item:

// This will trigger the corresponding OnSelect event
listView.Select(index);
// If you want to trigger the OnSelect event, then
listView.Select(index, true);

Scroll to the top of the list:

listView.SlideToTop();
// To skip the scroll animation and jump instantly:
listView.SlideToTop(true);

Scroll to the bottom of the list:

listView.SlideToBottom();
// To skip the scroll animation and jump instantly:
listView.SlideToBottom(true);

Scroll to a specified position:

listView.SlideTo(position);
// To skip the scroll animation and jump instantly:
listView.SlideTo(position, true);

Get the position of a specified list item (for scrolling):

listView.GetItemPosition(index);

Others

Immediately refresh all list item appearances:

listView.RefreshItemAppearance();

Get the instances of currently displayed list items (MilListViewItem):

listView.GetDisplayingItems();

Notes

warning
  • MilListView only supports list items with fixed size along the target dimension. For example, if your list is vertical, the height of list items must be fixed; if horizontal, the width must be fixed.
  • MilListView determines the size of list items during the Awake phase for subsequent calculations. Therefore, you should ensure the item size is correct at that moment.
  • For looping lists, MilListView currently only works properly when the number of visible items is greater than the total number of list items.
  • Because data is dynamically assigned to MilListViewItem, the same instance of MilListViewItem does not necessarily control the same data — the Binding and Index of a MilListViewItem instance can change dynamically.