LoopHorizontalScrollRect.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. using UnityEngine;
  2. using System.Collections;
  3. using ET;
  4. namespace UnityEngine.UI
  5. {
  6. //[AddComponentMenu("UI/Loop Horizontal Scroll Rect", 50)]
  7. [DisallowMultipleComponent]
  8. public class LoopHorizontalScrollRect : LoopScrollRect
  9. {
  10. LoopHorizontalScrollRect()
  11. {
  12. direction = LoopScrollRectDirection.Horizontal;
  13. }
  14. protected override float GetSize(RectTransform item, bool includeSpacing)
  15. {
  16. float size = includeSpacing ? contentSpacing : 0;
  17. if (m_GridLayout != null)
  18. {
  19. size += m_GridLayout.cellSize.x;
  20. }
  21. else
  22. {
  23. size += LayoutUtility.GetPreferredWidth(item);
  24. }
  25. size *= m_Content.localScale.x;
  26. return size;
  27. }
  28. protected override float GetDimension(Vector2 vector)
  29. {
  30. return -vector.x;
  31. }
  32. protected override float GetAbsDimension(Vector2 vector)
  33. {
  34. return vector.x;
  35. }
  36. protected override Vector2 GetVector(float value)
  37. {
  38. return new Vector2(-value, 0);
  39. }
  40. protected override void Awake()
  41. {
  42. base.Awake();
  43. if (m_Content)
  44. {
  45. GridLayoutGroup layout = m_Content.GetComponent<GridLayoutGroup>();
  46. if (layout != null && layout.constraint != GridLayoutGroup.Constraint.FixedRowCount)
  47. {
  48. Debug.LogError($"[LoopScrollRect] {this.gameObject.name} 不支持的GridLayoutGroup约束 必须使用 FixedRowCount",this);
  49. }
  50. }
  51. }
  52. protected override async ETTask<(bool,Bounds,Bounds)> UpdateItems(Bounds viewBounds, Bounds contentBounds)
  53. {
  54. bool changed = false;
  55. // special case: handling move several page in one frame
  56. if ((viewBounds.size.x < contentBounds.min.x - viewBounds.max.x) && itemTypeEnd > itemTypeStart)
  57. {
  58. float currentSize = contentBounds.size.x;
  59. float elementSize = (currentSize - contentSpacing * (CurrentLines - 1)) / CurrentLines;
  60. ReturnToTempPool(false, itemTypeEnd - itemTypeStart);
  61. itemTypeEnd = itemTypeStart;
  62. int offsetCount = Mathf.FloorToInt((contentBounds.min.x - viewBounds.max.x) / (elementSize + contentSpacing));
  63. if (totalCount >= 0 && itemTypeStart - offsetCount * contentConstraintCount < 0)
  64. {
  65. offsetCount = Mathf.FloorToInt((float)(itemTypeStart) / contentConstraintCount);
  66. }
  67. itemTypeStart -= offsetCount * contentConstraintCount;
  68. if (totalCount >= 0)
  69. {
  70. itemTypeStart = Mathf.Max(itemTypeStart, 0);
  71. }
  72. itemTypeEnd = itemTypeStart;
  73. float offset = offsetCount * (elementSize + contentSpacing);
  74. m_Content.anchoredPosition -= new Vector2(offset + (reverseDirection ? currentSize : 0), 0);
  75. contentBounds.center -= new Vector3(offset + currentSize / 2, 0, 0);
  76. contentBounds.size = Vector3.zero;
  77. changed = true;
  78. }
  79. if ((viewBounds.min.x - contentBounds.max.x > viewBounds.size.x) && itemTypeEnd > itemTypeStart)
  80. {
  81. int maxItemTypeStart = -1;
  82. if (totalCount >= 0)
  83. {
  84. maxItemTypeStart = Mathf.Max(0, totalCount - (itemTypeEnd - itemTypeStart));
  85. maxItemTypeStart = (maxItemTypeStart / contentConstraintCount) * contentConstraintCount;
  86. }
  87. float currentSize = contentBounds.size.x;
  88. float elementSize = (currentSize - contentSpacing * (CurrentLines - 1)) / CurrentLines;
  89. ReturnToTempPool(true, itemTypeEnd - itemTypeStart);
  90. // TODO: fix with contentConstraint?
  91. itemTypeStart = itemTypeEnd;
  92. int offsetCount = Mathf.FloorToInt((viewBounds.min.x - contentBounds.max.x) / (elementSize + contentSpacing));
  93. if (maxItemTypeStart >= 0 && itemTypeStart + offsetCount * contentConstraintCount > maxItemTypeStart)
  94. {
  95. offsetCount = Mathf.FloorToInt((float)(maxItemTypeStart - itemTypeStart) / contentConstraintCount);
  96. }
  97. itemTypeStart += offsetCount * contentConstraintCount;
  98. if (totalCount >= 0)
  99. {
  100. itemTypeStart = Mathf.Max(itemTypeStart, 0);
  101. }
  102. itemTypeEnd = itemTypeStart;
  103. float offset = offsetCount * (elementSize + contentSpacing);
  104. m_Content.anchoredPosition += new Vector2(offset + (reverseDirection ? 0 : currentSize), 0);
  105. contentBounds.center += new Vector3(offset + currentSize / 2, 0, 0);
  106. contentBounds.size = Vector3.zero;
  107. changed = true;
  108. }
  109. if (viewBounds.max.x > contentBounds.max.x - m_ContentRightPadding)
  110. {
  111. float size = await NewItemAtEnd(), totalSize = size;
  112. while (size > 0 && viewBounds.max.x > contentBounds.max.x - m_ContentRightPadding + totalSize)
  113. {
  114. size = await NewItemAtEnd();
  115. totalSize += size;
  116. }
  117. if (totalSize > 0)
  118. changed = true;
  119. }
  120. if (viewBounds.min.x < contentBounds.min.x + m_ContentLeftPadding)
  121. {
  122. float size = await NewItemAtStart(), totalSize = size;
  123. while (size > 0 && viewBounds.min.x < contentBounds.min.x + m_ContentLeftPadding - totalSize)
  124. {
  125. size = await NewItemAtStart();
  126. totalSize += size;
  127. }
  128. if (totalSize > 0)
  129. changed = true;
  130. }
  131. if (viewBounds.max.x < contentBounds.max.x - threshold - m_ContentRightPadding)
  132. {
  133. float size = DeleteItemAtEnd(), totalSize = size;
  134. while (size > 0 && viewBounds.max.x < contentBounds.max.x - threshold - m_ContentRightPadding - totalSize)
  135. {
  136. size = DeleteItemAtEnd();
  137. totalSize += size;
  138. }
  139. if (totalSize > 0)
  140. changed = true;
  141. }
  142. if (viewBounds.min.x > contentBounds.min.x + threshold + m_ContentLeftPadding)
  143. {
  144. float size = DeleteItemAtStart(), totalSize = size;
  145. while (size > 0 && viewBounds.min.x > contentBounds.min.x + threshold + m_ContentLeftPadding + totalSize)
  146. {
  147. size = DeleteItemAtStart();
  148. totalSize += size;
  149. }
  150. if (totalSize > 0)
  151. changed = true;
  152. }
  153. if (changed)
  154. {
  155. ClearTempPool();
  156. }
  157. return (changed,viewBounds,contentBounds);
  158. }
  159. }
  160. }