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

原文:http://blog.csdn.net/lyh916/article/details/46984789

猜你喜欢

转载自blog.csdn.net/abcd5711664321/article/details/78042005