当前位置:   article > 正文

ScrollView无限循环阻尼居中(带缩放)

ScrollView无限循环阻尼居中(带缩放)

       前两天写的SceollView阻尼居中的忘了加入循环列表的功能,本来我以为加入循环的功能不难,当写了才发现,因为上一个版本的Content里为了方便加的两个挂件(Content Size Fitter 和 Grid Layout Group)让我很尴尬,中间我试着实现了循环功能,发现在运行情况下我切换至VS后切换回Unity之后它又让我回到解放前(交换的Item位置又倍还原了。。),其中的原有我大概了解,但水平有限无法说明了。所以这次,我把它们卸了,自己给每个Item赋值,搞定!能力有限,写不出什么复用性高的代码。。。。。

之前忘记说,中间有一个AddChild()方法是自己写的拓展方法,只是为了方便一次性加入Item对象并返回所以子对象而写。
其中SignBox是放大区的标记点。

下面是代码:

  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using GameServer.Script.Model;
  5. using UnityEngine.UI;
  6. using UnityEngine.EventSystems;
  7. using System;
  8. public class MusicScrollView : MonoBehaviour, IEndDragHandler, IBeginDragHandler
  9. {
  10. LTDescr lt;
  11. private static MusicScrollView _instance;
  12. public static MusicScrollView Instance
  13. {
  14. get
  15. {
  16. if (_instance == null)
  17. {
  18. GameObject go = new GameObject();
  19. _instance = go.AddComponent<MusicScrollView>();
  20. }
  21. return _instance;
  22. }
  23. }
  24. //[组件信息]
  25. ScrollRect scrollRect;
  26. public DicItem ItemObj; //Item
  27. public GameObject SingBox; //标记盒子
  28. private Transform ContentObj; //父节点
  29. List<DicItem> itemList; //子节点管理
  30. //[UI效果设置参数]
  31. private float m_inertiaTime = 0f; //惯性作用时间
  32. private float m_BackTime = 0.3f; //会弹时间
  33. private float m_startDecelert = 0.05f;//初始惯性加速度
  34. private float m_UpRange = 0.4f; //放大检测范围及Scale增量
  35. //[Item设置参数]
  36. float m_SpaceBetween; //设置的碟片中心点间距
  37. float m_ParentStarPosY; //Content初始Y位置
  38. float m_CurPosY; //Content相对Y位置(0为参考)
  39. float ItemHeight = 300; //碟片高度
  40. float SpaceY = 180; //碟片边缘之间的间距
  41. int m_Index = 0; //Y位置与碟片(高度+间距)的整倍数
  42. float m_Surplus = 0; //Y位置与碟片(高度+间距)的整倍后剩余
  43. float MaxPosY = 0; //根据Item数量、间距、item高度计算得到的Y轴最大的数值
  44. Vector3 m_StartPos; //记录每次需要居中前的Content位置
  45. //[Item包含数据相关]
  46. [HideInInspector]
  47. public DicItem SelectDic; //选中碟片歌曲信息
  48. private int SelectItem; //选中歌曲在Content下的排列序号
  49. private int RealAmount; //真实的List<ResResut>Count
  50. //[计算相关数值]
  51. private int Direct = 0;
  52. private Vector3 lastPos;
  53. private Vector3 firstPos;
  54. int fistIndex = 0;
  55. int lastIndex = 0;
  56. Vector3[] PosArra;
  57. void Awake()
  58. {
  59. _instance = this;
  60. scrollRect = GetComponent<ScrollRect>();
  61. ContentObj = scrollRect.content;
  62. }
  63. // Use this for initialization
  64. void Start()
  65. {
  66. m_SpaceBetween = SpaceY + ItemHeight;// ContentObj.GetComponent<GridLayoutGroup>().spacing.y + m_ItemHight;
  67. }
  68. /// <summary>
  69. /// Content的初始位置Y赋值
  70. /// </summary>
  71. void ContentPointInit()
  72. {
  73. if (ContentObj.childCount % 2 == 0)//判断子对象的奇偶(上一次亦为奇数)
  74. {
  75. ContentObj.localPosition = new Vector3(ContentObj.localPosition.x, ContentObj.localPosition.y - (m_SpaceBetween / 2), ContentObj.localPosition.z);
  76. }
  77. else if (ContentObj.childCount % 2 != 0)
  78. {
  79. }
  80. m_ParentStarPosY = ContentObj.localPosition.y;
  81. }
  82. // Update is called once per frame
  83. void Update()
  84. {
  85. m_PreviousIndex = m_CurrentIndex;
  86. ChanageItemScale();
  87. CalculationContentChanege();
  88. }
  89. /// <summary>
  90. /// 初始更新列表内容
  91. /// </summary>
  92. /// <param name="Rr">对象</param>
  93. public void RefreshMusicList(List<ResResut> Rr)
  94. {
  95. MaxPosY = (Rr.Count / 2) * m_SpaceBetween; //根据Item数量计算得到最顶上Item的Pos,用于往下一次推算之后的Pos
  96. if (Rr.Count % 2 == 0)
  97. MaxPosY -= m_SpaceBetween / 2;
  98. RealAmount = Rr.Count;
  99. gameObject.SetActive(true);
  100. itemList = ContentObj.AddChild<DicItem>(ItemObj.gameObject, Rr.Count).ToList();//数组转List
  101. for (int i = 0; i < itemList.Count; i++)
  102. {
  103. if (Rr[i].ResType == 1)
  104. itemList[i].Init(Rr[i], i % 3); //专辑封面零时
  105. itemList[i].transform.localPosition = new Vector3(0, MaxPosY - i * m_SpaceBetween, 0); //便利赋值所有子对象的LocaPos
  106. }
  107. ContentPointInit(); //更新列表初始位置
  108. fistIndex = 0; //记录首末序号
  109. lastIndex = RealAmount - 1;
  110. }
  111. /// <summary>
  112. /// Item定位
  113. /// </summary>
  114. public void LocateItem()
  115. {
  116. lt = LeanTween.value(0, 1, m_inertiaTime).setOnStart(() =>
  117. {
  118. scrollRect.decelerationRate = m_startDecelert;
  119. }).setOnUpdate((float f) =>
  120. {
  121. scrollRect.decelerationRate = Mathf.Lerp(m_startDecelert, 0, f);
  122. }).setOnComplete(() =>
  123. {
  124. lt = LeanTween.value(0, 1, m_BackTime).setOnStart(() =>
  125. {
  126. m_StartPos = ContentObj.localPosition;
  127. m_CurPosY = ContentObj.localPosition.y - m_ParentStarPosY;
  128. m_Index = (int)(m_CurPosY / m_SpaceBetween);
  129. m_Surplus = m_CurPosY % m_SpaceBetween;
  130. if ((m_Surplus >= (m_SpaceBetween / 3) && m_Index > 0) || (m_Index < 0 && -m_Surplus >= (m_SpaceBetween / 3)))
  131. {
  132. m_Index += (m_Index / Mathf.Abs(m_Index));
  133. }
  134. else if (m_Index == 0)
  135. {
  136. if ((m_CurPosY > 0 && m_CurPosY >= (m_SpaceBetween / 3)) || (m_CurPosY < 0 && -m_CurPosY >= (m_SpaceBetween / 3)))
  137. {
  138. m_Index += (int)(m_CurPosY / Mathf.Abs(m_CurPosY));
  139. }
  140. }
  141. }).setOnUpdate((float f) =>
  142. {
  143. ContentObj.localPosition = Vector3.Lerp(m_StartPos, new Vector3(ContentObj.localPosition.x, m_Index * m_SpaceBetween + m_ParentStarPosY, ContentObj.localPosition.z), f);
  144. });
  145. });
  146. }
  147. void IEndDragHandler.OnEndDrag(PointerEventData eventData)
  148. {
  149. scrollRect.OnEndDrag(eventData);
  150. m_inertiaTime = Mathf.Clamp(Mathf.Clamp01(Math.Abs(eventData.delta.y * 0.008f)), 0, 0.1f); //根据拖拽的速度限制惯性运行的时间
  151. LocateItem();
  152. }
  153. public void OnBeginDrag(PointerEventData eventData)
  154. {
  155. if (lt != null)
  156. lt.reset();
  157. }
  158. /// <summary>
  159. /// 碟片尺寸过渡
  160. /// </summary>
  161. void ChanageItemScale()
  162. {
  163. for (int i = 0; i < itemList.Count; i++)
  164. {
  165. if (itemList[i].transform.position.y < SingBox.transform.position.y + m_UpRange && itemList[i].transform.position.y > SingBox.transform.position.y - m_UpRange)
  166. {
  167. float m_addSca = m_UpRange - Math.Abs(itemList[i].transform.position.y - SingBox.transform.position.y);
  168. itemList[i].transform.localScale = Vector3.one + new Vector3(m_addSca, m_addSca, m_addSca);
  169. if (m_addSca >= (m_UpRange - 0.3f))//&& i != m_LastIndex
  170. {
  171. if (SelectItem != i)
  172. {
  173. SelectItem = i; //得到Scale最大的碟片序号
  174. SelectDic = itemList[i].transform.GetComponent<DicItem>(); //得到Scale最大的碟片信息
  175. }
  176. }
  177. }
  178. else
  179. {
  180. itemList[i].transform.transform.localScale = Vector3.one;
  181. }
  182. }
  183. }
  184. void Circulation(int _dir)
  185. {
  186. if (_dir > 0)
  187. {
  188. itemList[fistIndex].transform.localPosition = itemList[lastIndex].transform.localPosition - new Vector3(0, m_SpaceBetween, 0);//PosArra[RealAmount - 1];
  189. lastIndex = fistIndex;
  190. fistIndex = (fistIndex + 1) % RealAmount;
  191. }
  192. else if (_dir < 0)
  193. {
  194. itemList[lastIndex].transform.localPosition = itemList[fistIndex].transform.localPosition + new Vector3(0, m_SpaceBetween, 0);
  195. fistIndex = lastIndex;
  196. lastIndex = (lastIndex + RealAmount - 1) % RealAmount;
  197. }
  198. }
  199. int m_CurrentIndex = 0;
  200. int m_PreviousIndex = 0;
  201. private void CalculationContentChanege()
  202. {
  203. m_CurrentIndex = Mathf.FloorToInt(((ContentObj.localPosition.y)/ m_SpaceBetween)); //向下取整获得变化的Index!!!!!!!!!!
  204. if (m_PreviousIndex != m_CurrentIndex)
  205. {
  206. for (int i = 0; i < Mathf.Abs(m_CurrentIndex - m_PreviousIndex); i++)
  207. Circulation(m_CurrentIndex - m_PreviousIndex);
  208. }
  209. }
  210. //List<DicItem> sortList(int _ChanageIndx, List<DicItem> _list)
  211. //{
  212. // List<DicItem> temp = new List<DicItem>();
  213. // for (int i = 0; i < _list.Count; i++)
  214. // {
  215. // if (_ChanageIndx < 0)
  216. // temp[i] = _list[(i + 1) % _list.Count];
  217. // else
  218. // temp[i] = _list[(_list.Count - 1 - i) % _list.Count];
  219. // }
  220. // return temp;
  221. //}
  222. }

在上下AddChild()的拓
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. public static partial class Extensions{
  5. public static T[] AddChild<T>(this Transform trans,GameObject t,int count,bool isReset = false)where T:MonoBehaviour
  6. {
  7. //获取所有子物体
  8. T[] children = trans.GetComponentsInChildren<T>(true);
  9. //子物体的数量少于要求的
  10. if (children.Length < count)
  11. {
  12. //要补充创建的数量
  13. int createCount = count - children.Length;
  14. for(int i = 0; i < createCount; i++)
  15. {
  16. //实例化的对象
  17. GameObject go = GameObject.Instantiate(t);
  18. //设置父物体
  19. go.transform.SetParent(trans);
  20. //设置初值
  21. go.transform.localScale = Vector3.one;
  22. go.transform.localPosition = Vector3.zero;
  23. }
  24. }
  25. children = trans.GetComponentsInChildren<T>(true);
  26. int cur = 0;
  27. for(int i = 0; i < children.Length; i++)
  28. {
  29. //获取子物体
  30. T child = children[i];
  31. child.transform.SetParent(trans);
  32. child.transform.localScale = Vector3.one;
  33. child.transform.localPosition = Vector3.zero;
  34. //如果索引小于物体总数
  35. if (cur < count)
  36. //激活子物体
  37. child.gameObject.SetActive(true);
  38. else
  39. //失活子物体
  40. child.gameObject.SetActive(false);
  41. //索引++
  42. cur++;
  43. }
  44. //返回数组
  45. return trans.GetComponentsInChildren<T>()
  1. }
  2. /// <summary>
  3. /// 数组转list
  4. /// </summary>
  5. /// <typeparam name="T"></typeparam>
  6. /// <param name="arr"></param>
  7. /// <returns></returns>
  8. public static List<T> ToList<T>(this T[] arr)
  9. {
  10. List<T> list = new List<T>();
  11. for (int i = 0; i < arr.Length; i++)
  12. {
  13. list.Add(arr[i]);
  14. }
  15. return list;
  16. }
  17. }
组件面板参数设置

能力有限,只是抱着分享和记录并学习的想法上传了,有不妥的地方,见谅。

(一直没有补上效果图。。。隔一年了再来补上2018.6.23)



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/422034
推荐阅读
相关标签
  

闽ICP备14008679号