zoukankan      html  css  js  c++  java
  • [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.等等...

  • 相关阅读:
    sonarqube代码质量检测工具安装(docker安装篇)
    jenkins-job构建完成后通知企业微信
    jenkins-构建job成功后自动打tag到git仓库
    初识Python-变量
    初识Python-文件类型(入坑篇)
    kubernetes-部署LNMP环境运行Discuz
    harbor部署常见的错误
    kubernetes-部署harbor
    Google Hacking语法
    信息搜集总结
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/7009651.html
Copyright © 2011-2022 走看看