效果图:

使用的是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时要全然确定好全部图片的排序。

  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. using DG.Tweening;
  4.  
  5. public class ScrollView : MonoBehaviour {
  6.  
  7. public int xOffset = 1;//x轴偏移
  8. public int yOffset = 0;//y轴偏移
  9. public float scale = 0.8f;//缩放倍数
  10. public float time = 0.5f;//偏移与缩放动画的播放时间
  11.  
  12. private int left;//最左端的编号
  13. private int right;//最右端的编号
  14. public int itemAmount = 5;//展示的图片数
  15. public Vector3 middlePos;//最中间的位置
  16.  
  17. public GameObject itemPrefab;
  18. private GameObject canvas;
  19. private GameObject[] sortArray;
  20. private List<GameObject> list = new List<GameObject>();
  21.  
  22. private void InstantiateItem(Vector3 pos,float scale)
  23. {
  24. GameObject go = Instantiate(itemPrefab) as GameObject;
  25. go.transform.SetParent(canvas.transform);
  26. go.transform.localPosition = pos;
  27. go.transform.localScale *= scale;
  28.  
  29. InsertToSortArray(go, go.transform.localScale.x);
  30. list.Add(go);
  31. }
  32.  
  33. public void Init()
  34. {
  35. left = 0;
  36. right = itemAmount - 1;
  37. canvas = GameObject.Find("Canvas");
  38. sortArray = new GameObject[itemAmount];
  39.  
  40. int oneSideAmount = (itemAmount - 1) / 2;
  41.  
  42. for(int i = oneSideAmount;i >= 1;i--)
  43. {
  44. Vector3 pos = middlePos + new Vector3(i * xOffset,i * yOffset,0) * -1;
  45. InstantiateItem(pos,Mathf.Pow(scale,i));
  46. }
  47.  
  48. InstantiateItem(middlePos,1);
  49.  
  50. for(int i = 1;i <= oneSideAmount;i++)
  51. {
  52. Vector3 pos = middlePos + new Vector3(i * xOffset,i * yOffset,0);
  53. InstantiateItem(pos,Mathf.Pow(scale,i));
  54. }
  55.  
  56. Sort();
  57. }
  58.  
  59. /// <summary>
  60. /// 依据缩放倍数计算深度
  61. /// </summary>
  62. /// <param name="scaleNum"></param>
  63. /// <returns></returns>
  64. private int CalculateDepth(float scaleNum)
  65. {
  66. float num = 0;
  67. int i = 0;
  68. while (true)
  69. {
  70. num = Mathf.Pow(scale, i);
  71. if (num != scaleNum) i++;
  72. else break;
  73. }
  74. return i;
  75. }
  76.  
  77. /// <summary>
  78. /// 插入到排序数组中。数组序号越低。则越远离屏幕
  79. /// </summary>
  80. /// <param name="go"></param>
  81. /// <param name="localScaleX"></param>
  82. private void InsertToSortArray(GameObject go, float localScaleX)
  83. {
  84. int depth = CalculateDepth(localScaleX);
  85. depth = itemAmount / 2 - depth;
  86.  
  87. if (depth == itemAmount / 2)
  88. sortArray[depth * 2] = go;
  89. else if (sortArray[depth] == null)
  90. sortArray[depth] = go;
  91. else
  92. sortArray[depth + itemAmount / 2] = go;
  93. }
  94.  
  95. private void Sort()
  96. {
  97. for (int i = 0; i < itemAmount; i++)
  98. {
  99. sortArray[i].transform.SetSiblingIndex(i);
  100. }
  101. sortArray = new GameObject[itemAmount];
  102. }
  103.  
  104. public void Move(int direction)
  105. {
  106. if(direction == -1)//向左滑动
  107. {
  108. int startIndex = left;
  109. int lastIndex = right;
  110. Vector3 lastPos = list[lastIndex].transform.position;
  111.  
  112. InsertToSortArray(list[startIndex], list[startIndex].transform.localScale.x);
  113.  
  114. for (int i = 0; i < itemAmount - 1;i++ )
  115. {
  116. int index = (lastIndex - i + itemAmount) % itemAmount;
  117. int preIndex = (index - 1 + itemAmount) % itemAmount;
  118. list[index].transform.DOMove(list[preIndex].transform.position,time);
  119. list[index].transform.DOScale(list[preIndex].transform.localScale,time);
  120.  
  121. InsertToSortArray(list[index], list[preIndex].transform.localScale.x);
  122. }
  123.  
  124. list[startIndex].transform.DOMove(lastPos,time);
  125.  
  126. left = (left + 1) % itemAmount;
  127. right = (right + 1) % itemAmount;
  128. }
  129. else if (direction == 1)//向右滑动
  130. {
  131. int startIndex = right;
  132. int lastIndex = left;
  133. Vector3 lastPos = list[lastIndex].transform.position;
  134.  
  135. InsertToSortArray(list[startIndex], list[startIndex].transform.localScale.x);
  136.  
  137. for (int i = 0; i < itemAmount - 1; i++)
  138. {
  139. int index = (lastIndex + i + itemAmount) % itemAmount;
  140. int preIndex = (index + 1 + itemAmount) % itemAmount;
  141. list[index].transform.DOMove(list[preIndex].transform.position, time);
  142. list[index].transform.DOScale(list[preIndex].transform.localScale, time);
  143.  
  144. InsertToSortArray(list[index], list[preIndex].transform.localScale.x);
  145. }
  146.  
  147. list[startIndex].transform.DOMove(lastPos, time);
  148.  
  149. left = (left - 1 + itemAmount) % itemAmount;
  150. right = (right - 1 + itemAmount) % itemAmount;
  151. }
  152.  
  153. Sort();
  154. }
  155. }

不足之处:

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

2.等等...

[UnityUI]循环滑动列表的更多相关文章

  1. [UGUI]滑动列表优化(循环利用)

    需要注意的有下面几点: 1. 区分好表现上的index和逻辑上的index.表现上的index是指这个go是go列表中的第几项,但实际上这个index的意义并不大,因为在滚动的过程中go列表是轮转的: ...

  2. Android使用ViewPager实现左右循环滑动及轮播效果

    边界的时候会看到一个不能翻页的动画,可能影响用户体验.此外,某些区域性的ViewPager(例如展示广告或者公告之类的ViewPager),可能需要自动轮播的效果,即用户在不用滑动的情况下就能够看到其 ...

  3. Jquery制作--循环滚动列表

    自己模仿JQ插件的写法写了一个循环滚动列表插件,支持自定义上.下.左.右四个方向,支持平滑滚动或者间断滚动两种方式,都是通过参数设置.JQ里面有些重复的地方,暂时没想到更好的方法去精简.不过效果还是可 ...

  4. viewpage 循环滑动播放图片

    一般来说,viewpage 只支持图片的顺序滑动播放,在滑到边界时就再也滑不动了,如果要想继续滑动,只能向两边额外增加一张相片,即把第一张相片的位置放在最后一张图片的后面,给用户的感觉我继续滑就滑到了 ...

  5. 自定义循环滑动的viewpager

    今天和大家分享一下如何定制一个可以循环滑动的viewpager.其实今天更重要的提供一种组件化思想,当然你可以理解为面向对象思想. 吐槽一下网上流行的实现方式吧(为了方便说明,下文称之为方式A),方式 ...

  6. android中无限循环滑动的gallery实例

    android中无限循环滑动的gallery实例 1.点击图片有变暗的效果,使用imageview.setAlpha(),并且添加ontouchListener public void init() ...

  7. Unity3d NGUI的使用(九)(UIScrollView制作滑动列表)

    UIScrollView制作滑动列表,可横向,竖直展示一些列表在固定可视范围内 UIScrollVIew只是一个可滑动的UI组件 如果需要制作复杂的可视区域UI需要配合使用UIPanel与UIGrid ...

  8. 多行滚动jQuery循环新闻列表代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. 使用泛型简单封装NGUI的ScrollView实现滑动列表

    懒,是老毛病了,周末跑了半马,跑完也是一通累,好久没锻炼了..也是懒的,有时都懒的写博客..最近看到项目中各种滑动列表框,本着要懒出水平来的原则,决定花点时间简单处理下(暂时未做列表太多时的优化):1 ...

随机推荐

  1. 34.share_ptr智能指针共享内存,引用计数

    #include <iostream> #include <memory> #include <string> #include <vector> us ...

  2. POJ 2373 单调队列优化DP

    题意: 思路: f[i] = min(f[j]) + 1; 2 * a <= i - j <= 2 *b: i表示当前在第i个点.f[i]表示当前最少的线段个数 先是N^2的朴素DP(果断 ...

  3. HDFS的安全模式

  4. 使用python fabric搭建RHEL 7.2大数据基础环境以及部分优化

    1.使用python fabric进行Linux基础配置 使用python,可以让任何事情高效起来,包括运维工作,fabric正式这样一套基于python2的类库,它执行本地或远程shell命令提供了 ...

  5. VS导出方法名和方法备注的方法

    VS导出方法名和方法备注的方法 方法一: 只能导出图片格式的UML 类图 1.点击查看类图 2.在空白处点击讲关系导出为图像 方法二: 是把整个类库的方法名都罗列出来 这个方便整理一些 具体方法如下 ...

  6. Windows Phone相关

    Windows Phone IP over USB Transport (IpOverUsbSvc) is not running 进“服务”搜索 “Windows Phone IP Over USB ...

  7. [国家集训队]整数的lqp拆分 数学推导 打表找规律

    题解: 考场上靠打表找规律切的题,不过严谨的数学推导才是本题精妙所在:求:$\sum\prod_{i=1}^{m}F_{a{i}}$ 设 $f(i)$ 为 $N=i$ 时的答案,$F_{i}$ 为斐波 ...

  8. PHP实现杨辉三角形

    <?php /**** * 杨辉三角形:我的实现方式. * 下标 * 1 0 * 1 1 1 循环上一行数据1次,计算后结果追加到当前行末尾 * 1 2 1 2 * 1 3 3 1 3 * 1 ...

  9. 在MAC上安装lxml到Python3

    首先可以直接使用以下命令安装lxml,但是会默认安装到Python2,没有找到怎么指定安装到Python3 sudo easy_install lxml 想要安装到Python3需要先安装pip: s ...

  10. C#开发奇技淫巧二:根据dll文件加载C++或者Delphi插件

    原文:C#开发奇技淫巧二:根据dll文件加载C++或者Delphi插件 这两天忙着把框架改为支持加载C++和Delphi的插件,来不及更新blog了.      原来的写的框架只支持c#插件,这个好做 ...