虚拟列表
又称“无限列表”,该列表允许你向列表中添加大规模的数据,而其性能几乎不会受到影响。
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
的数值范围是 ,表示当前列表项在整个列表中的位置的占比。
例如,我们需要使文本在列表中央时的颜色最红:
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()
{
}
Awake
和 OnDestory
方法已被 MilListViewItem
占用,替代地,你可以在提供的 OnInitialize
和 OnTerminate
事件中编写相关逻辑。
其他属性
-
Index:当前列表项绑定的数据在
MilListView
中的Items
的序号。 -
ParentListView:当前列表项所属的
MilListView
-
DefaultTransition:过渡到
Default
状态的时长 -
HoverTransition:过渡到
Hover
和Selected
状态的时长 -
OnSelectEvent:你可以在此处额外绑定列表项被选中时要调用的方法
设置虚拟列表
由于虚拟列表需要接收 UI 事件,它所在的 UI 的 raycast
应当启动,才能响应点击、滚动等操作。
你可以在一个 Image 上添加 MilListView
组件,然后在这个 Image 的节点下,创建你的列表项物体(列表项物体的根物体上要有实现了 MilListViewItem
的具体类)。
随后,把你的列表项物体拖动至 MilListView
的 ItemPrefab
即可。
属性
交互部分:
- 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
实例得到的Binding
和Index
是会动态变化的。