[UnityUI]循环滑动列表

效果图:

在这里插入图片描述
使用的是UGUI和DOTween

其中比较关键的是循环滑动和层次排序:

1.循环滑动:这里先假设显示五张图片,分别标记为0,1,2,3,4,那么当向左滑动时,序列就变为1,2,3,4,0,这里先保存4的位置,然后从4开始,4的位置和大小向3渐变,3的位置和大小向2渐变,2的位置和大小向1渐变,1的位置和大小向0渐变,0的位置直接变为原来保存的4的位置。也就是说,当向左滑动时,最左端的那张图片特殊处理,其余的向左推进;当向右滑动时,最右端的那张图片特殊处理,其余的向右推进。

2.层次排序:由于使用的是UGUI,UI的排序跟在Hierarchy的位置有关。如果图片缩放得越小,就认为它越远离屏幕,因此就越靠前,会被后面的图片遮住。注意的是在缩放动画播放时,localScale是不确定的,因此要直接将当前位置的下一个位置的localScale传入,从而计算图片的"深度"。还有就是使用SetSiblingIndex时要完全确定好所有图片的排序。

using UnityEngine;
using System.Collections.Generic;
using DG.Tweening;

public class ScrollView : MonoBehaviour {

public int xOffset = 1;//x轴偏移
public int yOffset = 0;//y轴偏移
public float scale = 0.8f;//缩放倍数
public float time = 0.5f;//偏移与缩放动画的播放时间

private int left;//最左端的编号
private int right;//最右端的编号
public int itemAmount = 5;//展示的图片数
public Vector3 middlePos;//最中间的位置

public GameObject itemPrefab;
private GameObject canvas;
private GameObject[] sortArray;
private List<GameObject> list = new List<GameObject>();

private void InstantiateItem(Vector3 pos,float scale)
{
	GameObject go = Instantiate(itemPrefab) as GameObject;
    go.transform.SetParent(canvas.transform);
    go.transform.localPosition = pos;
	go.transform.localScale *= scale;

    InsertToSortArray(go, go.transform.localScale.x);
	list.Add(go);
}

public void Init()
{
    left = 0;
    right = itemAmount - 1;
    canvas = GameObject.Find("Canvas");
    sortArray = new GameObject[itemAmount];

	int oneSideAmount = (itemAmount - 1) / 2;

	for(int i = oneSideAmount;i >= 1;i--)
	{
		Vector3 pos = middlePos + new Vector3(i * xOffset,i * yOffset,0) * -1;
		InstantiateItem(pos,Mathf.Pow(scale,i));
	}

	InstantiateItem(middlePos,1);

	for(int i = 1;i <= oneSideAmount;i++)
	{
		Vector3 pos = middlePos + new Vector3(i * xOffset,i * yOffset,0);
		InstantiateItem(pos,Mathf.Pow(scale,i));
	}

    Sort();
}

/// <summary>
/// 根据缩放倍数计算深度
/// </summary>
/// <param name="scaleNum"></param>
/// <returns></returns>
private int CalculateDepth(float scaleNum)
{
    float num = 0;
    int i = 0;
    while (true)
    {
        num = Mathf.Pow(scale, i);
        if (num != scaleNum) i++;
        else break;
    }
    return i;
}

/// <summary>
/// 插入到排序数组中,数组序号越低,则越远离屏幕
/// </summary>
/// <param name="go"></param>
/// <param name="localScaleX"></param>
private void InsertToSortArray(GameObject go, float localScaleX)
{
    int depth = CalculateDepth(localScaleX);
    depth = itemAmount / 2 - depth;

    if (depth == itemAmount / 2)
        sortArray[depth * 2] = go;
    else if (sortArray[depth] == null)
        sortArray[depth] = go;
    else
        sortArray[depth + itemAmount / 2] = go;   
}

private void Sort()
{
    for (int i = 0; i < itemAmount; i++)
    {
        sortArray[i].transform.SetSiblingIndex(i);
    }
    sortArray = new GameObject[itemAmount];
}

public void Move(int direction)
{
	if(direction == -1)//向左滑动
	{
		int startIndex = left;
		int lastIndex = right;
        Vector3 lastPos = list[lastIndex].transform.position;

        InsertToSortArray(list[startIndex], list[startIndex].transform.localScale.x);

        for (int i = 0; i < itemAmount - 1;i++ )
        {
            int index = (lastIndex - i + itemAmount) % itemAmount;
            int preIndex = (index - 1 + itemAmount) % itemAmount;
            list[index].transform.DOMove(list[preIndex].transform.position,time);
            list[index].transform.DOScale(list[preIndex].transform.localScale,time);

            InsertToSortArray(list[index], list[preIndex].transform.localScale.x);
        }
        			
		list[startIndex].transform.DOMove(lastPos,time);
        
        left = (left + 1) % itemAmount;
        right = (right + 1) % itemAmount;
	}
    else if (direction == 1)//向右滑动
	{
        int startIndex = right;
        int lastIndex = left;
        Vector3 lastPos = list[lastIndex].transform.position;

        InsertToSortArray(list[startIndex], list[startIndex].transform.localScale.x);

        for (int i = 0; i < itemAmount - 1; i++)
        {
            int index = (lastIndex + i + itemAmount) % itemAmount;
            int preIndex = (index + 1 + itemAmount) % itemAmount;
            list[index].transform.DOMove(list[preIndex].transform.position, time);
            list[index].transform.DOScale(list[preIndex].transform.localScale, time);

            InsertToSortArray(list[index], list[preIndex].transform.localScale.x);
        }

        list[startIndex].transform.DOMove(lastPos, time);

        left = (left - 1 + itemAmount) % itemAmount;
        right = (right - 1 + itemAmount) % itemAmount;
	}

	Sort();
}

}

不足之处:

1.只适用于展示图片数为奇数的场合

2.等等…

作者:宏哥1995
来源:CSDN
原文:https://blog.csdn.net/lyh916/article/details/46984789

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值