跳到主要内容

虚拟列表

又称“无限列表”,该列表允许你向列表中添加大规模的数据,而其性能几乎不会受到影响。

MilListView 将维护一个列表项物体的对象池,在 Awake 阶段确定列表项的尺寸,随后通过相关计算,自动复用列表项物体和列表项控制器。也就是说,并不是每一个数据都有一个列表项物体和列表项控制器与之绑定,而是根据当前列表能显示的部分,动态地将这部分的数据分配给有限的列表项物体和列表项控制器,让他们将其呈现在场景中。

虚拟列表项

首先,我们需要通过实现抽象类 MilListViewItem 编写一个列表项控制器,处理列表项的外观逻辑和交互逻辑。

动画设置

覆写列表项的 Default 状态(可选,默认为空):

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

覆写列表项的 Selected 状态(可选,默认为空):

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

若不需要列表项的 UI 动画,则两个方法均返回 null 即可。

你也可以通过实现 ConfigClickAnimation 函数配置列表项的点击动画,配置的动画将在该列表项被点击时播放;若不需要,则返回 null 即可。

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

解释外观

例如,我们的列表项数据可能是 string,编写逻辑:

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

其中,Binding 是当前列表项绑定的数据,它由 MilListView 进行分配。

同时,Milease 也提供了一种可以根据列表项当前的位置变化外观的控制函数,其中参数 pos 的数值范围是 [0,1][0, 1] ,表示当前列表项在整个列表中的位置的占比。

例如,我们需要使文本在列表中央时的颜色最红:

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);
}

事件处理

// 选择当前列表项
public override void OnSelect(PointerEventData eventData)
{

}

// 初始化事件
protected override void OnInitialize()
{

}

// 销毁事件
protected override void OnTerminate()
{

}
注意

AwakeOnDestory 方法已被 MilListViewItem 占用,替代地,你可以在提供的 OnInitializeOnTerminate 事件中编写相关逻辑。

其他属性

  • Index:当前列表项绑定的数据在 MilListView 中的 Items 的序号。

  • ParentListView:当前列表项所属的 MilListView

  • DefaultTransition:过渡到 Default 状态的时长

  • HoverTransition:过渡到 HoverSelected 状态的时长

  • OnSelectEvent:你可以在此处额外绑定列表项被选中时要调用的方法

设置虚拟列表

由于虚拟列表需要接收 UI 事件,它所在的 UI 的 raycast 应当启动,才能响应点击、滚动等操作。

你可以在一个 Image 上添加 MilListView 组件,然后在这个 Image 的节点下,创建你的列表项物体(列表项物体的根物体上要有实现了 MilListViewItem 的具体类)。

随后,把你的列表项物体拖动至 MilListViewItemPrefab 即可。

属性

交互部分:

  • Interactable:是否处理选中事件,若未启用,点击列表项将不会触发 OnSelect 函数。
  • Scrollable:列表是否可以滚动。
  • Mouse Scroll Sensitivity:滚动灵敏度(同样作用于移动端的滚动灵敏度)

外观部分:

  • Vertical:是否为“垂直”布局的列表,否则是“水平”布局的列表。
  • Spacing:列表项之间的间距。
  • Start Padding:首个列表项距离列表边界的距离。
  • End Padding:最后一个列表项距离列表边界的距离。
  • Indentation:列表项缩进尺寸。
  • Align:列表项的对齐方式。

扩展选项:

  • LoopList:是否启用“循环列表”,启用后,列表的最后一项将与第一项相接,可以无限滚动。
  • Scrollbar:列表的滚动条组件。

事件:

  • OnScrollDone:当滚动结束时触发。

使用虚拟列表

数据操作

向虚拟列表添加数据:

listView.Add(obj);

这个数据可以是任意的类型,最后它将自动分配给某一个 MilListViewItem,也就是你在实现 MilListViewItem 时接触到的 Binding 属性。

从虚拟列表中移除数据:

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

清空虚拟列表的数据:

listView.Clear();

更新某一项的列表数据:

// 将列表中第 index 个数据替换成 obj,并更新列表项外观
listView.UpdateItem(index, obj);
信息

在 OnSelect 事件中,对列表数据做增删改操作是可以正常工作的,你甚至可以删除当前正在选中的列表项数据。

交互

选中指定的列表项:

// 这将会触发对应的 OnSelect 事件
listView.Select(index);
// 如果你希望触发 OnSelect 事件,则
listView.Select(index, true);

滚动至列表的顶部:

listView.SlideToTop();
// 若不需要滚动过渡动画,使得列表位置瞬间跳跃,则需要:
listView.SlideToTop(true);

滚动至列表的底部:

listView.SlideToBottom();
// 若不需要滚动过渡动画,使得列表位置瞬间跳跃,则需要:
listView.SlideToBottom(true);

滚动至指定位置:

listView.SlideTo(position);
// 若不需要滚动过渡动画,使得列表位置瞬间跳跃,则需要:
listView.SlideTo(position, true);

获取指定列表项的位置(用于滚动):

listView.GetItemPosition(index);

其他

立即更新全部列表项的外观:

listView.RefreshItemAppearance();

获得当前正在显示的列表项的 MilListViewItem 实例:

listView.GetDisplayingItems();

注意事项

注意
  • MilListView 仅支持在目标维度上固定尺寸的列表项。例如,当你的列表是垂直列表,你的列表项的高度必定是固定的;当你的列表是水平列表,你的列表项的宽度必定是固定的。
  • MilListView 将在 Awake 阶段确定列表项的尺寸用于后续的计算。因此,你应该确保在这个时刻,列表项的尺寸是正确的。
  • 对于循环列表,MilListView 当前仅在 列表显示的项的个数 多于 列表项的总个数 时可以正常工作。
  • 由于数据是动态分配给 MilListViewItem 的,因此,它们并不一定控制的一直是同一个数据,即同一个 MilListViewItem 实例得到的 BindingIndex 是会动态变化的。