ScrollPane.cs 77 KB

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