VirtualScrollRectPlus.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.EventSystems;
  6. using UnityEngine.UI;
  7. public class VirtualScrollRectPlus : ScrollRect
  8. {
  9. #region Config //对象池需要外部实现
  10. public Action OnVerticalLessEqual0;
  11. public Action OnVerticalGreaterEqual1;
  12. public Action OnHorizontalLessEqual0;
  13. public Action OnHorizontalGreaterEqual1;
  14. public Func<int, VirtualScrollRectItem> OnGetNextItem;
  15. public Func<int, VirtualScrollRectItem> OnGetPreviousItem;
  16. public Action<int, VirtualScrollRectItem> OnSaveItem;
  17. public int FirstIndex;
  18. public int LastIndex;
  19. public bool Inited;
  20. public HorizontalOrVerticalLayoutGroup LayoutGroup;
  21. public int MaxRollAmount;
  22. public int MaxChildAmount;
  23. public List<VirtualScrollRectItem> Children = new List<VirtualScrollRectItem>();
  24. public Dictionary<VirtualScrollRectItem, int> ChildrenDataIndexDictionary = new Dictionary<VirtualScrollRectItem, int>();
  25. #endregion
  26. public override void OnDrag(PointerEventData eventData)
  27. {
  28. base.OnDrag(eventData);
  29. if (!Inited)
  30. {
  31. return;
  32. }
  33. if (horizontal && !vertical)
  34. {
  35. if (horizontalNormalizedPosition <= 0)
  36. {
  37. //Vector2 widthAndHeight = PreviousPage();
  38. //Roll(new Vector2(-widthAndHeight.x, 0));
  39. PreviousHorizontalPage();
  40. OnHorizontalGreaterEqual1.SafeInvoke();
  41. }
  42. if (horizontalNormalizedPosition >= 1)
  43. {
  44. //Vector2 widthAndHeight = NextPage();
  45. //Roll(new Vector2(widthAndHeight.x, 0));
  46. NextHorizontalPage();
  47. OnHorizontalLessEqual0.SafeInvoke();
  48. }
  49. }
  50. else if (!horizontal && vertical)
  51. {
  52. if (verticalNormalizedPosition >= 1)
  53. {
  54. //Vector2 widthAndHeight = PreviousPage();
  55. //Roll(new Vector2(0, widthAndHeight.y));
  56. PreviousVerticalPage();
  57. OnVerticalGreaterEqual1.SafeInvoke();
  58. }
  59. if (verticalNormalizedPosition <= 0)
  60. {
  61. //Vector2 widthAndHeight = NextPage();
  62. //Roll(new Vector2(0, -widthAndHeight.y));
  63. NextVerticalPage();
  64. OnVerticalLessEqual0.SafeInvoke();
  65. }
  66. }
  67. }
  68. public void Init(int maxRollAmount, int maxChildAmount, Func<int, VirtualScrollRectItem> getNextItem = null, Func<int, VirtualScrollRectItem> getPreviousItem = null, Action<int, VirtualScrollRectItem> onSaveItem = null)
  69. {
  70. Inited = true;
  71. MaxRollAmount = maxRollAmount;
  72. MaxChildAmount = maxChildAmount;
  73. LayoutGroup = content.GetComponent<HorizontalOrVerticalLayoutGroup>();
  74. OnGetNextItem = getNextItem;
  75. OnGetPreviousItem = getPreviousItem;
  76. OnSaveItem = onSaveItem;
  77. }
  78. public void SaveAllChild()
  79. {
  80. while (Children.Count > 0)
  81. {
  82. SaveFirstChild();
  83. }
  84. }
  85. public void SaveChild(VirtualScrollRectItem item)
  86. {
  87. int dataIndex = ChildrenDataIndexDictionary[item];
  88. OnSaveItem.Invoke(dataIndex, item);
  89. Children.Remove(item);
  90. ChildrenDataIndexDictionary.Remove(item);
  91. if (Children.Count > 0)
  92. {
  93. FirstIndex = ChildrenDataIndexDictionary[Children[0]];
  94. LastIndex = ChildrenDataIndexDictionary[Children.Back(0)];
  95. }
  96. else
  97. {
  98. FirstIndex = 0;
  99. LastIndex = 0;
  100. }
  101. }
  102. public void SaveFirstChild()
  103. {
  104. SaveChild(Children[0]);
  105. }
  106. public void SaveLastChild()
  107. {
  108. SaveChild(Children.Back(0));
  109. }
  110. public VirtualScrollRectItem InsertChild(int siblingIndex, int dataIndex, VirtualScrollRectItem item, bool saveItem = false, int savaSiblingIndex = 0)
  111. {
  112. VirtualScrollRectItem savedItem = null;
  113. if (saveItem && Children.Count >= MaxChildAmount)
  114. {
  115. if (savaSiblingIndex == -1)
  116. {
  117. savedItem = Children.Back(0);
  118. }
  119. else
  120. {
  121. savedItem = Children[savaSiblingIndex];
  122. }
  123. if (siblingIndex == Children.Count)
  124. {
  125. siblingIndex--;
  126. }
  127. SaveChild(savedItem);
  128. }
  129. Children.Insert(siblingIndex, item);
  130. ChildrenDataIndexDictionary.Add(item, dataIndex);
  131. item.transform.SetSiblingIndex(siblingIndex);
  132. FirstIndex = ChildrenDataIndexDictionary[Children[0]];
  133. LastIndex = ChildrenDataIndexDictionary[Children.Back(0)];
  134. return savedItem;
  135. }
  136. public VirtualScrollRectItem InsertChildToFirst(int dataIndex, VirtualScrollRectItem item, bool saveItem = false, int savaSiblingIndex = 0)
  137. {
  138. return InsertChild(0, dataIndex, item, saveItem, savaSiblingIndex);
  139. }
  140. public VirtualScrollRectItem InsertChildToLast(int dataIndex, VirtualScrollRectItem item, bool saveItem = false, int savaSiblingIndex = 0)
  141. {
  142. return InsertChild(Children.Count, dataIndex, item, saveItem, savaSiblingIndex);
  143. }
  144. public void NextVerticalPage()
  145. {
  146. Vector2 widthAndHeight = NextPage();
  147. Roll(new Vector2(0, -widthAndHeight.y));
  148. }
  149. public void NextHorizontalPage()
  150. {
  151. Vector2 widthAndHeight = NextPage();
  152. Roll(new Vector2(widthAndHeight.x, 0));
  153. }
  154. public void PreviousVerticalPage()
  155. {
  156. Vector2 widthAndHeight = PreviousPage();
  157. Roll(new Vector2(0, widthAndHeight.y));
  158. }
  159. public void PreviousHorizontalPage()
  160. {
  161. Vector2 widthAndHeight = PreviousPage();
  162. Roll(new Vector2(-widthAndHeight.x, 0));
  163. }
  164. private Vector2 NextPage()
  165. {
  166. //Debug.LogWarning("NextPage");
  167. List<VirtualScrollRectItem> rolledItems = new List<VirtualScrollRectItem>();
  168. for (int i = 0; i < MaxRollAmount; i++)
  169. {
  170. int dataIndex = Children.Count == 0 ? 0 : LastIndex + 1;
  171. VirtualScrollRectItem item = OnGetNextItem.Invoke(dataIndex);
  172. if (item == null)
  173. {
  174. break;
  175. }
  176. else
  177. {
  178. VirtualScrollRectItem savedItem = InsertChildToLast(dataIndex, item, true, 0);
  179. if (savedItem != null)
  180. {
  181. rolledItems.Add(savedItem);
  182. }
  183. }
  184. }
  185. Vector2 widthAndHeight = new Vector2(rolledItems.MySum(item => item.RectTransform.rect.width), rolledItems.MySum(item => item.RectTransform.rect.height));
  186. widthAndHeight += new Vector2(LayoutGroup.spacing, LayoutGroup.spacing) * Mathf.Max(rolledItems.Count - 1, 0);
  187. return widthAndHeight;
  188. }
  189. private Vector2 PreviousPage()
  190. {
  191. //Debug.LogWarning("PreviousPage");
  192. List<VirtualScrollRectItem> rolledItems = new List<VirtualScrollRectItem>();
  193. for (int i = 0; i < MaxRollAmount; i++)
  194. {
  195. VirtualScrollRectItem item = OnGetPreviousItem.Invoke(FirstIndex-1);
  196. if (item == null)
  197. {
  198. break;
  199. }
  200. else
  201. {
  202. VirtualScrollRectItem savedItem = InsertChildToFirst(FirstIndex-1, item, true, -1);
  203. if (savedItem != null)
  204. {
  205. rolledItems.Add(savedItem);
  206. }
  207. }
  208. }
  209. Vector2 widthAndHeight = new Vector2(rolledItems.MySum(item => item.RectTransform.rect.width), rolledItems.MySum(item => item.RectTransform.rect.height));
  210. widthAndHeight += new Vector2(LayoutGroup.spacing, LayoutGroup.spacing)*Mathf.Max(rolledItems.Count - 1, 0);
  211. return widthAndHeight;
  212. }
  213. public void Roll(Vector2 contentOffset)
  214. {
  215. m_ContentStartPosition += contentOffset;
  216. }
  217. }