UIScrollPage.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /****************************************************************************
  2. * Copyright (c) 2018.8 liangxie
  3. *
  4. * http://qframework.io
  5. * https://github.com/liangxiegame/QFramework
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. ****************************************************************************/
  25. using UnityEngine;
  26. using System.Collections.Generic;
  27. using UnityEngine.EventSystems;
  28. using UnityEngine.UI;
  29. using UnityEngine.Events;
  30. namespace QFramework
  31. {
  32. public class UIScrollPageChangeEvent : UnityEvent<int, int> {}
  33. public class UIScrollPage : MonoBehaviour, IBeginDragHandler, IEndDragHandler
  34. {
  35. ScrollRect rect;
  36. //页面:0,1,2,3 索引从0开始
  37. //每页占的比列:0/3=0 1/3=0.333 2/3=0.6666 3/3=1
  38. //float[] pages = { 0f, 0.333f, 0.6666f, 1f };
  39. List<float> pages = new List<float>();
  40. int currentPageIndex = -1;
  41. //滑动速度
  42. public float smooting = 4;
  43. //滑动的起始坐标
  44. float targethorizontal = 0;
  45. //是否拖拽结束
  46. bool isDrag = false;
  47. /// <summary>
  48. /// 用于返回一个页码,-1说明page的数据为0
  49. /// </summary>
  50. private UIScrollPageChangeEvent mOnPageChanged;
  51. float startime = 0f;
  52. float delay = 0.1f;
  53. void Awake()
  54. {
  55. rect = transform.GetComponent<ScrollRect>();
  56. startime = Time.time;
  57. }
  58. void Update()
  59. {
  60. if (Time.time < startime + delay) return;
  61. UpdatePages();
  62. //如果不判断。当在拖拽的时候要也会执行插值,所以会出现闪烁的效果
  63. //这里只要在拖动结束的时候。在进行插值
  64. if (!isDrag && pages.Count > 0)
  65. {
  66. rect.horizontalNormalizedPosition = Mathf.Lerp(rect.horizontalNormalizedPosition, targethorizontal, Time.deltaTime * smooting);
  67. }
  68. }
  69. public void OnBeginDrag(PointerEventData eventData)
  70. {
  71. isDrag = true;
  72. }
  73. public void OnEndDrag(PointerEventData eventData)
  74. {
  75. isDrag = false;
  76. if (eventData != null)
  77. {
  78. bool bLeft = eventData.position.x < eventData.pressPosition.x;
  79. if (bLeft)
  80. {
  81. if (currentPageIndex < pages.Count - 1)
  82. currentPageIndex++;
  83. }
  84. else
  85. {
  86. if (currentPageIndex > 0)
  87. currentPageIndex--;
  88. }
  89. mOnPageChanged.Invoke(pages.Count, currentPageIndex);
  90. targethorizontal = pages[currentPageIndex];
  91. }
  92. //float posX = rect.horizontalNormalizedPosition;
  93. //int index = 0;
  94. ////假设离第一位最近
  95. //float offset = Mathf.Abs(pages[index] - posX);
  96. //for (int i = 1; i < pages.Count; i++)
  97. //{
  98. // float temp = Mathf.Abs(pages[i] - posX);
  99. // if (temp < offset)
  100. // {
  101. // index = i;
  102. // //保存当前的偏移量
  103. // //如果到最后一页。反翻页。所以要保存该值,如果不保存。你试试效果就知道
  104. // offset = temp;
  105. // }
  106. //}
  107. //if(index!=currentPageIndex)
  108. //{
  109. // currentPageIndex = index;
  110. // OnPageChanged(pages.Count, currentPageIndex);
  111. //}
  112. ///*
  113. // 因为这样效果不好。没有滑动效果。比较死板。所以改为插值
  114. // */
  115. ////rect.horizontalNormalizedPosition = page[index];
  116. //targethorizontal = pages[index];
  117. }
  118. void UpdatePages()
  119. {
  120. // 获取子对象的数量
  121. int count = this.rect.content.childCount;
  122. int temp = 0;
  123. for (int i = 0; i < count; i++)
  124. {
  125. if (this.rect.content.GetChild(i).gameObject.activeSelf)
  126. {
  127. temp++;
  128. }
  129. }
  130. count = temp;
  131. if (pages.Count != count)
  132. {
  133. if (count != 0)
  134. {
  135. pages.Clear();
  136. for (int i = 0; i < count; i++)
  137. {
  138. float page = 0;
  139. if (count != 1)
  140. page = i / ((float) (count - 1));
  141. pages.Add(page);
  142. //Debug.Log(i.ToString() + " page:" + page.ToString());
  143. }
  144. }
  145. OnEndDrag(null);
  146. }
  147. }
  148. /// <summary>
  149. /// force set page index
  150. /// </summary>
  151. /// <param name="pageIndex"></param>
  152. public void SetPage(int pageIndex)
  153. {
  154. isDrag = false;
  155. UpdatePages();
  156. currentPageIndex = Mathf.Clamp(pageIndex, 0, pages.Count - 1);
  157. mOnPageChanged.Invoke(pages.Count, currentPageIndex);
  158. targethorizontal = pages[currentPageIndex];
  159. rect.horizontalNormalizedPosition = targethorizontal;
  160. }
  161. /// <summary>
  162. /// get all pages' count
  163. /// </summary>
  164. public int GetPageCount()
  165. {
  166. return pages.Count;
  167. }
  168. /// <summary>
  169. /// get current showed page index
  170. /// </summary>
  171. public int GetCurrentPageIndex()
  172. {
  173. return currentPageIndex;
  174. }
  175. /// <summary>
  176. /// register page change event listener
  177. /// </summary>
  178. public void AddPageChangeListener(UnityAction<int, int> listener)
  179. {
  180. if (mOnPageChanged == null)
  181. mOnPageChanged = new UIScrollPageChangeEvent();
  182. mOnPageChanged.AddListener(listener);
  183. }
  184. /// <summary>
  185. /// remove page change event listener
  186. /// </summary>
  187. public void RemovePageChangeListener(UnityAction<int, int> listener)
  188. {
  189. if (mOnPageChanged == null)
  190. return;
  191. mOnPageChanged.RemoveListener(listener);
  192. }
  193. void OnDestroy()
  194. {
  195. if (mOnPageChanged != null)
  196. mOnPageChanged.RemoveAllListeners();
  197. }
  198. }
  199. }