FancyScrollView通用UI组件

FancyScrollView通用UI组件

一、简介

FancyScrollView是一个可以实现复杂灵活动画效果的通用UI滑动列表组件,可以帮助开发者快速实现表现力丰富的UI滑动列表。

开源库链接:https://lab.uwa4d.com/lab/5bc4219e04617c5805d4d3a1

二、创建一个FancyScrollView

以示例项目中最基础的第一个例子为例,来看一下如何使用FancyScrollView实现一个动画滑动列表。

1、创建一个ItemData类,用于存放每个单元中所需的数据。

public class ItemData
{
    public string Message { get; }
    public ItemData(string message)
    {
        Message = message;
    }
}

2、创建一个Cell类,继承自FancyCell。其中有两个主要函数,UpdateContent用于刷新UI上对应ItemData中的数据内容,UpdatePosition用于控制每个Cell的滑动效果,包括位置、动画等。在Example01中,使用了Animator来控制动画。

public class MyCell : FancyCell<ItemData>
{
    [SerializeField] Animator animator = default;
    [SerializeField] Text message = default;


    public override void UpdateContent(ItemData itemData)
    {
        message.text = itemData.Message;
    }


    public override void UpdatePosition(float position)
    {
        // position 是 0.0 ~ 1.0 之间的值
        // 基于position可以自由控制Scroll的外观
        if (animator.isActiveAndEnabled)
        {
            animator.Play(AnimatorHash.Scroll, -1, position);
        }


        animator.speed = 0;
    }
}

3、创建一个ScrollView类,继承自FancyScrollView

public class MyScrollView : FancyScrollView<ItemData>
{
    [SerializeField] Scroller scroller = default;
    [SerializeField] GameObject cellPrefab = default;


    protected override GameObject CellPrefab => cellPrefab;


    void Start()
    {
        scroller.OnValueChanged(base.UpdatePosition);
    }


    public void UpdateData(IList<ItemData> items)
    {
        base.UpdateContents(items);
        scroller.SetTotalCount(items.Count);
    }
}

4、创建一个Example01,用于初始化列表数据。

public class Example01 : MonoBehaviour
{
    [SerializeField] MyScrollView myScrollView = default;


    void Start()
    {
        var items = Enumerable.Range(0, 20)
            .Select(i => new ItemData($"Cell {i}"))
            .ToArray();


        myScrollView.UpdateData(items);
    }
}

5、创建一个Cell Prefab,为它制作一个好看的动画效果,并创建制作好对应的AnimatorController。

6、组装好这些GameObject后,即可得到一个FancyScrollView效果啦。

三、其它功能及应用

1、无限循环
如果希望实现头尾相接的循环列表,只需要设置两个选项:勾选FancyScrollView的“Loop”,并将Scroller的Movement Type设定为Unrestricted即可。

2、捕捉(Snap)


启用Snap之后,在滑动快结束时会定位到最近的一个单元,而不会停留在中间状态。这也是滑动列表非常常用的功能。同时还可以调整这里定位的速度、时长、EasingType等参数。

3、结合Shader制作列表背景
在示例4和示例5中,展示了如何使用Shader制作出表现力更丰富的滑动列表。这里给出的两个例子分别是Metaball和Voronoi效果的应用。


在Metaball.hlsl中,可以找到Shader实现的核心方法。

float4 metaball(float2 st)
{
    float scale = 4600;
    float d = 0;


    [unroll]
    for (int i = 0; i < DATA_COUNT; i++)
    {
        d += f(st - _CellState[i].xy) * _CellState[i].w;
    }


    d *= scale;
    d = abs(d - 0.5);


    float3 color = 1;
    color = lerp(color, float3(0.16, 0.07, 0.31), smoothstep(d - 0.04, d - 0.04 + 0.002, 0));
    color = lerp(color, float3(0.16, 0.80, 0.80), smoothstep(d - 0.02, d - 0.02 + 0.002, 0));
    return float4(color, 1)
}

其中_CellState为ScrollView中的Cell数据集合。xy对应的是每个Cell的位置position数据,w对应的是每个cell的缩放scale数据。

4、ScrollRect和GridView
除了常规的滑动列表外,FancyScrollView还提供了行列类的滑动列表,且在示例工程中,提供了如果修改Cell单元间距、顶距等配置方式。但这两种ScrollView不支持无限循环和捕捉功能。

四、性能测评

效果虽好,但由于这里面每个cell都用到一个Animator,在性能上也是有不少开销的。博物纳新惯例,使用UWA GOT在红米4X上测试了一下最基础示例的性能开销。

1、滑动测试
使用基础示例测试了一下持续滑动列表的情况。发现动画更新耗时和UI重建的开销在列表滑动时都比较高,是两个主要耗时函数,其耗时均值分别达到1.9ms和1.6ms。


Animators.Update耗时情况


SendWillRenderCanvases耗时情况

2、静止测试
使用同一个示例测试了一下静止状态的列表。则动画更新耗时和UI重建耗时都明显下降。耗时均值分别为0.3ms和0ms(<0.05ms)。


Animators.Update耗时情况


SendWillRenderCanvases耗时情况

五、总结

FancyScrollView可以帮助开发者快速实现灵活复杂的滑动列表动画,但如果是使用Animator的方式实现,带来的动画更新开销也会偏高一些,更适合在其它CPU压力不大的场景下使用,且需要注意制作的动画及动画状态机不宜过于复杂。

作者发布项目时的介绍使用的是日文编写,为了方便大家阅读,UWA开源库已将其翻译成中文版本,欢迎大家共同学习:https://lab.uwa4d.com/lab/5bc4219e04617c5805d4d3a1

今天的推荐就到这儿啦,或者它可直接使用,或者它需要您的润色,或者它启发了您的思路......

请不要吝啬您的点赞和转发,让我们知道我们在做对的事。当然如果您可以留言给出宝贵的意见,我们会越做越好。


【博物纳新】是UWA旨在为开发者推荐新颖、易用、有趣的开源项目,帮助大家在项目研发之余发现世界上的热门项目、前沿技术或者令人惊叹的视觉效果,并探索将其应用到自己项目的可行性。很多时候,我们并不知道自己想要什么,直到某一天我们遇到了它。

更多精彩内容请关注:lab.uwa4d.com