ScrollPane.cs 76 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294
  1. using System;
  2. using UnityEngine;
  3. using FairyGUI.Utils;
  4. namespace FairyGUI
  5. {
  6. /// <summary>
  7. ///
  8. /// </summary>
  9. public class ScrollPane : EventDispatcher
  10. {
  11. /// <summary>
  12. /// 当前被拖拽的滚动面板。同一时间只能有一个在进行此操作。
  13. /// </summary>
  14. public static ScrollPane draggingPane { get; private set; }
  15. ScrollType _scrollType;
  16. float _scrollStep;
  17. float _decelerationRate;
  18. Margin _scrollBarMargin;
  19. bool _bouncebackEffect;
  20. bool _touchEffect;
  21. bool _scrollBarDisplayAuto;
  22. bool _vScrollNone;
  23. bool _hScrollNone;
  24. bool _needRefresh;
  25. int _refreshBarAxis;
  26. bool _displayOnLeft;
  27. bool _snapToItem;
  28. internal bool _displayInDemand;
  29. bool _mouseWheelEnabled;
  30. bool _softnessOnTopOrLeftSide;
  31. bool _pageMode;
  32. Vector2 _pageSize;
  33. bool _inertiaDisabled;
  34. bool _maskDisabled;
  35. bool _floating;
  36. bool _dontClipMargin;
  37. float _xPos;
  38. float _yPos;
  39. Vector2 _viewSize;
  40. Vector2 _contentSize;
  41. Vector2 _overlapSize;
  42. Vector2 _containerPos;
  43. Vector2 _beginTouchPos;
  44. Vector2 _lastTouchPos;
  45. Vector2 _lastTouchGlobalPos;
  46. Vector2 _velocity;
  47. float _velocityScale;
  48. float _lastMoveTime;
  49. bool _dragged;
  50. bool _isHoldAreaDone;
  51. int _aniFlag;
  52. internal int _loop;
  53. int _headerLockedSize;
  54. int _footerLockedSize;
  55. bool _hover;
  56. int _tweening;
  57. Vector2 _tweenStart;
  58. Vector2 _tweenChange;
  59. Vector2 _tweenTime;
  60. Vector2 _tweenDuration;
  61. Action _refreshDelegate;
  62. TimerCallback _tweenUpdateDelegate;
  63. GTweenCallback1 _hideScrollBarDelegate;
  64. GComponent _owner;
  65. Container _maskContainer;
  66. Container _container;
  67. GScrollBar _hzScrollBar;
  68. GScrollBar _vtScrollBar;
  69. GComponent _header;
  70. GComponent _footer;
  71. Controller _pageController;
  72. EventListener _onScroll;
  73. EventListener _onScrollEnd;
  74. EventListener _onPullDownRelease;
  75. EventListener _onPullUpRelease;
  76. static int _gestureFlag;
  77. public static float TWEEN_TIME_GO = 0.3f; //调用SetPos(ani)时使用的缓动时间
  78. public static float TWEEN_TIME_DEFAULT = 0.3f; //惯性滚动的最小缓动时间
  79. public static float PULL_RATIO = 0.5f; //下拉过顶或者上拉过底时允许超过的距离占显示区域的比例
  80. public ScrollPane(GComponent owner)
  81. {
  82. _onScroll = new EventListener(this, "onScroll");
  83. _onScrollEnd = new EventListener(this, "onScrollEnd");
  84. _scrollStep = UIConfig.defaultScrollStep;
  85. _softnessOnTopOrLeftSide = UIConfig.allowSoftnessOnTopOrLeftSide;
  86. _decelerationRate = UIConfig.defaultScrollDecelerationRate;
  87. _touchEffect = UIConfig.defaultScrollTouchEffect;
  88. _bouncebackEffect = UIConfig.defaultScrollBounceEffect;
  89. _mouseWheelEnabled = true;
  90. _pageSize = Vector2.one;
  91. _refreshDelegate = Refresh;
  92. _tweenUpdateDelegate = TweenUpdate;
  93. _hideScrollBarDelegate = __barTweenComplete;
  94. _owner = owner;
  95. _maskContainer = new Container();
  96. _owner.rootContainer.AddChild(_maskContainer);
  97. _container = _owner.container;
  98. _container.SetXY(0, 0);
  99. _maskContainer.AddChild(_container);
  100. _owner.rootContainer.onMouseWheel.Add(__mouseWheel);
  101. _owner.rootContainer.onTouchBegin.Add(__touchBegin);
  102. _owner.rootContainer.onTouchMove.Add(__touchMove);
  103. _owner.rootContainer.onTouchEnd.Add(__touchEnd);
  104. }
  105. public void Setup(ByteBuffer buffer)
  106. {
  107. _scrollType = (ScrollType)buffer.ReadByte();
  108. ScrollBarDisplayType scrollBarDisplay = (ScrollBarDisplayType)buffer.ReadByte();
  109. int flags = buffer.ReadInt();
  110. if (buffer.ReadBool())
  111. {
  112. _scrollBarMargin.top = buffer.ReadInt();
  113. _scrollBarMargin.bottom = buffer.ReadInt();
  114. _scrollBarMargin.left = buffer.ReadInt();
  115. _scrollBarMargin.right = buffer.ReadInt();
  116. }
  117. string vtScrollBarRes = buffer.ReadS();
  118. string hzScrollBarRes = buffer.ReadS();
  119. string headerRes = buffer.ReadS();
  120. string footerRes = buffer.ReadS();
  121. _displayOnLeft = (flags & 1) != 0;
  122. _snapToItem = (flags & 2) != 0;
  123. _displayInDemand = (flags & 4) != 0;
  124. _pageMode = (flags & 8) != 0;
  125. if ((flags & 16) != 0)
  126. _touchEffect = true;
  127. else if ((flags & 32) != 0)
  128. _touchEffect = false;
  129. if ((flags & 64) != 0)
  130. _bouncebackEffect = true;
  131. else if ((flags & 128) != 0)
  132. _bouncebackEffect = false;
  133. _inertiaDisabled = (flags & 256) != 0;
  134. _maskDisabled = (flags & 512) != 0;
  135. _floating = (flags & 1024) != 0;
  136. _dontClipMargin = (flags & 2048) != 0;
  137. if (scrollBarDisplay == ScrollBarDisplayType.Default)
  138. {
  139. if (Application.isMobilePlatform)
  140. scrollBarDisplay = ScrollBarDisplayType.Auto;
  141. else
  142. scrollBarDisplay = UIConfig.defaultScrollBarDisplay;
  143. }
  144. if (scrollBarDisplay != ScrollBarDisplayType.Hidden)
  145. {
  146. if (_scrollType == ScrollType.Both || _scrollType == ScrollType.Vertical)
  147. {
  148. string res = vtScrollBarRes != null ? vtScrollBarRes : UIConfig.verticalScrollBar;
  149. if (!string.IsNullOrEmpty(res))
  150. {
  151. _vtScrollBar = UIPackage.CreateObjectFromURL(res) as GScrollBar;
  152. if (_vtScrollBar == null)
  153. Debug.LogWarning("FairyGUI: cannot create scrollbar from " + res);
  154. else
  155. {
  156. _vtScrollBar.SetScrollPane(this, true);
  157. _owner.rootContainer.AddChild(_vtScrollBar.displayObject);
  158. }
  159. }
  160. }
  161. if (_scrollType == ScrollType.Both || _scrollType == ScrollType.Horizontal)
  162. {
  163. string res = hzScrollBarRes != null ? hzScrollBarRes : UIConfig.horizontalScrollBar;
  164. if (!string.IsNullOrEmpty(res))
  165. {
  166. _hzScrollBar = UIPackage.CreateObjectFromURL(res) as GScrollBar;
  167. if (_hzScrollBar == null)
  168. Debug.LogWarning("FairyGUI: cannot create scrollbar from " + res);
  169. else
  170. {
  171. _hzScrollBar.SetScrollPane(this, false);
  172. _owner.rootContainer.AddChild(_hzScrollBar.displayObject);
  173. }
  174. }
  175. }
  176. _scrollBarDisplayAuto = scrollBarDisplay == ScrollBarDisplayType.Auto;
  177. if (_scrollBarDisplayAuto)
  178. {
  179. if (_vtScrollBar != null)
  180. _vtScrollBar.displayObject.visible = false;
  181. if (_hzScrollBar != null)
  182. _hzScrollBar.displayObject.visible = false;
  183. _owner.rootContainer.onRollOver.Add(__rollOver);
  184. _owner.rootContainer.onRollOut.Add(__rollOut);
  185. }
  186. }
  187. else
  188. _mouseWheelEnabled = false;
  189. if (Application.isPlaying)
  190. {
  191. if (headerRes != null)
  192. {
  193. _header = (GComponent)UIPackage.CreateObjectFromURL(headerRes);
  194. if (_header == null)
  195. Debug.LogWarning("FairyGUI: cannot create scrollPane header from " + headerRes);
  196. }
  197. if (footerRes != null)
  198. {
  199. _footer = (GComponent)UIPackage.CreateObjectFromURL(footerRes);
  200. if (_footer == null)
  201. Debug.LogWarning("FairyGUI: cannot create scrollPane footer from " + footerRes);
  202. }
  203. if (_header != null || _footer != null)
  204. _refreshBarAxis = (_scrollType == ScrollType.Both || _scrollType == ScrollType.Vertical) ? 1 : 0;
  205. }
  206. SetSize(owner.width, owner.height);
  207. }
  208. /// <summary>
  209. ///
  210. /// </summary>
  211. public void Dispose()
  212. {
  213. RemoveEventListeners();
  214. if (_tweening != 0)
  215. Timers.inst.Remove(_tweenUpdateDelegate);
  216. if (draggingPane == this)
  217. draggingPane = null;
  218. _pageController = null;
  219. if (_hzScrollBar != null)
  220. _hzScrollBar.Dispose();
  221. if (_vtScrollBar != null)
  222. _vtScrollBar.Dispose();
  223. if (_header != null)
  224. _header.Dispose();
  225. if (_footer != null)
  226. _footer.Dispose();
  227. }
  228. /// <summary>
  229. /// Dispatched when scrolling.
  230. /// 在滚动时派发该事件。
  231. /// </summary>
  232. public EventListener onScroll
  233. {
  234. get { return _onScroll ?? (_onScroll = new EventListener(this, "onScroll")); }
  235. }
  236. /// <summary>
  237. /// 在滚动结束时派发该事件。
  238. /// </summary>
  239. public EventListener onScrollEnd
  240. {
  241. get { return _onScrollEnd ?? (_onScrollEnd = new EventListener(this, "onScrollEnd")); }
  242. }
  243. /// <summary>
  244. /// 向下拉过上边缘后释放则派发该事件。
  245. /// </summary>
  246. public EventListener onPullDownRelease
  247. {
  248. get { return _onPullDownRelease ?? (_onPullDownRelease = new EventListener(this, "onPullDownRelease")); }
  249. }
  250. /// <summary>
  251. /// 向上拉过下边缘后释放则派发该事件。
  252. /// </summary>
  253. public EventListener onPullUpRelease
  254. {
  255. get { return _onPullUpRelease ?? (_onPullUpRelease = new EventListener(this, "onPullUpRelease")); }
  256. }
  257. /// <summary>
  258. ///
  259. /// </summary>
  260. public GComponent owner
  261. {
  262. get { return _owner; }
  263. }
  264. /// <summary>
  265. ///
  266. /// </summary>
  267. public GScrollBar hzScrollBar
  268. {
  269. get { return _hzScrollBar; }
  270. }
  271. /// <summary>
  272. ///
  273. /// </summary>
  274. public GScrollBar vtScrollBar
  275. {
  276. get { return _vtScrollBar; }
  277. }
  278. /// <summary>
  279. ///
  280. /// </summary>
  281. public GComponent header
  282. {
  283. get { return _header; }
  284. }
  285. /// <summary>
  286. ///
  287. /// </summary>
  288. public GComponent footer
  289. {
  290. get { return _footer; }
  291. }
  292. /// <summary>
  293. /// 滚动到达边缘时是否允许回弹效果。
  294. /// </summary>
  295. public bool bouncebackEffect
  296. {
  297. get { return _bouncebackEffect; }
  298. set { _bouncebackEffect = value; }
  299. }
  300. /// <summary>
  301. /// 是否允许拖拽内容区域进行滚动。
  302. /// </summary>
  303. public bool touchEffect
  304. {
  305. get { return _touchEffect; }
  306. set { _touchEffect = value; }
  307. }
  308. /// <summary>
  309. /// 是否允许惯性滚动。
  310. /// </summary>
  311. public bool inertiaDisabled
  312. {
  313. get { return _inertiaDisabled; }
  314. set { _inertiaDisabled = value; }
  315. }
  316. /// <summary>
  317. /// 是否允许在左/上边缘显示虚化效果。
  318. /// </summary>
  319. public bool softnessOnTopOrLeftSide
  320. {
  321. get { return _softnessOnTopOrLeftSide; }
  322. set { _softnessOnTopOrLeftSide = value; }
  323. }
  324. /// <summary>
  325. /// 当调用ScrollPane.scrollUp/Down/Left/Right时,或者点击滚动条的上下箭头时,滑动的距离。
  326. /// </summary>
  327. public float scrollStep
  328. {
  329. get { return _scrollStep; }
  330. set
  331. {
  332. _scrollStep = value;
  333. if (_scrollStep == 0)
  334. _scrollStep = UIConfig.defaultScrollStep;
  335. }
  336. }
  337. /// <summary>
  338. /// 滚动位置是否保持贴近在某个元件的边缘。
  339. /// </summary>
  340. public bool snapToItem
  341. {
  342. get { return _snapToItem; }
  343. set { _snapToItem = value; }
  344. }
  345. /// <summary>
  346. /// 是否页面滚动模式。
  347. /// </summary>
  348. public bool pageMode
  349. {
  350. get { return _pageMode; }
  351. set { _pageMode = value; }
  352. }
  353. /// <summary>
  354. ///
  355. /// </summary>
  356. public Controller pageController
  357. {
  358. get { return _pageController; }
  359. set { _pageController = value; }
  360. }
  361. /// <summary>
  362. /// 是否允许使用鼠标滚轮进行滚动。
  363. /// </summary>
  364. public bool mouseWheelEnabled
  365. {
  366. get { return _mouseWheelEnabled; }
  367. set { _mouseWheelEnabled = value; }
  368. }
  369. /// <summary>
  370. /// 当处于惯性滚动时减速的速率。默认值是UIConfig.defaultScrollDecelerationRate。
  371. /// 越接近1,减速越慢,意味着滑动的时间和距离更长。
  372. /// </summary>
  373. public float decelerationRate
  374. {
  375. get { return _decelerationRate; }
  376. set { _decelerationRate = value; }
  377. }
  378. /// <summary>
  379. /// </summary>
  380. public bool isDragged
  381. {
  382. get { return _dragged; }
  383. }
  384. /// <summary>
  385. /// 当前X轴滚动位置百分比,0~1(包含)。
  386. /// </summary>
  387. public float percX
  388. {
  389. get { return _overlapSize.x == 0 ? 0 : _xPos / _overlapSize.x; }
  390. set { SetPercX(value, false); }
  391. }
  392. /// <summary>
  393. /// 设置当前X轴滚动位置百分比,0~1(包含)。
  394. /// </summary>
  395. /// <param name="value"></param>
  396. /// <param name="ani">是否使用缓动到达目标。</param>
  397. public void SetPercX(float value, bool ani)
  398. {
  399. _owner.EnsureBoundsCorrect();
  400. SetPosX(_overlapSize.x * Mathf.Clamp01(value), ani);
  401. }
  402. /// <summary>
  403. /// 当前Y轴滚动位置百分比,0~1(包含)。
  404. /// </summary>
  405. public float percY
  406. {
  407. get { return _overlapSize.y == 0 ? 0 : _yPos / _overlapSize.y; }
  408. set { SetPercY(value, false); }
  409. }
  410. /// <summary>
  411. /// 设置当前Y轴滚动位置百分比,0~1(包含)。
  412. /// </summary>
  413. /// <param name="value"></param>
  414. /// <param name="ani">是否使用缓动到达目标。</param>
  415. public void SetPercY(float value, bool ani)
  416. {
  417. _owner.EnsureBoundsCorrect();
  418. SetPosY(_overlapSize.y * Mathf.Clamp01(value), ani);
  419. }
  420. /// <summary>
  421. /// 当前X轴滚动位置,值范围是viewWidth与contentWidth之差。
  422. /// </summary>
  423. public float posX
  424. {
  425. get { return _xPos; }
  426. set { SetPosX(value, false); }
  427. }
  428. /// <summary>
  429. /// 设置当前X轴滚动位置。
  430. /// </summary>
  431. /// <param name="value"></param>
  432. /// <param name="ani">是否使用缓动到达目标。</param>
  433. public void SetPosX(float value, bool ani)
  434. {
  435. _owner.EnsureBoundsCorrect();
  436. if (_loop == 1)
  437. LoopCheckingNewPos(ref value, 0);
  438. value = Mathf.Clamp(value, 0, _overlapSize.x);
  439. if (value != _xPos)
  440. {
  441. _xPos = value;
  442. PosChanged(ani);
  443. }
  444. }
  445. /// <summary>
  446. /// 当前Y轴滚动位置,值范围是viewHeight与contentHeight之差。
  447. /// </summary>
  448. public float posY
  449. {
  450. get { return _yPos; }
  451. set { SetPosY(value, false); }
  452. }
  453. /// <summary>
  454. /// 设置当前Y轴滚动位置。
  455. /// </summary>
  456. /// <param name="value"></param>
  457. /// <param name="ani">是否使用缓动到达目标。</param>
  458. public void SetPosY(float value, bool ani)
  459. {
  460. _owner.EnsureBoundsCorrect();
  461. if (_loop == 2)
  462. LoopCheckingNewPos(ref value, 1);
  463. value = Mathf.Clamp(value, 0, _overlapSize.y);
  464. if (value != _yPos)
  465. {
  466. _yPos = value;
  467. PosChanged(ani);
  468. }
  469. }
  470. /// <summary>
  471. /// 返回当前滚动位置是否在最下边。
  472. /// </summary>
  473. public bool isBottomMost
  474. {
  475. get { return _yPos == _overlapSize.y || _overlapSize.y == 0; }
  476. }
  477. /// <summary>
  478. /// 返回当前滚动位置是否在最右边。
  479. /// </summary>
  480. public bool isRightMost
  481. {
  482. get { return _xPos == _overlapSize.x || _overlapSize.x == 0; }
  483. }
  484. /// <summary>
  485. /// 如果处于分页模式,返回当前在X轴的页码。
  486. /// </summary>
  487. public int currentPageX
  488. {
  489. get
  490. {
  491. if (!_pageMode)
  492. return 0;
  493. int page = Mathf.FloorToInt(_xPos / _pageSize.x);
  494. if (_xPos - page * _pageSize.x > _pageSize.x * 0.5f)
  495. page++;
  496. return page;
  497. }
  498. set
  499. {
  500. if (!_pageMode)
  501. return;
  502. _owner.EnsureBoundsCorrect();
  503. if (_overlapSize.x > 0)
  504. this.SetPosX(value * _pageSize.x, false);
  505. }
  506. }
  507. /// <summary>
  508. /// 如果处于分页模式,可设置X轴的页码。
  509. /// </summary>
  510. /// <param name="value"></param>
  511. /// <param name="ani">是否使用缓动到达目标。</param>
  512. public void SetCurrentPageX(int value, bool ani)
  513. {
  514. if (!_pageMode)
  515. return;
  516. _owner.EnsureBoundsCorrect();
  517. if (_overlapSize.x > 0)
  518. this.SetPosX(value * _pageSize.x, ani);
  519. }
  520. /// <summary>
  521. /// 如果处于分页模式,返回当前在Y轴的页码。
  522. /// </summary>
  523. public int currentPageY
  524. {
  525. get
  526. {
  527. if (!_pageMode)
  528. return 0;
  529. int page = Mathf.FloorToInt(_yPos / _pageSize.y);
  530. if (_yPos - page * _pageSize.y > _pageSize.y * 0.5f)
  531. page++;
  532. return page;
  533. }
  534. set
  535. {
  536. if (!_pageMode)
  537. return;
  538. _owner.EnsureBoundsCorrect();
  539. if (_overlapSize.y > 0)
  540. this.SetPosY(value * _pageSize.y, false);
  541. }
  542. }
  543. /// <summary>
  544. /// 如果处于分页模式,可设置Y轴的页码。
  545. /// </summary>
  546. /// <param name="value"></param>
  547. /// <param name="ani">是否使用缓动到达目标。</param>
  548. public void SetCurrentPageY(int value, bool ani)
  549. {
  550. if (!_pageMode)
  551. return;
  552. _owner.EnsureBoundsCorrect();
  553. if (_overlapSize.y > 0)
  554. this.SetPosY(value * _pageSize.y, ani);
  555. }
  556. /// <summary>
  557. /// 这个值与PosX不同在于,他反映的是实时位置,而PosX在有缓动过程的情况下只是终值。
  558. /// </summary>
  559. public float scrollingPosX
  560. {
  561. get
  562. {
  563. return Mathf.Clamp(-_container.x, 0, _overlapSize.x);
  564. }
  565. }
  566. /// <summary>
  567. /// 这个值与PosY不同在于,他反映的是实时位置,而PosY在有缓动过程的情况下只是终值。
  568. /// </summary>
  569. public float scrollingPosY
  570. {
  571. get
  572. {
  573. return Mathf.Clamp(-_container.y, 0, _overlapSize.y);
  574. }
  575. }
  576. /// <summary>
  577. /// 显示内容宽度。
  578. /// </summary>
  579. public float contentWidth
  580. {
  581. get
  582. {
  583. return _contentSize.x;
  584. }
  585. }
  586. /// <summary>
  587. /// 显示内容高度。
  588. /// </summary>
  589. public float contentHeight
  590. {
  591. get
  592. {
  593. return _contentSize.y;
  594. }
  595. }
  596. /// <summary>
  597. /// 显示区域宽度。
  598. /// </summary>
  599. public float viewWidth
  600. {
  601. get { return _viewSize.x; }
  602. set
  603. {
  604. value = value + _owner.margin.left + _owner.margin.right;
  605. if (_vtScrollBar != null && !_floating)
  606. value += _vtScrollBar.width;
  607. _owner.width = value;
  608. }
  609. }
  610. /// <summary>
  611. /// 显示区域高度。
  612. /// </summary>
  613. public float viewHeight
  614. {
  615. get { return _viewSize.y; }
  616. set
  617. {
  618. value = value + _owner.margin.top + _owner.margin.bottom;
  619. if (_hzScrollBar != null && !_floating)
  620. value += _hzScrollBar.height;
  621. _owner.height = value;
  622. }
  623. }
  624. /// <summary>
  625. ///
  626. /// </summary>
  627. public void ScrollTop()
  628. {
  629. ScrollTop(false);
  630. }
  631. /// <summary>
  632. ///
  633. /// </summary>
  634. /// <param name="ani"></param>
  635. public void ScrollTop(bool ani)
  636. {
  637. this.SetPercY(0, ani);
  638. }
  639. /// <summary>
  640. ///
  641. /// </summary>
  642. public void ScrollBottom()
  643. {
  644. ScrollBottom(false);
  645. }
  646. /// <summary>
  647. ///
  648. /// </summary>
  649. /// <param name="ani"></param>
  650. public void ScrollBottom(bool ani)
  651. {
  652. this.SetPercY(1, ani);
  653. }
  654. /// <summary>
  655. ///
  656. /// </summary>
  657. public void ScrollUp()
  658. {
  659. ScrollUp(1, false);
  660. }
  661. /// <summary>
  662. ///
  663. /// </summary>
  664. /// <param name="ratio"></param>
  665. /// <param name="ani"></param>
  666. public void ScrollUp(float ratio, bool ani)
  667. {
  668. if (_pageMode)
  669. SetPosY(_yPos - _pageSize.y * ratio, ani);
  670. else
  671. SetPosY(_yPos - _scrollStep * ratio, ani);
  672. }
  673. /// <summary>
  674. ///
  675. /// </summary>
  676. public void ScrollDown()
  677. {
  678. ScrollDown(1, false);
  679. }
  680. /// <summary>
  681. ///
  682. /// </summary>
  683. /// <param name="ratio"></param>
  684. /// <param name="ani"></param>
  685. public void ScrollDown(float ratio, bool ani)
  686. {
  687. if (_pageMode)
  688. SetPosY(_yPos + _pageSize.y * ratio, ani);
  689. else
  690. SetPosY(_yPos + _scrollStep * ratio, ani);
  691. }
  692. /// <summary>
  693. ///
  694. /// </summary>
  695. public void ScrollLeft()
  696. {
  697. ScrollLeft(1, false);
  698. }
  699. /// <summary>
  700. ///
  701. /// </summary>
  702. /// <param name="speed"></param>
  703. /// <param name="ani"></param>
  704. public void ScrollLeft(float ratio, bool ani)
  705. {
  706. if (_pageMode)
  707. SetPosX(_xPos - _pageSize.x * ratio, ani);
  708. else
  709. SetPosX(_xPos - _scrollStep * ratio, ani);
  710. }
  711. /// <summary>
  712. ///
  713. /// </summary>
  714. public void ScrollRight()
  715. {
  716. ScrollRight(1, false);
  717. }
  718. /// <summary>
  719. ///
  720. /// </summary>
  721. /// <param name="ratio"></param>
  722. /// <param name="ani"></param>
  723. public void ScrollRight(float ratio, bool ani)
  724. {
  725. if (_pageMode)
  726. SetPosX(_xPos + _pageSize.x * ratio, ani);
  727. else
  728. SetPosX(_xPos + _scrollStep * ratio, ani);
  729. }
  730. /// <summary>
  731. ///
  732. /// </summary>
  733. /// <param name="obj">obj can be any object on stage, not limited to the direct child of this container.</param>
  734. public void ScrollToView(GObject obj)
  735. {
  736. ScrollToView(obj, false);
  737. }
  738. /// <summary>
  739. ///
  740. /// </summary>
  741. /// <param name="obj">obj can be any object on stage, not limited to the direct child of this container.</param>
  742. /// <param name="ani">If moving to target position with animation</param>
  743. public void ScrollToView(GObject obj, bool ani)
  744. {
  745. ScrollToView(obj, ani, false);
  746. }
  747. /// <summary>
  748. ///
  749. /// </summary>
  750. /// <param name="obj">obj can be any object on stage, not limited to the direct child of this container.</param>
  751. /// <param name="ani">If moving to target position with animation</param>
  752. /// <param name="setFirst">If true, scroll to make the target on the top/left; If false, scroll to make the target any position in view.</param>
  753. public void ScrollToView(GObject obj, bool ani, bool setFirst)
  754. {
  755. _owner.EnsureBoundsCorrect();
  756. if (_needRefresh)
  757. Refresh();
  758. Rect rect = new Rect(obj.x, obj.y, obj.width, obj.height);
  759. if (obj.parent != _owner)
  760. rect = obj.parent.TransformRect(rect, _owner);
  761. ScrollToView(rect, ani, setFirst);
  762. }
  763. /// <summary>
  764. ///
  765. /// </summary>
  766. /// <param name="rect">Rect in local coordinates</param>
  767. /// <param name="ani">If moving to target position with animation</param>
  768. /// <param name="setFirst">If true, scroll to make the target on the top/left; If false, scroll to make the target any position in view.</param>
  769. public void ScrollToView(Rect rect, bool ani, bool setFirst)
  770. {
  771. _owner.EnsureBoundsCorrect();
  772. if (_needRefresh)
  773. Refresh();
  774. if (_overlapSize.y > 0)
  775. {
  776. float bottom = _yPos + _viewSize.y;
  777. if (setFirst || rect.y <= _yPos || rect.height >= _viewSize.y)
  778. {
  779. if (_pageMode)
  780. this.SetPosY(Mathf.Floor(rect.y / _pageSize.y) * _pageSize.y, ani);
  781. else
  782. SetPosY(rect.y, ani);
  783. }
  784. else if (rect.y + rect.height > bottom)
  785. {
  786. if (_pageMode)
  787. this.SetPosY(Mathf.Floor(rect.y / _pageSize.y) * _pageSize.y, ani);
  788. else if (rect.height <= _viewSize.y / 2)
  789. SetPosY(rect.y + rect.height * 2 - _viewSize.y, ani);
  790. else
  791. SetPosY(rect.y + rect.height - _viewSize.y, ani);
  792. }
  793. }
  794. if (_overlapSize.x > 0)
  795. {
  796. float right = _xPos + _viewSize.x;
  797. if (setFirst || rect.x <= _xPos || rect.width >= _viewSize.x)
  798. {
  799. if (_pageMode)
  800. this.SetPosX(Mathf.Floor(rect.x / _pageSize.x) * _pageSize.x, ani);
  801. SetPosX(rect.x, ani);
  802. }
  803. else if (rect.x + rect.width > right)
  804. {
  805. if (_pageMode)
  806. this.SetPosX(Mathf.Floor(rect.x / _pageSize.x) * _pageSize.x, ani);
  807. else if (rect.width <= _viewSize.x / 2)
  808. SetPosX(rect.x + rect.width * 2 - _viewSize.x, ani);
  809. else
  810. SetPosX(rect.x + rect.width - _viewSize.x, ani);
  811. }
  812. }
  813. if (!ani && _needRefresh)
  814. Refresh();
  815. }
  816. /// <summary>
  817. ///
  818. /// </summary>
  819. /// <param name="obj">obj must be the direct child of this container</param>
  820. /// <returns></returns>
  821. public bool IsChildInView(GObject obj)
  822. {
  823. if (_overlapSize.y > 0)
  824. {
  825. float dist = obj.y + _container.y;
  826. if (dist <= -obj.height || dist >= _viewSize.y)
  827. return false;
  828. }
  829. if (_overlapSize.x > 0)
  830. {
  831. float dist = obj.x + _container.x;
  832. if (dist <= -obj.width || dist >= _viewSize.x)
  833. return false;
  834. }
  835. return true;
  836. }
  837. /// <summary>
  838. /// 当滚动面板处于拖拽滚动状态或即将进入拖拽状态时,可以调用此方法停止或禁止本次拖拽。
  839. /// </summary>
  840. public void CancelDragging()
  841. {
  842. Stage.inst.RemoveTouchMonitor(_owner.rootContainer);
  843. if (draggingPane == this)
  844. draggingPane = null;
  845. _gestureFlag = 0;
  846. _dragged = false;
  847. }
  848. /// <summary>
  849. /// 设置Header固定显示。如果size为0,则取消固定显示。
  850. /// </summary>
  851. /// <param name="size">Header显示的大小</param>
  852. public void LockHeader(int size)
  853. {
  854. if (_headerLockedSize == size)
  855. return;
  856. _headerLockedSize = size;
  857. if (!isDispatching("onPullDownRelease") && _container.xy[_refreshBarAxis] >= 0)
  858. {
  859. _tweenStart = _container.xy;
  860. _tweenChange = Vector2.zero;
  861. _tweenChange[_refreshBarAxis] = _headerLockedSize - _tweenStart[_refreshBarAxis];
  862. _tweenDuration = new Vector2(TWEEN_TIME_DEFAULT, TWEEN_TIME_DEFAULT);
  863. StartTween(2);
  864. }
  865. }
  866. /// <summary>
  867. /// 设置Footer固定显示。如果size为0,则取消固定显示。
  868. /// </summary>
  869. /// <param name="size"></param>
  870. public void LockFooter(int size)
  871. {
  872. if (_footerLockedSize == size)
  873. return;
  874. _footerLockedSize = size;
  875. if (!isDispatching("onPullUpRelease") && _container.xy[_refreshBarAxis] <= -_overlapSize[_refreshBarAxis])
  876. {
  877. _tweenStart = _container.xy;
  878. _tweenChange = Vector2.zero;
  879. float max = _overlapSize[_refreshBarAxis];
  880. if (max == 0)
  881. max = Mathf.Max(_contentSize[_refreshBarAxis] + _footerLockedSize - _viewSize[_refreshBarAxis], 0);
  882. else
  883. max += _footerLockedSize;
  884. _tweenChange[_refreshBarAxis] = -max - _tweenStart[_refreshBarAxis];
  885. _tweenDuration = new Vector2(TWEEN_TIME_DEFAULT, TWEEN_TIME_DEFAULT);
  886. StartTween(2);
  887. }
  888. }
  889. internal void OnOwnerSizeChanged()
  890. {
  891. SetSize(_owner.width, _owner.height);
  892. PosChanged(false);
  893. }
  894. internal void HandleControllerChanged(Controller c)
  895. {
  896. if (_pageController == c)
  897. {
  898. if (_scrollType == ScrollType.Horizontal)
  899. this.SetCurrentPageX(c.selectedIndex, true);
  900. else
  901. this.SetCurrentPageY(c.selectedIndex, true);
  902. }
  903. }
  904. void UpdatePageController()
  905. {
  906. if (_pageController != null && !_pageController.changing)
  907. {
  908. int index;
  909. if (_scrollType == ScrollType.Horizontal)
  910. index = this.currentPageX;
  911. else
  912. index = this.currentPageY;
  913. if (index < _pageController.pageCount)
  914. {
  915. Controller c = _pageController;
  916. _pageController = null; //防止HandleControllerChanged的调用
  917. c.selectedIndex = index;
  918. _pageController = c;
  919. }
  920. }
  921. }
  922. internal void AdjustMaskContainer()
  923. {
  924. float mx, my;
  925. if (_displayOnLeft && _vtScrollBar != null && !_floating)
  926. mx = Mathf.FloorToInt(_owner.margin.left + _vtScrollBar.width);
  927. else
  928. mx = _owner.margin.left;
  929. my = _owner.margin.top;
  930. mx += _owner._alignOffset.x;
  931. my += _owner._alignOffset.y;
  932. _maskContainer.SetXY(mx, my);
  933. }
  934. void SetSize(float aWidth, float aHeight)
  935. {
  936. AdjustMaskContainer();
  937. if (_hzScrollBar != null)
  938. {
  939. _hzScrollBar.y = aHeight - _hzScrollBar.height;
  940. if (_vtScrollBar != null)
  941. {
  942. _hzScrollBar.width = aWidth - _vtScrollBar.width - _scrollBarMargin.left - _scrollBarMargin.right;
  943. if (_displayOnLeft)
  944. _hzScrollBar.x = _scrollBarMargin.left + _vtScrollBar.width;
  945. else
  946. _hzScrollBar.x = _scrollBarMargin.left;
  947. }
  948. else
  949. {
  950. _hzScrollBar.width = aWidth - _scrollBarMargin.left - _scrollBarMargin.right;
  951. _hzScrollBar.x = _scrollBarMargin.left;
  952. }
  953. }
  954. if (_vtScrollBar != null)
  955. {
  956. if (!_displayOnLeft)
  957. _vtScrollBar.x = aWidth - _vtScrollBar.width;
  958. if (_hzScrollBar != null)
  959. _vtScrollBar.height = aHeight - _hzScrollBar.height - _scrollBarMargin.top - _scrollBarMargin.bottom;
  960. else
  961. _vtScrollBar.height = aHeight - _scrollBarMargin.top - _scrollBarMargin.bottom;
  962. _vtScrollBar.y = _scrollBarMargin.top;
  963. }
  964. _viewSize.x = aWidth;
  965. _viewSize.y = aHeight;
  966. if (_hzScrollBar != null && !_floating)
  967. _viewSize.y -= _hzScrollBar.height;
  968. if (_vtScrollBar != null && !_floating)
  969. _viewSize.x -= _vtScrollBar.width;
  970. _viewSize.x -= (_owner.margin.left + _owner.margin.right);
  971. _viewSize.y -= (_owner.margin.top + _owner.margin.bottom);
  972. _viewSize.x = Mathf.Max(1, _viewSize.x);
  973. _viewSize.y = Mathf.Max(1, _viewSize.y);
  974. _pageSize.x = _viewSize.x;
  975. _pageSize.y = _viewSize.y;
  976. HandleSizeChanged();
  977. }
  978. internal void SetContentSize(float aWidth, float aHeight)
  979. {
  980. if (Mathf.Approximately(_contentSize.x, aWidth) && Mathf.Approximately(_contentSize.y, aHeight))
  981. return;
  982. _contentSize.x = aWidth;
  983. _contentSize.y = aHeight;
  984. HandleSizeChanged();
  985. }
  986. /// <summary>
  987. /// 内部使用。由虚拟列表调用。在滚动时修改显示内容的大小,需要进行修正,避免滚动跳跃。
  988. /// </summary>
  989. /// <param name="deltaWidth"></param>
  990. /// <param name="deltaHeight"></param>
  991. /// <param name="deltaPosX"></param>
  992. /// <param name="deltaPosY"></param>
  993. internal void ChangeContentSizeOnScrolling(float deltaWidth, float deltaHeight, float deltaPosX, float deltaPosY)
  994. {
  995. bool isRightmost = _xPos == _overlapSize.x;
  996. bool isBottom = _yPos == _overlapSize.y;
  997. _contentSize.x += deltaWidth;
  998. _contentSize.y += deltaHeight;
  999. HandleSizeChanged();
  1000. if (_tweening == 1)
  1001. {
  1002. //如果原来滚动位置是贴边,加入处理继续贴边。
  1003. if (deltaWidth != 0 && isRightmost && _tweenChange.x < 0)
  1004. {
  1005. _xPos = _overlapSize.x;
  1006. _tweenChange.x = -_xPos - _tweenStart.x;
  1007. }
  1008. if (deltaHeight != 0 && isBottom && _tweenChange.y < 0)
  1009. {
  1010. _yPos = _overlapSize.y;
  1011. _tweenChange.y = -_yPos - _tweenStart.y;
  1012. }
  1013. }
  1014. else if (_tweening == 2)
  1015. {
  1016. //重新调整起始位置,确保能够顺滑滚下去
  1017. if (deltaPosX != 0)
  1018. {
  1019. _container.x -= deltaPosX;
  1020. _tweenStart.x -= deltaPosX;
  1021. _xPos = -_container.x;
  1022. }
  1023. if (deltaPosY != 0)
  1024. {
  1025. _container.y -= deltaPosY;
  1026. _tweenStart.y -= deltaPosY;
  1027. _yPos = -_container.y;
  1028. }
  1029. }
  1030. else if (_dragged)
  1031. {
  1032. if (deltaPosX != 0)
  1033. {
  1034. _container.x -= deltaPosX;
  1035. _containerPos.x -= deltaPosX;
  1036. _xPos = -_container.x;
  1037. }
  1038. if (deltaPosY != 0)
  1039. {
  1040. _container.y -= deltaPosY;
  1041. _containerPos.y -= deltaPosY;
  1042. _yPos = -_container.y;
  1043. }
  1044. }
  1045. else
  1046. {
  1047. //如果原来滚动位置是贴边,加入处理继续贴边。
  1048. if (deltaWidth != 0 && isRightmost)
  1049. {
  1050. _xPos = _overlapSize.x;
  1051. _container.x = -_xPos;
  1052. }
  1053. if (deltaHeight != 0 && isBottom)
  1054. {
  1055. _yPos = _overlapSize.y;
  1056. _container.y = -_yPos;
  1057. }
  1058. }
  1059. if (_pageMode)
  1060. UpdatePageController();
  1061. }
  1062. void HandleSizeChanged()
  1063. {
  1064. if (_displayInDemand)
  1065. {
  1066. _vScrollNone = _contentSize.y <= _viewSize.y;
  1067. _hScrollNone = _contentSize.x <= _viewSize.x;
  1068. }
  1069. if (_vtScrollBar != null)
  1070. {
  1071. if (_contentSize.y == 0)
  1072. _vtScrollBar.SetDisplayPerc(0);
  1073. else
  1074. _vtScrollBar.SetDisplayPerc(Mathf.Min(1, _viewSize.y / _contentSize.y));
  1075. }
  1076. if (_hzScrollBar != null)
  1077. {
  1078. if (_contentSize.x == 0)
  1079. _hzScrollBar.SetDisplayPerc(0);
  1080. else
  1081. _hzScrollBar.SetDisplayPerc(Mathf.Min(1, _viewSize.x / _contentSize.x));
  1082. }
  1083. UpdateScrollBarVisible();
  1084. if (!_maskDisabled)
  1085. {
  1086. Rect rect = new Rect(-_owner._alignOffset.x, -_owner._alignOffset.y, _viewSize.x, _viewSize.y);
  1087. if (_vScrollNone && _vtScrollBar != null)
  1088. rect.width += _vtScrollBar.width;
  1089. if (_hScrollNone && _hzScrollBar != null)
  1090. rect.height += _hzScrollBar.height;
  1091. if (_dontClipMargin)
  1092. {
  1093. rect.x -= _owner.margin.left;
  1094. rect.width += (_owner.margin.left + _owner.margin.right);
  1095. rect.y -= _owner.margin.top;
  1096. rect.height += (_owner.margin.top + _owner.margin.bottom);
  1097. }
  1098. _maskContainer.clipRect = rect;
  1099. }
  1100. if (_scrollType == ScrollType.Horizontal || _scrollType == ScrollType.Both)
  1101. _overlapSize.x = Mathf.CeilToInt(Math.Max(0, _contentSize.x - _viewSize.x));
  1102. else
  1103. _overlapSize.x = 0;
  1104. if (_scrollType == ScrollType.Vertical || _scrollType == ScrollType.Both)
  1105. _overlapSize.y = Mathf.CeilToInt(Math.Max(0, _contentSize.y - _viewSize.y));
  1106. else
  1107. _overlapSize.y = 0;
  1108. //边界检查
  1109. _xPos = Mathf.Clamp(_xPos, 0, _overlapSize.x);
  1110. _yPos = Mathf.Clamp(_yPos, 0, _overlapSize.y);
  1111. float max = _overlapSize[_refreshBarAxis];
  1112. if (max == 0)
  1113. max = Mathf.Max(_contentSize[_refreshBarAxis] + _footerLockedSize - _viewSize[_refreshBarAxis], 0);
  1114. else
  1115. max += _footerLockedSize;
  1116. if (_refreshBarAxis == 0)
  1117. _container.SetXY(Mathf.Clamp(_container.x, -max, _headerLockedSize), Mathf.Clamp(_container.y, -_overlapSize.y, 0));
  1118. else
  1119. _container.SetXY(Mathf.Clamp(_container.x, -_overlapSize.x, 0), Mathf.Clamp(_container.y, -max, _headerLockedSize));
  1120. if (_header != null)
  1121. {
  1122. if (_refreshBarAxis == 0)
  1123. _header.height = _viewSize.y;
  1124. else
  1125. _header.width = _viewSize.x;
  1126. }
  1127. if (_footer != null)
  1128. {
  1129. if (_refreshBarAxis == 0)
  1130. _footer.height = _viewSize.y;
  1131. else
  1132. _footer.width = _viewSize.x;
  1133. }
  1134. UpdateScrollBarPos();
  1135. if (_pageMode)
  1136. UpdatePageController();
  1137. }
  1138. private void PosChanged(bool ani)
  1139. {
  1140. //只要有1处要求不要缓动,那就不缓动
  1141. if (_aniFlag == 0)
  1142. _aniFlag = ani ? 1 : -1;
  1143. else if (_aniFlag == 1 && !ani)
  1144. _aniFlag = -1;
  1145. _needRefresh = true;
  1146. UpdateContext.OnBegin -= _refreshDelegate;
  1147. UpdateContext.OnBegin += _refreshDelegate;
  1148. }
  1149. private void Refresh()
  1150. {
  1151. _needRefresh = false;
  1152. UpdateContext.OnBegin -= _refreshDelegate;
  1153. if (_owner.displayObject == null || _owner.displayObject.isDisposed)
  1154. return;
  1155. if (_pageMode || _snapToItem)
  1156. {
  1157. Vector2 pos = new Vector2(-_xPos, -_yPos);
  1158. AlignPosition(ref pos, false);
  1159. _xPos = -pos.x;
  1160. _yPos = -pos.y;
  1161. }
  1162. Refresh2();
  1163. _onScroll.Call();
  1164. if (_needRefresh) //在onScroll事件里开发者可能修改位置,这里再刷新一次,避免闪烁
  1165. {
  1166. _needRefresh = false;
  1167. UpdateContext.OnBegin -= _refreshDelegate;
  1168. Refresh2();
  1169. }
  1170. UpdateScrollBarPos();
  1171. _aniFlag = 0;
  1172. }
  1173. void Refresh2()
  1174. {
  1175. if (_aniFlag == 1 && !_dragged)
  1176. {
  1177. Vector2 pos = new Vector2();
  1178. if (_overlapSize.x > 0)
  1179. pos.x = -(int)_xPos;
  1180. else
  1181. {
  1182. if (_container.x != 0)
  1183. _container.x = 0;
  1184. pos.x = 0;
  1185. }
  1186. if (_overlapSize.y > 0)
  1187. pos.y = -(int)_yPos;
  1188. else
  1189. {
  1190. if (_container.y != 0)
  1191. _container.y = 0;
  1192. pos.y = 0;
  1193. }
  1194. if (pos.x != _container.x || pos.y != _container.y)
  1195. {
  1196. _tweenDuration = new Vector2(TWEEN_TIME_GO, TWEEN_TIME_GO);
  1197. _tweenStart = _container.xy;
  1198. _tweenChange = pos - _tweenStart;
  1199. StartTween(1);
  1200. }
  1201. else if (_tweening != 0)
  1202. KillTween();
  1203. }
  1204. else
  1205. {
  1206. if (_tweening != 0)
  1207. KillTween();
  1208. _container.SetXY((int)-_xPos, (int)-_yPos);
  1209. LoopCheckingCurrent();
  1210. }
  1211. if (_pageMode)
  1212. UpdatePageController();
  1213. }
  1214. private void __touchBegin(EventContext context)
  1215. {
  1216. if (!_touchEffect)
  1217. return;
  1218. InputEvent evt = context.inputEvent;
  1219. if (evt.button != 0)
  1220. return;
  1221. context.CaptureTouch();
  1222. Vector2 pt = _owner.GlobalToLocal(evt.position);
  1223. if (_tweening != 0)
  1224. {
  1225. KillTween();
  1226. Stage.inst.CancelClick(evt.touchId);
  1227. //立刻停止惯性滚动,可能位置不对齐,设定这个标志,使touchEnd时归位
  1228. _dragged = true;
  1229. }
  1230. else
  1231. _dragged = false;
  1232. _containerPos = _container.xy;
  1233. _beginTouchPos = _lastTouchPos = pt;
  1234. _lastTouchGlobalPos = evt.position;
  1235. _isHoldAreaDone = false;
  1236. _velocity = Vector2.zero;
  1237. _velocityScale = 1;
  1238. _lastMoveTime = Time.unscaledTime;
  1239. }
  1240. private void __touchMove(EventContext context)
  1241. {
  1242. if (!_touchEffect || draggingPane != null && draggingPane != this || GObject.draggingObject != null) //已经有其他拖动
  1243. return;
  1244. InputEvent evt = context.inputEvent;
  1245. Vector2 pt = _owner.GlobalToLocal(evt.position);
  1246. if (float.IsNaN(pt.x))
  1247. return;
  1248. int sensitivity;
  1249. if (Stage.touchScreen)
  1250. sensitivity = UIConfig.touchScrollSensitivity;
  1251. else
  1252. sensitivity = 8;
  1253. float diff;
  1254. bool sv = false, sh = false;
  1255. if (_scrollType == ScrollType.Vertical)
  1256. {
  1257. if (!_isHoldAreaDone)
  1258. {
  1259. //表示正在监测垂直方向的手势
  1260. _gestureFlag |= 1;
  1261. diff = Mathf.Abs(_beginTouchPos.y - pt.y);
  1262. if (diff < sensitivity)
  1263. return;
  1264. if ((_gestureFlag & 2) != 0) //已经有水平方向的手势在监测,那么我们用严格的方式检查是不是按垂直方向移动,避免冲突
  1265. {
  1266. float diff2 = Mathf.Abs(_beginTouchPos.x - pt.x);
  1267. if (diff < diff2) //不通过则不允许滚动了
  1268. return;
  1269. }
  1270. }
  1271. sv = true;
  1272. }
  1273. else if (_scrollType == ScrollType.Horizontal)
  1274. {
  1275. if (!_isHoldAreaDone)
  1276. {
  1277. _gestureFlag |= 2;
  1278. diff = Mathf.Abs(_beginTouchPos.x - pt.x);
  1279. if (diff < sensitivity)
  1280. return;
  1281. if ((_gestureFlag & 1) != 0)
  1282. {
  1283. float diff2 = Mathf.Abs(_beginTouchPos.y - pt.y);
  1284. if (diff < diff2)
  1285. return;
  1286. }
  1287. }
  1288. sh = true;
  1289. }
  1290. else
  1291. {
  1292. _gestureFlag = 3;
  1293. if (!_isHoldAreaDone)
  1294. {
  1295. diff = Mathf.Abs(_beginTouchPos.y - pt.y);
  1296. if (diff < sensitivity)
  1297. {
  1298. diff = Mathf.Abs(_beginTouchPos.x - pt.x);
  1299. if (diff < sensitivity)
  1300. return;
  1301. }
  1302. }
  1303. sv = sh = true;
  1304. }
  1305. Vector2 newPos = _containerPos + pt - _beginTouchPos;
  1306. newPos.x = (int)newPos.x;
  1307. newPos.y = (int)newPos.y;
  1308. if (sv)
  1309. {
  1310. if (newPos.y > 0)
  1311. {
  1312. if (!_bouncebackEffect)
  1313. _container.y = 0;
  1314. else if (_header != null && _header.maxHeight != 0)
  1315. _container.y = (int)Mathf.Min(newPos.y * 0.5f, _header.maxHeight);
  1316. else
  1317. _container.y = (int)Mathf.Min(newPos.y * 0.5f, _viewSize.y * PULL_RATIO);
  1318. }
  1319. else if (newPos.y < -_overlapSize.y)
  1320. {
  1321. if (!_bouncebackEffect)
  1322. _container.y = -_overlapSize.y;
  1323. else if (_footer != null && _footer.maxHeight > 0)
  1324. _container.y = (int)Mathf.Max((newPos.y + _overlapSize.y) * 0.5f, -_footer.maxHeight) - _overlapSize.y;
  1325. else
  1326. _container.y = (int)Mathf.Max((newPos.y + _overlapSize.y) * 0.5f, -_viewSize.y * PULL_RATIO) - _overlapSize.y;
  1327. }
  1328. else
  1329. _container.y = newPos.y;
  1330. }
  1331. if (sh)
  1332. {
  1333. if (newPos.x > 0)
  1334. {
  1335. if (!_bouncebackEffect)
  1336. _container.x = 0;
  1337. else if (_header != null && _header.maxWidth != 0)
  1338. _container.x = (int)Mathf.Min(newPos.x * 0.5f, _header.maxWidth);
  1339. else
  1340. _container.x = (int)Mathf.Min(newPos.x * 0.5f, _viewSize.x * PULL_RATIO);
  1341. }
  1342. else if (newPos.x < 0 - _overlapSize.x)
  1343. {
  1344. if (!_bouncebackEffect)
  1345. _container.x = -_overlapSize.x;
  1346. else if (_footer != null && _footer.maxWidth > 0)
  1347. _container.x = (int)Mathf.Max((newPos.x + _overlapSize.x) * 0.5f, -_footer.maxWidth) - _overlapSize.x;
  1348. else
  1349. _container.x = (int)Mathf.Max((newPos.x + _overlapSize.x) * 0.5f, -_viewSize.x * PULL_RATIO) - _overlapSize.x;
  1350. }
  1351. else
  1352. _container.x = newPos.x;
  1353. }
  1354. //更新速度
  1355. float deltaTime = Time.unscaledDeltaTime;
  1356. float elapsed = (Time.unscaledTime - _lastMoveTime) * 60 - 1;
  1357. if (elapsed > 1) //速度衰减
  1358. _velocity = _velocity * Mathf.Pow(0.833f, elapsed);
  1359. Vector2 deltaPosition = pt - _lastTouchPos;
  1360. if (!sh)
  1361. deltaPosition.x = 0;
  1362. if (!sv)
  1363. deltaPosition.y = 0;
  1364. _velocity = Vector2.Lerp(_velocity, deltaPosition / deltaTime, deltaTime * 10);
  1365. /*速度计算使用的是本地位移,但在后续的惯性滚动判断中需要用到屏幕位移,所以这里要记录一个位移的比例。
  1366. *后续的处理要使用这个比例但不使用坐标转换的方法的原因是,在曲面UI等异形UI中,还无法简单地进行屏幕坐标和本地坐标的转换。
  1367. */
  1368. Vector2 deltaGlobalPosition = _lastTouchGlobalPos - evt.position;
  1369. if (deltaPosition.x != 0)
  1370. _velocityScale = Mathf.Abs(deltaGlobalPosition.x / deltaPosition.x);
  1371. else if (deltaPosition.y != 0)
  1372. _velocityScale = Mathf.Abs(deltaGlobalPosition.y / deltaPosition.y);
  1373. _lastTouchPos = pt;
  1374. _lastTouchGlobalPos = evt.position;
  1375. _lastMoveTime = Time.unscaledTime;
  1376. //同步更新pos值
  1377. if (_overlapSize.x > 0)
  1378. _xPos = Mathf.Clamp(-_container.x, 0, _overlapSize.x);
  1379. if (_overlapSize.y > 0)
  1380. _yPos = Mathf.Clamp(-_container.y, 0, _overlapSize.y);
  1381. //循环滚动特别检查
  1382. if (_loop != 0)
  1383. {
  1384. newPos = _container.xy;
  1385. if (LoopCheckingCurrent())
  1386. _containerPos += _container.xy - newPos;
  1387. }
  1388. draggingPane = this;
  1389. _isHoldAreaDone = true;
  1390. _dragged = true;
  1391. UpdateScrollBarPos();
  1392. UpdateScrollBarVisible();
  1393. if (_pageMode)
  1394. UpdatePageController();
  1395. _onScroll.Call();
  1396. }
  1397. private void __touchEnd(EventContext context)
  1398. {
  1399. if (draggingPane == this)
  1400. draggingPane = null;
  1401. _gestureFlag = 0;
  1402. if (!_dragged || !_touchEffect)
  1403. {
  1404. _dragged = false;
  1405. return;
  1406. }
  1407. _dragged = false;
  1408. _tweenStart = _container.xy;
  1409. Vector2 endPos = _tweenStart;
  1410. bool flag = false;
  1411. if (_container.x > 0)
  1412. {
  1413. endPos.x = 0;
  1414. flag = true;
  1415. }
  1416. else if (_container.x < -_overlapSize.x)
  1417. {
  1418. endPos.x = -_overlapSize.x;
  1419. flag = true;
  1420. }
  1421. if (_container.y > 0)
  1422. {
  1423. endPos.y = 0;
  1424. flag = true;
  1425. }
  1426. else if (_container.y < -_overlapSize.y)
  1427. {
  1428. endPos.y = -_overlapSize.y;
  1429. flag = true;
  1430. }
  1431. if (flag)
  1432. {
  1433. _tweenChange = endPos - _tweenStart;
  1434. if (_tweenChange.x < -UIConfig.touchDragSensitivity || _tweenChange.y < -UIConfig.touchDragSensitivity)
  1435. DispatchEvent("onPullDownRelease", null);
  1436. else if (_tweenChange.x > UIConfig.touchDragSensitivity || _tweenChange.y > UIConfig.touchDragSensitivity)
  1437. DispatchEvent("onPullUpRelease", null);
  1438. if (_headerLockedSize > 0 && endPos[_refreshBarAxis] == 0)
  1439. {
  1440. endPos[_refreshBarAxis] = _headerLockedSize;
  1441. _tweenChange = endPos - _tweenStart;
  1442. }
  1443. else if (_footerLockedSize > 0 && endPos[_refreshBarAxis] == -_overlapSize[_refreshBarAxis])
  1444. {
  1445. float max = _overlapSize[_refreshBarAxis];
  1446. if (max == 0)
  1447. max = Mathf.Max(_contentSize[_refreshBarAxis] + _footerLockedSize - _viewSize[_refreshBarAxis], 0);
  1448. else
  1449. max += _footerLockedSize;
  1450. endPos[_refreshBarAxis] = -max;
  1451. _tweenChange = endPos - _tweenStart;
  1452. }
  1453. _tweenDuration.Set(TWEEN_TIME_DEFAULT, TWEEN_TIME_DEFAULT);
  1454. }
  1455. else
  1456. {
  1457. //更新速度
  1458. if (!_inertiaDisabled)
  1459. {
  1460. float elapsed = (Time.unscaledTime - _lastMoveTime) * 60 - 1;
  1461. if (elapsed > 1)
  1462. _velocity = _velocity * Mathf.Pow(0.833f, elapsed);
  1463. //根据速度计算目标位置和需要时间
  1464. endPos = UpdateTargetAndDuration(_tweenStart);
  1465. }
  1466. else
  1467. _tweenDuration.Set(TWEEN_TIME_DEFAULT, TWEEN_TIME_DEFAULT);
  1468. Vector2 oldChange = endPos - _tweenStart;
  1469. //调整目标位置
  1470. LoopCheckingTarget(ref endPos);
  1471. if (_pageMode || _snapToItem)
  1472. AlignPosition(ref endPos, true);
  1473. _tweenChange = endPos - _tweenStart;
  1474. if (_tweenChange.x == 0 && _tweenChange.y == 0)
  1475. {
  1476. UpdateScrollBarVisible();
  1477. return;
  1478. }
  1479. //如果目标位置已调整,随之调整需要时间
  1480. if (_pageMode || _snapToItem)
  1481. {
  1482. FixDuration(0, oldChange.x);
  1483. FixDuration(1, oldChange.y);
  1484. }
  1485. }
  1486. StartTween(2);
  1487. }
  1488. private void __mouseWheel(EventContext context)
  1489. {
  1490. if (!_mouseWheelEnabled)
  1491. return;
  1492. InputEvent evt = context.inputEvent;
  1493. float delta = evt.mouseWheelDelta / Stage.devicePixelRatio;
  1494. if (_snapToItem && Mathf.Abs(delta) < 1)
  1495. delta = Mathf.Sign(delta);
  1496. if (_overlapSize.x > 0 && _overlapSize.y == 0)
  1497. {
  1498. float step = _pageMode ? _pageSize.x : _scrollStep;
  1499. SetPosX(_xPos + step * delta, false);
  1500. }
  1501. else
  1502. {
  1503. float step = _pageMode ? _pageSize.y : _scrollStep;
  1504. SetPosY(_yPos + step * delta, false);
  1505. }
  1506. }
  1507. private void __rollOver()
  1508. {
  1509. _hover = true;
  1510. UpdateScrollBarVisible();
  1511. }
  1512. private void __rollOut()
  1513. {
  1514. _hover = false;
  1515. UpdateScrollBarVisible();
  1516. }
  1517. internal void UpdateClipSoft()
  1518. {
  1519. Vector2 softness = _owner.clipSoftness;
  1520. if (softness.x != 0 || softness.y != 0)
  1521. {
  1522. _maskContainer.clipSoftness = new Vector4(
  1523. (_container.x >= 0 || !_softnessOnTopOrLeftSide) ? 0 : softness.x,
  1524. (_container.y >= 0 || !_softnessOnTopOrLeftSide) ? 0 : softness.y,
  1525. (-_container.x - _overlapSize.x >= 0) ? 0 : softness.x,
  1526. (-_container.y - _overlapSize.y >= 0) ? 0 : softness.y);
  1527. }
  1528. else
  1529. _maskContainer.clipSoftness = null;
  1530. }
  1531. private void UpdateScrollBarPos()
  1532. {
  1533. if (_vtScrollBar != null)
  1534. _vtScrollBar.setScrollPerc(_overlapSize.y == 0 ? 0 : Mathf.Clamp(-_container.y, 0, _overlapSize.y) / _overlapSize.y);
  1535. if (_hzScrollBar != null)
  1536. _hzScrollBar.setScrollPerc(_overlapSize.x == 0 ? 0 : Mathf.Clamp(-_container.x, 0, _overlapSize.x) / _overlapSize.x);
  1537. UpdateClipSoft();
  1538. CheckRefreshBar();
  1539. }
  1540. public void UpdateScrollBarVisible()
  1541. {
  1542. if (_vtScrollBar != null)
  1543. {
  1544. if (_viewSize.y <= _vtScrollBar.minSize || _vScrollNone)
  1545. _vtScrollBar.displayObject.visible = false;
  1546. else
  1547. UpdateScrollBarVisible2(_vtScrollBar);
  1548. }
  1549. if (_hzScrollBar != null)
  1550. {
  1551. if (_viewSize.x <= _hzScrollBar.minSize || _hScrollNone)
  1552. _hzScrollBar.displayObject.visible = false;
  1553. else
  1554. UpdateScrollBarVisible2(_hzScrollBar);
  1555. }
  1556. }
  1557. private void UpdateScrollBarVisible2(GScrollBar bar)
  1558. {
  1559. if (_scrollBarDisplayAuto)
  1560. GTween.Kill(bar, TweenPropType.Alpha, false);
  1561. if (_scrollBarDisplayAuto && !_hover && _tweening == 0 && !_dragged && !bar.gripDragging)
  1562. {
  1563. if (bar.displayObject.visible)
  1564. GTween.To(1, 0, 0.5f).SetDelay(0.5f).OnComplete(_hideScrollBarDelegate).SetTarget(bar, TweenPropType.Alpha);
  1565. }
  1566. else
  1567. {
  1568. bar.alpha = 1;
  1569. bar.displayObject.visible = true;
  1570. }
  1571. }
  1572. private void __barTweenComplete(GTweener tweener)
  1573. {
  1574. GObject bar = (GObject)tweener.target;
  1575. bar.alpha = 1;
  1576. bar.displayObject.visible = false;
  1577. }
  1578. float GetLoopPartSize(float division, int axis)
  1579. {
  1580. return (_contentSize[axis] + (axis == 0 ? ((GList)_owner).columnGap : ((GList)_owner).lineGap)) / division;
  1581. }
  1582. /// <summary>
  1583. /// 对当前的滚动位置进行循环滚动边界检查。当到达边界时,回退一半内容区域(循环滚动内容大小通常是真实内容大小的偶数倍)。
  1584. /// </summary>
  1585. /// <returns></returns>
  1586. bool LoopCheckingCurrent()
  1587. {
  1588. bool changed = false;
  1589. if (_loop == 1 && _overlapSize.x > 0)
  1590. {
  1591. if (_xPos < 0.001f)
  1592. {
  1593. _xPos += GetLoopPartSize(2, 0);
  1594. changed = true;
  1595. }
  1596. else if (_xPos >= _overlapSize.x)
  1597. {
  1598. _xPos -= GetLoopPartSize(2, 0);
  1599. changed = true;
  1600. }
  1601. }
  1602. else if (_loop == 2 && _overlapSize.y > 0)
  1603. {
  1604. if (_yPos < 0.001f)
  1605. {
  1606. _yPos += GetLoopPartSize(2, 1);
  1607. changed = true;
  1608. }
  1609. else if (_yPos >= _overlapSize.y)
  1610. {
  1611. _yPos -= GetLoopPartSize(2, 1);
  1612. changed = true;
  1613. }
  1614. }
  1615. if (changed)
  1616. _container.SetXY((int)-_xPos, (int)-_yPos);
  1617. return changed;
  1618. }
  1619. /// <summary>
  1620. /// 对目标位置进行循环滚动边界检查。当到达边界时,回退一半内容区域(循环滚动内容大小通常是真实内容大小的偶数倍)。
  1621. /// </summary>
  1622. /// <param name="endPos"></param>
  1623. void LoopCheckingTarget(ref Vector2 endPos)
  1624. {
  1625. if (_loop == 1)
  1626. LoopCheckingTarget(ref endPos, 0);
  1627. if (_loop == 2)
  1628. LoopCheckingTarget(ref endPos, 1);
  1629. }
  1630. void LoopCheckingTarget(ref Vector2 endPos, int axis)
  1631. {
  1632. if (endPos[axis] > 0)
  1633. {
  1634. float halfSize = GetLoopPartSize(2, axis);
  1635. float tmp = _tweenStart[axis] - halfSize;
  1636. if (tmp <= 0 && tmp >= -_overlapSize[axis])
  1637. {
  1638. endPos[axis] -= halfSize;
  1639. _tweenStart[axis] = tmp;
  1640. }
  1641. }
  1642. else if (endPos[axis] < -_overlapSize[axis])
  1643. {
  1644. float halfSize = GetLoopPartSize(2, axis);
  1645. float tmp = _tweenStart[axis] + halfSize;
  1646. if (tmp <= 0 && tmp >= -_overlapSize[axis])
  1647. {
  1648. endPos[axis] += halfSize;
  1649. _tweenStart[axis] = tmp;
  1650. }
  1651. }
  1652. }
  1653. void LoopCheckingNewPos(ref float value, int axis)
  1654. {
  1655. if (_overlapSize[axis] == 0)
  1656. return;
  1657. float pos = axis == 0 ? _xPos : _yPos;
  1658. bool changed = false;
  1659. if (value < 0.001f)
  1660. {
  1661. value += GetLoopPartSize(2, axis);
  1662. if (value > pos)
  1663. {
  1664. float v = GetLoopPartSize(6, axis);
  1665. v = Mathf.CeilToInt((value - pos) / v) * v;
  1666. pos = Mathf.Clamp(pos + v, 0, _overlapSize[axis]);
  1667. changed = true;
  1668. }
  1669. }
  1670. else if (value >= _overlapSize[axis])
  1671. {
  1672. value -= GetLoopPartSize(2, axis);
  1673. if (value < pos)
  1674. {
  1675. float v = GetLoopPartSize(6, axis);
  1676. v = Mathf.CeilToInt((pos - value) / v) * v;
  1677. pos = Mathf.Clamp(pos - v, 0, _overlapSize[axis]);
  1678. changed = true;
  1679. }
  1680. }
  1681. if (changed)
  1682. {
  1683. if (axis == 0)
  1684. _container.x = -(int)pos;
  1685. else
  1686. _container.y = -(int)pos;
  1687. }
  1688. }
  1689. /// <summary>
  1690. /// 从oldPos滚动至pos,调整pos位置对齐页面、对齐item等(如果需要)。
  1691. /// </summary>
  1692. /// <param name="pos"></param>
  1693. /// <param name="inertialScrolling"></param>
  1694. void AlignPosition(ref Vector2 pos, bool inertialScrolling)
  1695. {
  1696. if (_pageMode)
  1697. {
  1698. pos.x = AlignByPage(pos.x, 0, inertialScrolling);
  1699. pos.y = AlignByPage(pos.y, 1, inertialScrolling);
  1700. }
  1701. else if (_snapToItem)
  1702. {
  1703. float tmpX = -pos.x;
  1704. float tmpY = -pos.y;
  1705. _owner.GetSnappingPosition(ref tmpX, ref tmpY);
  1706. if (pos.x < 0 && pos.x > -_overlapSize.x)
  1707. pos.x = -tmpX;
  1708. if (pos.y < 0 && pos.y > -_overlapSize.y)
  1709. pos.y = -tmpY;
  1710. }
  1711. }
  1712. /// <summary>
  1713. /// 从oldPos滚动至pos,调整目标位置到对齐页面。
  1714. /// </summary>
  1715. /// <param name="pos"></param>
  1716. /// <param name="axis"></param>
  1717. /// <param name="inertialScrolling"></param>
  1718. /// <returns></returns>
  1719. float AlignByPage(float pos, int axis, bool inertialScrolling)
  1720. {
  1721. int page;
  1722. if (pos > 0)
  1723. page = 0;
  1724. else if (pos < -_overlapSize[axis])
  1725. page = Mathf.CeilToInt(_contentSize[axis] / _pageSize[axis]) - 1;
  1726. else
  1727. {
  1728. page = Mathf.FloorToInt(-pos / _pageSize[axis]);
  1729. float change = inertialScrolling ? (pos - _containerPos[axis]) : (pos - _container.xy[axis]);
  1730. float testPageSize = Mathf.Min(_pageSize[axis], _contentSize[axis] - (page + 1) * _pageSize[axis]);
  1731. float delta = -pos - page * _pageSize[axis];
  1732. //页面吸附策略
  1733. if (Mathf.Abs(change) > _pageSize[axis])//如果滚动距离超过1页,则需要超过页面的一半,才能到更下一页
  1734. {
  1735. if (delta > testPageSize * 0.5f)
  1736. page++;
  1737. }
  1738. else //否则只需要页面的1/3,当然,需要考虑到左移和右移的情况
  1739. {
  1740. if (delta > testPageSize * (change < 0 ? 0.3f : 0.7f))
  1741. page++;
  1742. }
  1743. //重新计算终点
  1744. pos = -page * _pageSize[axis];
  1745. if (pos < -_overlapSize[axis]) //最后一页未必有pageSize那么大
  1746. pos = -_overlapSize[axis];
  1747. }
  1748. //惯性滚动模式下,会增加判断尽量不要滚动超过一页
  1749. if (inertialScrolling)
  1750. {
  1751. float oldPos = _tweenStart[axis];
  1752. int oldPage;
  1753. if (oldPos > 0)
  1754. oldPage = 0;
  1755. else if (oldPos < -_overlapSize[axis])
  1756. oldPage = Mathf.CeilToInt(_contentSize[axis] / _pageSize[axis]) - 1;
  1757. else
  1758. oldPage = Mathf.FloorToInt(-oldPos / _pageSize[axis]);
  1759. int startPage = Mathf.FloorToInt(-_containerPos[axis] / _pageSize[axis]);
  1760. if (Mathf.Abs(page - startPage) > 1 && Mathf.Abs(oldPage - startPage) <= 1)
  1761. {
  1762. if (page > startPage)
  1763. page = startPage + 1;
  1764. else
  1765. page = startPage - 1;
  1766. pos = -page * _pageSize[axis];
  1767. }
  1768. }
  1769. return pos;
  1770. }
  1771. /// <summary>
  1772. /// 根据当前速度,计算滚动的目标位置,以及到达时间。
  1773. /// </summary>
  1774. /// <param name="orignPos"></param>
  1775. /// <returns></returns>
  1776. Vector2 UpdateTargetAndDuration(Vector2 orignPos)
  1777. {
  1778. Vector2 ret = Vector2.zero;
  1779. ret.x = UpdateTargetAndDuration(orignPos.x, 0);
  1780. ret.y = UpdateTargetAndDuration(orignPos.y, 1);
  1781. return ret;
  1782. }
  1783. float UpdateTargetAndDuration(float pos, int axis)
  1784. {
  1785. float v = _velocity[axis];
  1786. float duration = 0;
  1787. if (pos > 0)
  1788. pos = 0;
  1789. else if (pos < -_overlapSize[axis])
  1790. pos = -_overlapSize[axis];
  1791. else
  1792. {
  1793. //以屏幕像素为基准
  1794. float v2 = Mathf.Abs(v) * _velocityScale;
  1795. //在移动设备上,需要对不同分辨率做一个适配,我们的速度判断以1136分辨率为基准
  1796. if (Stage.touchScreen)
  1797. v2 *= 1136f / Mathf.Max(Screen.width, Screen.height);
  1798. //这里有一些阈值的处理,因为在低速内,不希望产生较大的滚动(甚至不滚动)
  1799. float ratio = 0;
  1800. if (_pageMode || !Stage.touchScreen)
  1801. {
  1802. if (v2 > 500)
  1803. ratio = Mathf.Pow((v2 - 500) / 500, 2);
  1804. }
  1805. else
  1806. {
  1807. if (v2 > 1000)
  1808. ratio = Mathf.Pow((v2 - 1000) / 1000, 2);
  1809. }
  1810. if (ratio != 0)
  1811. {
  1812. if (ratio > 1)
  1813. ratio = 1;
  1814. v2 *= ratio;
  1815. v *= ratio;
  1816. _velocity[axis] = v;
  1817. //算法:v*(_decelerationRate的n次幂)= 60,即在n帧后速度降为60(假设每秒60帧)。
  1818. duration = Mathf.Log(60 / v2, _decelerationRate) / 60;
  1819. //计算距离要使用本地速度
  1820. //理论公式貌似滚动的距离不够,改为经验公式
  1821. //float change = (int)((v/ 60 - 1) / (1 - _decelerationRate));
  1822. float change = (int)(v * duration * 0.4f);
  1823. pos += change;
  1824. }
  1825. }
  1826. if (duration < TWEEN_TIME_DEFAULT)
  1827. duration = TWEEN_TIME_DEFAULT;
  1828. _tweenDuration[axis] = duration;
  1829. return pos;
  1830. }
  1831. /// <summary>
  1832. /// 根据修改后的tweenChange重新计算减速时间。
  1833. /// </summary>
  1834. void FixDuration(int axis, float oldChange)
  1835. {
  1836. if (_tweenChange[axis] == 0 || Mathf.Abs(_tweenChange[axis]) >= Mathf.Abs(oldChange))
  1837. return;
  1838. float newDuration = Mathf.Abs(_tweenChange[axis] / oldChange) * _tweenDuration[axis];
  1839. if (newDuration < TWEEN_TIME_DEFAULT)
  1840. newDuration = TWEEN_TIME_DEFAULT;
  1841. _tweenDuration[axis] = newDuration;
  1842. }
  1843. void StartTween(int type)
  1844. {
  1845. _tweenTime.Set(0, 0);
  1846. _tweening = type;
  1847. Timers.inst.AddUpdate(_tweenUpdateDelegate);
  1848. UpdateScrollBarVisible();
  1849. }
  1850. void KillTween()
  1851. {
  1852. if (_tweening == 1) //取消类型为1的tween需立刻设置到终点
  1853. {
  1854. _container.xy = _tweenStart + _tweenChange;
  1855. _onScroll.Call();
  1856. }
  1857. _tweening = 0;
  1858. Timers.inst.Remove(_tweenUpdateDelegate);
  1859. UpdateScrollBarVisible();
  1860. _onScrollEnd.Call();
  1861. }
  1862. void CheckRefreshBar()
  1863. {
  1864. if (_header == null && _footer == null)
  1865. return;
  1866. float pos = _container.xy[_refreshBarAxis];
  1867. if (_header != null)
  1868. {
  1869. if (pos > 0)
  1870. {
  1871. if (_header.displayObject.parent == null)
  1872. _maskContainer.AddChildAt(_header.displayObject, 0);
  1873. Vector2 vec;
  1874. vec = _header.size;
  1875. vec[_refreshBarAxis] = pos;
  1876. _header.size = vec;
  1877. }
  1878. else
  1879. {
  1880. if (_header.displayObject.parent != null)
  1881. _maskContainer.RemoveChild(_header.displayObject);
  1882. }
  1883. }
  1884. if (_footer != null)
  1885. {
  1886. float max = _overlapSize[_refreshBarAxis];
  1887. if (pos < -max || max == 0 && _footerLockedSize > 0)
  1888. {
  1889. if (_footer.displayObject.parent == null)
  1890. _maskContainer.AddChildAt(_footer.displayObject, 0);
  1891. Vector2 vec;
  1892. vec = _footer.xy;
  1893. if (max > 0)
  1894. vec[_refreshBarAxis] = pos + _contentSize[_refreshBarAxis];
  1895. else
  1896. vec[_refreshBarAxis] = Mathf.Max(Mathf.Min(pos + _viewSize[_refreshBarAxis], _viewSize[_refreshBarAxis] - _footerLockedSize), _viewSize[_refreshBarAxis] - _contentSize[_refreshBarAxis]);
  1897. _footer.xy = vec;
  1898. vec = _footer.size;
  1899. if (max > 0)
  1900. vec[_refreshBarAxis] = -max - pos;
  1901. else
  1902. vec[_refreshBarAxis] = _viewSize[_refreshBarAxis] - _footer.xy[_refreshBarAxis];
  1903. _footer.size = vec;
  1904. }
  1905. else
  1906. {
  1907. if (_footer.displayObject.parent != null)
  1908. _maskContainer.RemoveChild(_footer.displayObject);
  1909. }
  1910. }
  1911. }
  1912. void TweenUpdate(object param)
  1913. {
  1914. if (_owner.displayObject == null || _owner.displayObject.isDisposed)
  1915. {
  1916. Timers.inst.Remove(_tweenUpdateDelegate);
  1917. return;
  1918. }
  1919. float nx = RunTween(0);
  1920. float ny = RunTween(1);
  1921. _container.SetXY(nx, ny);
  1922. if (_tweening == 2)
  1923. {
  1924. if (_overlapSize.x > 0)
  1925. _xPos = Mathf.Clamp(-nx, 0, _overlapSize.x);
  1926. if (_overlapSize.y > 0)
  1927. _yPos = Mathf.Clamp(-ny, 0, _overlapSize.y);
  1928. if (_pageMode)
  1929. UpdatePageController();
  1930. }
  1931. if (_tweenChange.x == 0 && _tweenChange.y == 0)
  1932. {
  1933. _tweening = 0;
  1934. Timers.inst.Remove(_tweenUpdateDelegate);
  1935. LoopCheckingCurrent();
  1936. UpdateScrollBarPos();
  1937. UpdateScrollBarVisible();
  1938. _onScroll.Call();
  1939. _onScrollEnd.Call();
  1940. }
  1941. else
  1942. {
  1943. UpdateScrollBarPos();
  1944. _onScroll.Call();
  1945. }
  1946. }
  1947. float RunTween(int axis)
  1948. {
  1949. float newValue;
  1950. if (_tweenChange[axis] != 0)
  1951. {
  1952. _tweenTime[axis] += Time.unscaledDeltaTime;
  1953. if (_tweenTime[axis] >= _tweenDuration[axis])
  1954. {
  1955. newValue = _tweenStart[axis] + _tweenChange[axis];
  1956. _tweenChange[axis] = 0;
  1957. }
  1958. else
  1959. {
  1960. float ratio = EaseFunc(_tweenTime[axis], _tweenDuration[axis]);
  1961. newValue = _tweenStart[axis] + (int)(_tweenChange[axis] * ratio);
  1962. }
  1963. float threshold1 = 0;
  1964. float threshold2 = -_overlapSize[axis];
  1965. if (_headerLockedSize > 0 && _refreshBarAxis == axis)
  1966. threshold1 = _headerLockedSize;
  1967. if (_footerLockedSize > 0 && _refreshBarAxis == axis)
  1968. {
  1969. float max = _overlapSize[_refreshBarAxis];
  1970. if (max == 0)
  1971. max = Mathf.Max(_contentSize[_refreshBarAxis] + _footerLockedSize - _viewSize[_refreshBarAxis], 0);
  1972. else
  1973. max += _footerLockedSize;
  1974. threshold2 = -max;
  1975. }
  1976. if (_tweening == 2 && _bouncebackEffect)
  1977. {
  1978. if (newValue > 20 + threshold1 && _tweenChange[axis] > 0
  1979. || newValue > threshold1 && _tweenChange[axis] == 0)//开始回弹
  1980. {
  1981. _tweenTime[axis] = 0;
  1982. _tweenDuration[axis] = TWEEN_TIME_DEFAULT;
  1983. _tweenChange[axis] = -newValue + threshold1;
  1984. _tweenStart[axis] = newValue;
  1985. }
  1986. else if (newValue < threshold2 - 20 && _tweenChange[axis] < 0
  1987. || newValue < threshold2 && _tweenChange[axis] == 0)//开始回弹
  1988. {
  1989. _tweenTime[axis] = 0;
  1990. _tweenDuration[axis] = TWEEN_TIME_DEFAULT;
  1991. _tweenChange[axis] = threshold2 - newValue;
  1992. _tweenStart[axis] = newValue;
  1993. }
  1994. }
  1995. else
  1996. {
  1997. if (newValue > threshold1)
  1998. {
  1999. newValue = threshold1;
  2000. _tweenChange[axis] = 0;
  2001. }
  2002. else if (newValue < threshold2)
  2003. {
  2004. newValue = threshold2;
  2005. _tweenChange[axis] = 0;
  2006. }
  2007. }
  2008. }
  2009. else
  2010. newValue = _container.xy[axis];
  2011. return newValue;
  2012. }
  2013. static float EaseFunc(float t, float d)
  2014. {
  2015. return (t = t / d - 1) * t * t + 1;//cubicOut
  2016. }
  2017. }
  2018. }