ScrollPane.cs 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320
  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 (rect.yMax >= bottom) //if an item size is large than viewSize, dont scroll
  780. return;
  781. if (_pageMode)
  782. this.SetPosY(Mathf.Floor(rect.y / _pageSize.y) * _pageSize.y, ani);
  783. else
  784. SetPosY(rect.y, ani);
  785. }
  786. else if (rect.yMax > bottom)
  787. {
  788. if (_pageMode)
  789. this.SetPosY(Mathf.Floor(rect.y / _pageSize.y) * _pageSize.y, ani);
  790. else if (rect.height <= _viewSize.y / 2)
  791. SetPosY(rect.y + rect.height * 2 - _viewSize.y, ani);
  792. else
  793. SetPosY(rect.y + Mathf.Min(rect.height - _viewSize.y, 0), ani);
  794. }
  795. }
  796. if (_overlapSize.x > 0)
  797. {
  798. float right = _xPos + _viewSize.x;
  799. if (setFirst || rect.x <= _xPos || rect.width >= _viewSize.x)
  800. {
  801. if (rect.xMax >= right) //if an item size is large than viewSize, dont scroll
  802. return;
  803. if (_pageMode)
  804. this.SetPosX(Mathf.Floor(rect.x / _pageSize.x) * _pageSize.x, ani);
  805. SetPosX(rect.x, ani);
  806. }
  807. else if (rect.xMax > right)
  808. {
  809. if (_pageMode)
  810. this.SetPosX(Mathf.Floor(rect.x / _pageSize.x) * _pageSize.x, ani);
  811. else if (rect.width <= _viewSize.x / 2)
  812. SetPosX(rect.x + rect.width * 2 - _viewSize.x, ani);
  813. else
  814. SetPosX(rect.x + Mathf.Min(rect.width - _viewSize.x, 0), ani);
  815. }
  816. }
  817. if (!ani && _needRefresh)
  818. Refresh();
  819. }
  820. /// <summary>
  821. ///
  822. /// </summary>
  823. /// <param name="obj">obj must be the direct child of this container</param>
  824. /// <returns></returns>
  825. public bool IsChildInView(GObject obj)
  826. {
  827. if (_overlapSize.y > 0)
  828. {
  829. float dist = obj.y + _container.y;
  830. if (dist <= -obj.height || dist >= _viewSize.y)
  831. return false;
  832. }
  833. if (_overlapSize.x > 0)
  834. {
  835. float dist = obj.x + _container.x;
  836. if (dist <= -obj.width || dist >= _viewSize.x)
  837. return false;
  838. }
  839. return true;
  840. }
  841. /// <summary>
  842. /// 当滚动面板处于拖拽滚动状态或即将进入拖拽状态时,可以调用此方法停止或禁止本次拖拽。
  843. /// </summary>
  844. public void CancelDragging()
  845. {
  846. Stage.inst.RemoveTouchMonitor(_owner.rootContainer);
  847. if (draggingPane == this)
  848. draggingPane = null;
  849. _gestureFlag = 0;
  850. _dragged = false;
  851. }
  852. /// <summary>
  853. /// 设置Header固定显示。如果size为0,则取消固定显示。
  854. /// </summary>
  855. /// <param name="size">Header显示的大小</param>
  856. public void LockHeader(int size)
  857. {
  858. if (_headerLockedSize == size)
  859. return;
  860. _headerLockedSize = size;
  861. if (!isDispatching("onPullDownRelease") && _container.xy[_refreshBarAxis] >= 0)
  862. {
  863. _tweenStart = _container.xy;
  864. _tweenChange = Vector2.zero;
  865. _tweenChange[_refreshBarAxis] = _headerLockedSize - _tweenStart[_refreshBarAxis];
  866. _tweenDuration = new Vector2(TWEEN_TIME_DEFAULT, TWEEN_TIME_DEFAULT);
  867. StartTween(2);
  868. }
  869. }
  870. /// <summary>
  871. /// 设置Footer固定显示。如果size为0,则取消固定显示。
  872. /// </summary>
  873. /// <param name="size"></param>
  874. public void LockFooter(int size)
  875. {
  876. if (_footerLockedSize == size)
  877. return;
  878. _footerLockedSize = size;
  879. if (!isDispatching("onPullUpRelease") && _container.xy[_refreshBarAxis] <= -_overlapSize[_refreshBarAxis])
  880. {
  881. _tweenStart = _container.xy;
  882. _tweenChange = Vector2.zero;
  883. float max = _overlapSize[_refreshBarAxis];
  884. if (max == 0)
  885. max = Mathf.Max(_contentSize[_refreshBarAxis] + _footerLockedSize - _viewSize[_refreshBarAxis], 0);
  886. else
  887. max += _footerLockedSize;
  888. _tweenChange[_refreshBarAxis] = -max - _tweenStart[_refreshBarAxis];
  889. _tweenDuration = new Vector2(TWEEN_TIME_DEFAULT, TWEEN_TIME_DEFAULT);
  890. StartTween(2);
  891. }
  892. }
  893. internal void OnOwnerSizeChanged()
  894. {
  895. SetSize(_owner.width, _owner.height);
  896. PosChanged(false);
  897. }
  898. internal void HandleControllerChanged(Controller c)
  899. {
  900. if (_pageController == c)
  901. {
  902. if (_scrollType == ScrollType.Horizontal)
  903. this.SetCurrentPageX(c.selectedIndex, true);
  904. else
  905. this.SetCurrentPageY(c.selectedIndex, true);
  906. }
  907. }
  908. void UpdatePageController()
  909. {
  910. if (_pageController != null && !_pageController.changing)
  911. {
  912. int index;
  913. if (_scrollType == ScrollType.Horizontal)
  914. index = this.currentPageX;
  915. else
  916. index = this.currentPageY;
  917. if (index < _pageController.pageCount)
  918. {
  919. Controller c = _pageController;
  920. _pageController = null; //防止HandleControllerChanged的调用
  921. c.selectedIndex = index;
  922. _pageController = c;
  923. }
  924. }
  925. }
  926. internal void AdjustMaskContainer()
  927. {
  928. float mx, my;
  929. if (_displayOnLeft && _vtScrollBar != null && !_floating)
  930. mx = Mathf.FloorToInt(_owner.margin.left + _vtScrollBar.width);
  931. else
  932. mx = _owner.margin.left;
  933. my = _owner.margin.top;
  934. mx += _owner._alignOffset.x;
  935. my += _owner._alignOffset.y;
  936. _maskContainer.SetXY(mx, my);
  937. }
  938. void SetSize(float aWidth, float aHeight)
  939. {
  940. AdjustMaskContainer();
  941. if (_hzScrollBar != null)
  942. {
  943. _hzScrollBar.y = aHeight - _hzScrollBar.height;
  944. if (_vtScrollBar != null)
  945. {
  946. _hzScrollBar.width = aWidth - _vtScrollBar.width - _scrollBarMargin.left - _scrollBarMargin.right;
  947. if (_displayOnLeft)
  948. _hzScrollBar.x = _scrollBarMargin.left + _vtScrollBar.width;
  949. else
  950. _hzScrollBar.x = _scrollBarMargin.left;
  951. }
  952. else
  953. {
  954. _hzScrollBar.width = aWidth - _scrollBarMargin.left - _scrollBarMargin.right;
  955. _hzScrollBar.x = _scrollBarMargin.left;
  956. }
  957. }
  958. if (_vtScrollBar != null)
  959. {
  960. if (!_displayOnLeft)
  961. _vtScrollBar.x = aWidth - _vtScrollBar.width;
  962. if (_hzScrollBar != null)
  963. _vtScrollBar.height = aHeight - _hzScrollBar.height - _scrollBarMargin.top - _scrollBarMargin.bottom;
  964. else
  965. _vtScrollBar.height = aHeight - _scrollBarMargin.top - _scrollBarMargin.bottom;
  966. _vtScrollBar.y = _scrollBarMargin.top;
  967. }
  968. _viewSize.x = aWidth;
  969. _viewSize.y = aHeight;
  970. if (_hzScrollBar != null && !_floating)
  971. _viewSize.y -= _hzScrollBar.height;
  972. if (_vtScrollBar != null && !_floating)
  973. _viewSize.x -= _vtScrollBar.width;
  974. _viewSize.x -= (_owner.margin.left + _owner.margin.right);
  975. _viewSize.y -= (_owner.margin.top + _owner.margin.bottom);
  976. _viewSize.x = Mathf.Max(1, _viewSize.x);
  977. _viewSize.y = Mathf.Max(1, _viewSize.y);
  978. _pageSize.x = _viewSize.x;
  979. _pageSize.y = _viewSize.y;
  980. HandleSizeChanged();
  981. }
  982. internal void SetContentSize(float aWidth, float aHeight)
  983. {
  984. if (Mathf.Approximately(_contentSize.x, aWidth) && Mathf.Approximately(_contentSize.y, aHeight))
  985. return;
  986. _contentSize.x = aWidth;
  987. _contentSize.y = aHeight;
  988. HandleSizeChanged();
  989. }
  990. /// <summary>
  991. /// 内部使用。由虚拟列表调用。在滚动时修改显示内容的大小,需要进行修正,避免滚动跳跃。
  992. /// </summary>
  993. /// <param name="deltaWidth"></param>
  994. /// <param name="deltaHeight"></param>
  995. /// <param name="deltaPosX"></param>
  996. /// <param name="deltaPosY"></param>
  997. internal void ChangeContentSizeOnScrolling(float deltaWidth, float deltaHeight, float deltaPosX, float deltaPosY)
  998. {
  999. bool isRightmost = _xPos == _overlapSize.x;
  1000. bool isBottom = _yPos == _overlapSize.y;
  1001. _contentSize.x += deltaWidth;
  1002. _contentSize.y += deltaHeight;
  1003. HandleSizeChanged();
  1004. if (_tweening == 1)
  1005. {
  1006. //如果原来滚动位置是贴边,加入处理继续贴边。
  1007. if (deltaWidth != 0 && isRightmost && _tweenChange.x < 0)
  1008. {
  1009. _xPos = _overlapSize.x;
  1010. _tweenChange.x = -_xPos - _tweenStart.x;
  1011. }
  1012. if (deltaHeight != 0 && isBottom && _tweenChange.y < 0)
  1013. {
  1014. _yPos = _overlapSize.y;
  1015. _tweenChange.y = -_yPos - _tweenStart.y;
  1016. }
  1017. }
  1018. else if (_tweening == 2)
  1019. {
  1020. //重新调整起始位置,确保能够顺滑滚下去
  1021. if (deltaPosX != 0)
  1022. {
  1023. _container.x -= deltaPosX;
  1024. _tweenStart.x -= deltaPosX;
  1025. _xPos = -_container.x;
  1026. }
  1027. if (deltaPosY != 0)
  1028. {
  1029. _container.y -= deltaPosY;
  1030. _tweenStart.y -= deltaPosY;
  1031. _yPos = -_container.y;
  1032. }
  1033. }
  1034. else if (_dragged)
  1035. {
  1036. if (deltaPosX != 0)
  1037. {
  1038. _container.x -= deltaPosX;
  1039. _containerPos.x -= deltaPosX;
  1040. _xPos = -_container.x;
  1041. }
  1042. if (deltaPosY != 0)
  1043. {
  1044. _container.y -= deltaPosY;
  1045. _containerPos.y -= deltaPosY;
  1046. _yPos = -_container.y;
  1047. }
  1048. }
  1049. else
  1050. {
  1051. //如果原来滚动位置是贴边,加入处理继续贴边。
  1052. if (deltaWidth != 0 && isRightmost)
  1053. {
  1054. _xPos = _overlapSize.x;
  1055. _container.x = -_xPos;
  1056. }
  1057. if (deltaHeight != 0 && isBottom)
  1058. {
  1059. _yPos = _overlapSize.y;
  1060. _container.y = -_yPos;
  1061. }
  1062. }
  1063. if (_pageMode)
  1064. UpdatePageController();
  1065. }
  1066. void HandleSizeChanged()
  1067. {
  1068. if (_displayInDemand)
  1069. {
  1070. _vScrollNone = _contentSize.y <= _viewSize.y;
  1071. _hScrollNone = _contentSize.x <= _viewSize.x;
  1072. if (_vtScrollBar != null && _hzScrollBar != null)
  1073. {
  1074. if (!_hScrollNone)
  1075. _vtScrollBar.height = _owner.height - _hzScrollBar.height - _scrollBarMargin.top - _scrollBarMargin.bottom;
  1076. else
  1077. _vtScrollBar.height = _owner.height - _scrollBarMargin.top - _scrollBarMargin.bottom;
  1078. if (!_vScrollNone)
  1079. _hzScrollBar.width = _owner.width - _vtScrollBar.width - _scrollBarMargin.left - _scrollBarMargin.right;
  1080. else
  1081. _hzScrollBar.width = _owner.width - _scrollBarMargin.left - _scrollBarMargin.right;
  1082. }
  1083. }
  1084. if (_vtScrollBar != null)
  1085. {
  1086. if (_contentSize.y == 0)
  1087. _vtScrollBar.SetDisplayPerc(0);
  1088. else
  1089. _vtScrollBar.SetDisplayPerc(Mathf.Min(1, _viewSize.y / _contentSize.y));
  1090. }
  1091. if (_hzScrollBar != null)
  1092. {
  1093. if (_contentSize.x == 0)
  1094. _hzScrollBar.SetDisplayPerc(0);
  1095. else
  1096. _hzScrollBar.SetDisplayPerc(Mathf.Min(1, _viewSize.x / _contentSize.x));
  1097. }
  1098. UpdateScrollBarVisible();
  1099. if (!_maskDisabled)
  1100. {
  1101. Rect rect = new Rect(-_owner._alignOffset.x, -_owner._alignOffset.y, _viewSize.x, _viewSize.y);
  1102. if (_vScrollNone && _vtScrollBar != null)
  1103. rect.width += _vtScrollBar.width;
  1104. if (_hScrollNone && _hzScrollBar != null)
  1105. rect.height += _hzScrollBar.height;
  1106. if (_dontClipMargin)
  1107. {
  1108. rect.x -= _owner.margin.left;
  1109. rect.width += (_owner.margin.left + _owner.margin.right);
  1110. rect.y -= _owner.margin.top;
  1111. rect.height += (_owner.margin.top + _owner.margin.bottom);
  1112. }
  1113. _maskContainer.clipRect = rect;
  1114. }
  1115. if (_scrollType == ScrollType.Horizontal || _scrollType == ScrollType.Both)
  1116. _overlapSize.x = Mathf.CeilToInt(Math.Max(0, _contentSize.x - _viewSize.x));
  1117. else
  1118. _overlapSize.x = 0;
  1119. if (_scrollType == ScrollType.Vertical || _scrollType == ScrollType.Both)
  1120. _overlapSize.y = Mathf.CeilToInt(Math.Max(0, _contentSize.y - _viewSize.y));
  1121. else
  1122. _overlapSize.y = 0;
  1123. //边界检查
  1124. _xPos = Mathf.Clamp(_xPos, 0, _overlapSize.x);
  1125. _yPos = Mathf.Clamp(_yPos, 0, _overlapSize.y);
  1126. float max = _overlapSize[_refreshBarAxis];
  1127. if (max == 0)
  1128. max = Mathf.Max(_contentSize[_refreshBarAxis] + _footerLockedSize - _viewSize[_refreshBarAxis], 0);
  1129. else
  1130. max += _footerLockedSize;
  1131. if (_refreshBarAxis == 0)
  1132. _container.SetXY(Mathf.Clamp(_container.x, -max, _headerLockedSize), Mathf.Clamp(_container.y, -_overlapSize.y, 0));
  1133. else
  1134. _container.SetXY(Mathf.Clamp(_container.x, -_overlapSize.x, 0), Mathf.Clamp(_container.y, -max, _headerLockedSize));
  1135. if (_header != null)
  1136. {
  1137. if (_refreshBarAxis == 0)
  1138. _header.height = _viewSize.y;
  1139. else
  1140. _header.width = _viewSize.x;
  1141. }
  1142. if (_footer != null)
  1143. {
  1144. if (_refreshBarAxis == 0)
  1145. _footer.height = _viewSize.y;
  1146. else
  1147. _footer.width = _viewSize.x;
  1148. }
  1149. UpdateScrollBarPos();
  1150. if (_pageMode)
  1151. UpdatePageController();
  1152. }
  1153. private void PosChanged(bool ani)
  1154. {
  1155. //只要有1处要求不要缓动,那就不缓动
  1156. if (_aniFlag == 0)
  1157. _aniFlag = ani ? 1 : -1;
  1158. else if (_aniFlag == 1 && !ani)
  1159. _aniFlag = -1;
  1160. _needRefresh = true;
  1161. UpdateContext.OnBegin -= _refreshDelegate;
  1162. UpdateContext.OnBegin += _refreshDelegate;
  1163. }
  1164. private void Refresh()
  1165. {
  1166. _needRefresh = false;
  1167. UpdateContext.OnBegin -= _refreshDelegate;
  1168. if (_owner.displayObject == null || _owner.displayObject.isDisposed)
  1169. return;
  1170. if (_pageMode || _snapToItem)
  1171. {
  1172. Vector2 pos = new Vector2(-_xPos, -_yPos);
  1173. AlignPosition(ref pos, false);
  1174. _xPos = -pos.x;
  1175. _yPos = -pos.y;
  1176. }
  1177. Refresh2();
  1178. _onScroll.Call();
  1179. if (_needRefresh) //在onScroll事件里开发者可能修改位置,这里再刷新一次,避免闪烁
  1180. {
  1181. _needRefresh = false;
  1182. UpdateContext.OnBegin -= _refreshDelegate;
  1183. Refresh2();
  1184. }
  1185. UpdateScrollBarPos();
  1186. _aniFlag = 0;
  1187. }
  1188. void Refresh2()
  1189. {
  1190. if (_aniFlag == 1 && !_dragged)
  1191. {
  1192. Vector2 pos = new Vector2();
  1193. if (_overlapSize.x > 0)
  1194. pos.x = -(int)_xPos;
  1195. else
  1196. {
  1197. if (_container.x != 0)
  1198. _container.x = 0;
  1199. pos.x = 0;
  1200. }
  1201. if (_overlapSize.y > 0)
  1202. pos.y = -(int)_yPos;
  1203. else
  1204. {
  1205. if (_container.y != 0)
  1206. _container.y = 0;
  1207. pos.y = 0;
  1208. }
  1209. if (pos.x != _container.x || pos.y != _container.y)
  1210. {
  1211. _tweenDuration = new Vector2(TWEEN_TIME_GO, TWEEN_TIME_GO);
  1212. _tweenStart = _container.xy;
  1213. _tweenChange = pos - _tweenStart;
  1214. StartTween(1);
  1215. }
  1216. else if (_tweening != 0)
  1217. KillTween();
  1218. }
  1219. else
  1220. {
  1221. if (_tweening != 0)
  1222. KillTween();
  1223. _container.SetXY((int)-_xPos, (int)-_yPos);
  1224. LoopCheckingCurrent();
  1225. }
  1226. if (_pageMode)
  1227. UpdatePageController();
  1228. }
  1229. private void __touchBegin(EventContext context)
  1230. {
  1231. if (!_touchEffect)
  1232. return;
  1233. InputEvent evt = context.inputEvent;
  1234. if (evt.button != 0)
  1235. return;
  1236. context.CaptureTouch();
  1237. Vector2 pt = _owner.GlobalToLocal(evt.position);
  1238. if (_tweening != 0)
  1239. {
  1240. KillTween();
  1241. Stage.inst.CancelClick(evt.touchId);
  1242. //立刻停止惯性滚动,可能位置不对齐,设定这个标志,使touchEnd时归位
  1243. _dragged = true;
  1244. }
  1245. else
  1246. _dragged = false;
  1247. _containerPos = _container.xy;
  1248. _beginTouchPos = _lastTouchPos = pt;
  1249. _lastTouchGlobalPos = evt.position;
  1250. _isHoldAreaDone = false;
  1251. _velocity = Vector2.zero;
  1252. _velocityScale = 1;
  1253. _lastMoveTime = Time.unscaledTime;
  1254. }
  1255. private void __touchMove(EventContext context)
  1256. {
  1257. if (!_touchEffect || draggingPane != null && draggingPane != this || GObject.draggingObject != null) //已经有其他拖动
  1258. return;
  1259. InputEvent evt = context.inputEvent;
  1260. Vector2 pt = _owner.GlobalToLocal(evt.position);
  1261. if (float.IsNaN(pt.x))
  1262. return;
  1263. int sensitivity;
  1264. if (Stage.touchScreen)
  1265. sensitivity = UIConfig.touchScrollSensitivity;
  1266. else
  1267. sensitivity = 8;
  1268. float diff;
  1269. bool sv = false, sh = false;
  1270. if (_scrollType == ScrollType.Vertical)
  1271. {
  1272. if (!_isHoldAreaDone)
  1273. {
  1274. //表示正在监测垂直方向的手势
  1275. _gestureFlag |= 1;
  1276. diff = Mathf.Abs(_beginTouchPos.y - pt.y);
  1277. if (diff < sensitivity)
  1278. return;
  1279. if ((_gestureFlag & 2) != 0) //已经有水平方向的手势在监测,那么我们用严格的方式检查是不是按垂直方向移动,避免冲突
  1280. {
  1281. float diff2 = Mathf.Abs(_beginTouchPos.x - pt.x);
  1282. if (diff < diff2) //不通过则不允许滚动了
  1283. return;
  1284. }
  1285. }
  1286. sv = true;
  1287. }
  1288. else if (_scrollType == ScrollType.Horizontal)
  1289. {
  1290. if (!_isHoldAreaDone)
  1291. {
  1292. _gestureFlag |= 2;
  1293. diff = Mathf.Abs(_beginTouchPos.x - pt.x);
  1294. if (diff < sensitivity)
  1295. return;
  1296. if ((_gestureFlag & 1) != 0)
  1297. {
  1298. float diff2 = Mathf.Abs(_beginTouchPos.y - pt.y);
  1299. if (diff < diff2)
  1300. return;
  1301. }
  1302. }
  1303. sh = true;
  1304. }
  1305. else
  1306. {
  1307. _gestureFlag = 3;
  1308. if (!_isHoldAreaDone)
  1309. {
  1310. diff = Mathf.Abs(_beginTouchPos.y - pt.y);
  1311. if (diff < sensitivity)
  1312. {
  1313. diff = Mathf.Abs(_beginTouchPos.x - pt.x);
  1314. if (diff < sensitivity)
  1315. return;
  1316. }
  1317. }
  1318. sv = sh = true;
  1319. }
  1320. Vector2 newPos = _containerPos + pt - _beginTouchPos;
  1321. newPos.x = (int)newPos.x;
  1322. newPos.y = (int)newPos.y;
  1323. if (sv)
  1324. {
  1325. if (newPos.y > 0)
  1326. {
  1327. if (!_bouncebackEffect)
  1328. _container.y = 0;
  1329. else if (_header != null && _header.maxHeight != 0)
  1330. _container.y = (int)Mathf.Min(newPos.y * 0.5f, _header.maxHeight);
  1331. else
  1332. _container.y = (int)Mathf.Min(newPos.y * 0.5f, _viewSize.y * PULL_RATIO);
  1333. }
  1334. else if (newPos.y < -_overlapSize.y)
  1335. {
  1336. if (!_bouncebackEffect)
  1337. _container.y = -_overlapSize.y;
  1338. else if (_footer != null && _footer.maxHeight > 0)
  1339. _container.y = (int)Mathf.Max((newPos.y + _overlapSize.y) * 0.5f, -_footer.maxHeight) - _overlapSize.y;
  1340. else
  1341. _container.y = (int)Mathf.Max((newPos.y + _overlapSize.y) * 0.5f, -_viewSize.y * PULL_RATIO) - _overlapSize.y;
  1342. }
  1343. else
  1344. _container.y = newPos.y;
  1345. }
  1346. if (sh)
  1347. {
  1348. if (newPos.x > 0)
  1349. {
  1350. if (!_bouncebackEffect)
  1351. _container.x = 0;
  1352. else if (_header != null && _header.maxWidth != 0)
  1353. _container.x = (int)Mathf.Min(newPos.x * 0.5f, _header.maxWidth);
  1354. else
  1355. _container.x = (int)Mathf.Min(newPos.x * 0.5f, _viewSize.x * PULL_RATIO);
  1356. }
  1357. else if (newPos.x < 0 - _overlapSize.x)
  1358. {
  1359. if (!_bouncebackEffect)
  1360. _container.x = -_overlapSize.x;
  1361. else if (_footer != null && _footer.maxWidth > 0)
  1362. _container.x = (int)Mathf.Max((newPos.x + _overlapSize.x) * 0.5f, -_footer.maxWidth) - _overlapSize.x;
  1363. else
  1364. _container.x = (int)Mathf.Max((newPos.x + _overlapSize.x) * 0.5f, -_viewSize.x * PULL_RATIO) - _overlapSize.x;
  1365. }
  1366. else
  1367. _container.x = newPos.x;
  1368. }
  1369. //更新速度
  1370. float deltaTime = Time.unscaledDeltaTime;
  1371. float elapsed = (Time.unscaledTime - _lastMoveTime) * 60 - 1;
  1372. if (elapsed > 1) //速度衰减
  1373. _velocity = _velocity * Mathf.Pow(0.833f, elapsed);
  1374. Vector2 deltaPosition = pt - _lastTouchPos;
  1375. if (!sh)
  1376. deltaPosition.x = 0;
  1377. if (!sv)
  1378. deltaPosition.y = 0;
  1379. _velocity = Vector2.Lerp(_velocity, deltaPosition / deltaTime, deltaTime * 10);
  1380. /*速度计算使用的是本地位移,但在后续的惯性滚动判断中需要用到屏幕位移,所以这里要记录一个位移的比例。
  1381. *后续的处理要使用这个比例但不使用坐标转换的方法的原因是,在曲面UI等异形UI中,还无法简单地进行屏幕坐标和本地坐标的转换。
  1382. */
  1383. Vector2 deltaGlobalPosition = _lastTouchGlobalPos - evt.position;
  1384. if (deltaPosition.x != 0)
  1385. _velocityScale = Mathf.Abs(deltaGlobalPosition.x / deltaPosition.x);
  1386. else if (deltaPosition.y != 0)
  1387. _velocityScale = Mathf.Abs(deltaGlobalPosition.y / deltaPosition.y);
  1388. _lastTouchPos = pt;
  1389. _lastTouchGlobalPos = evt.position;
  1390. _lastMoveTime = Time.unscaledTime;
  1391. //同步更新pos值
  1392. if (_overlapSize.x > 0)
  1393. _xPos = Mathf.Clamp(-_container.x, 0, _overlapSize.x);
  1394. if (_overlapSize.y > 0)
  1395. _yPos = Mathf.Clamp(-_container.y, 0, _overlapSize.y);
  1396. //循环滚动特别检查
  1397. if (_loop != 0)
  1398. {
  1399. newPos = _container.xy;
  1400. if (LoopCheckingCurrent())
  1401. _containerPos += _container.xy - newPos;
  1402. }
  1403. draggingPane = this;
  1404. _isHoldAreaDone = true;
  1405. _dragged = true;
  1406. UpdateScrollBarPos();
  1407. UpdateScrollBarVisible();
  1408. if (_pageMode)
  1409. UpdatePageController();
  1410. _onScroll.Call();
  1411. }
  1412. private void __touchEnd(EventContext context)
  1413. {
  1414. if (draggingPane == this)
  1415. draggingPane = null;
  1416. _gestureFlag = 0;
  1417. if (!_dragged || !_touchEffect)
  1418. {
  1419. _dragged = false;
  1420. return;
  1421. }
  1422. _dragged = false;
  1423. _tweenStart = _container.xy;
  1424. Vector2 endPos = _tweenStart;
  1425. bool flag = false;
  1426. if (_container.x > 0)
  1427. {
  1428. endPos.x = 0;
  1429. flag = true;
  1430. }
  1431. else if (_container.x < -_overlapSize.x)
  1432. {
  1433. endPos.x = -_overlapSize.x;
  1434. flag = true;
  1435. }
  1436. if (_container.y > 0)
  1437. {
  1438. endPos.y = 0;
  1439. flag = true;
  1440. }
  1441. else if (_container.y < -_overlapSize.y)
  1442. {
  1443. endPos.y = -_overlapSize.y;
  1444. flag = true;
  1445. }
  1446. if (flag)
  1447. {
  1448. _tweenChange = endPos - _tweenStart;
  1449. if (_tweenChange.x < -UIConfig.touchDragSensitivity || _tweenChange.y < -UIConfig.touchDragSensitivity)
  1450. DispatchEvent("onPullDownRelease", null);
  1451. else if (_tweenChange.x > UIConfig.touchDragSensitivity || _tweenChange.y > UIConfig.touchDragSensitivity)
  1452. DispatchEvent("onPullUpRelease", null);
  1453. if (_headerLockedSize > 0 && endPos[_refreshBarAxis] == 0)
  1454. {
  1455. endPos[_refreshBarAxis] = _headerLockedSize;
  1456. _tweenChange = endPos - _tweenStart;
  1457. }
  1458. else if (_footerLockedSize > 0 && endPos[_refreshBarAxis] == -_overlapSize[_refreshBarAxis])
  1459. {
  1460. float max = _overlapSize[_refreshBarAxis];
  1461. if (max == 0)
  1462. max = Mathf.Max(_contentSize[_refreshBarAxis] + _footerLockedSize - _viewSize[_refreshBarAxis], 0);
  1463. else
  1464. max += _footerLockedSize;
  1465. endPos[_refreshBarAxis] = -max;
  1466. _tweenChange = endPos - _tweenStart;
  1467. }
  1468. _tweenDuration.Set(TWEEN_TIME_DEFAULT, TWEEN_TIME_DEFAULT);
  1469. }
  1470. else
  1471. {
  1472. //更新速度
  1473. if (!_inertiaDisabled)
  1474. {
  1475. float elapsed = (Time.unscaledTime - _lastMoveTime) * 60 - 1;
  1476. if (elapsed > 1)
  1477. _velocity = _velocity * Mathf.Pow(0.833f, elapsed);
  1478. //根据速度计算目标位置和需要时间
  1479. endPos = UpdateTargetAndDuration(_tweenStart);
  1480. }
  1481. else
  1482. _tweenDuration.Set(TWEEN_TIME_DEFAULT, TWEEN_TIME_DEFAULT);
  1483. Vector2 oldChange = endPos - _tweenStart;
  1484. //调整目标位置
  1485. LoopCheckingTarget(ref endPos);
  1486. if (_pageMode || _snapToItem)
  1487. AlignPosition(ref endPos, true);
  1488. _tweenChange = endPos - _tweenStart;
  1489. if (_tweenChange.x == 0 && _tweenChange.y == 0)
  1490. {
  1491. UpdateScrollBarVisible();
  1492. return;
  1493. }
  1494. //如果目标位置已调整,随之调整需要时间
  1495. if (_pageMode || _snapToItem)
  1496. {
  1497. FixDuration(0, oldChange.x);
  1498. FixDuration(1, oldChange.y);
  1499. }
  1500. }
  1501. StartTween(2);
  1502. }
  1503. private void __mouseWheel(EventContext context)
  1504. {
  1505. if (!_mouseWheelEnabled)
  1506. return;
  1507. InputEvent evt = context.inputEvent;
  1508. float delta = evt.mouseWheelDelta / Stage.devicePixelRatio;
  1509. if (_snapToItem && Mathf.Abs(delta) < 1)
  1510. delta = Mathf.Sign(delta);
  1511. if (_overlapSize.x > 0 && _overlapSize.y == 0)
  1512. {
  1513. float step = _pageMode ? _pageSize.x : _scrollStep;
  1514. SetPosX(_xPos + step * delta, false);
  1515. }
  1516. else
  1517. {
  1518. float step = _pageMode ? _pageSize.y : _scrollStep;
  1519. SetPosY(_yPos + step * delta, false);
  1520. }
  1521. }
  1522. private void __rollOver()
  1523. {
  1524. _hover = true;
  1525. UpdateScrollBarVisible();
  1526. }
  1527. private void __rollOut()
  1528. {
  1529. _hover = false;
  1530. UpdateScrollBarVisible();
  1531. }
  1532. internal void UpdateClipSoft()
  1533. {
  1534. Vector2 softness = _owner.clipSoftness;
  1535. if (softness.x != 0 || softness.y != 0)
  1536. {
  1537. _maskContainer.clipSoftness = new Vector4(
  1538. (_container.x >= 0 || !_softnessOnTopOrLeftSide) ? 0 : softness.x,
  1539. (_container.y >= 0 || !_softnessOnTopOrLeftSide) ? 0 : softness.y,
  1540. (-_container.x - _overlapSize.x >= 0) ? 0 : softness.x,
  1541. (-_container.y - _overlapSize.y >= 0) ? 0 : softness.y);
  1542. }
  1543. else
  1544. _maskContainer.clipSoftness = null;
  1545. }
  1546. private void UpdateScrollBarPos()
  1547. {
  1548. if (_vtScrollBar != null)
  1549. _vtScrollBar.setScrollPerc(_overlapSize.y == 0 ? 0 : Mathf.Clamp(-_container.y, 0, _overlapSize.y) / _overlapSize.y);
  1550. if (_hzScrollBar != null)
  1551. _hzScrollBar.setScrollPerc(_overlapSize.x == 0 ? 0 : Mathf.Clamp(-_container.x, 0, _overlapSize.x) / _overlapSize.x);
  1552. UpdateClipSoft();
  1553. CheckRefreshBar();
  1554. }
  1555. public void UpdateScrollBarVisible()
  1556. {
  1557. if (_vtScrollBar != null)
  1558. {
  1559. if (_viewSize.y <= _vtScrollBar.minSize || _vScrollNone)
  1560. _vtScrollBar.displayObject.visible = false;
  1561. else
  1562. UpdateScrollBarVisible2(_vtScrollBar);
  1563. }
  1564. if (_hzScrollBar != null)
  1565. {
  1566. if (_viewSize.x <= _hzScrollBar.minSize || _hScrollNone)
  1567. _hzScrollBar.displayObject.visible = false;
  1568. else
  1569. UpdateScrollBarVisible2(_hzScrollBar);
  1570. }
  1571. }
  1572. private void UpdateScrollBarVisible2(GScrollBar bar)
  1573. {
  1574. if (_scrollBarDisplayAuto)
  1575. GTween.Kill(bar, TweenPropType.Alpha, false);
  1576. if (_scrollBarDisplayAuto && !_hover && _tweening == 0 && !_dragged && !bar.gripDragging)
  1577. {
  1578. if (bar.displayObject.visible)
  1579. GTween.To(1, 0, 0.5f).SetDelay(0.5f).OnComplete(_hideScrollBarDelegate).SetTarget(bar, TweenPropType.Alpha);
  1580. }
  1581. else
  1582. {
  1583. bar.alpha = 1;
  1584. bar.displayObject.visible = true;
  1585. }
  1586. }
  1587. private void __barTweenComplete(GTweener tweener)
  1588. {
  1589. GObject bar = (GObject)tweener.target;
  1590. bar.alpha = 1;
  1591. bar.displayObject.visible = false;
  1592. }
  1593. float GetLoopPartSize(float division, int axis)
  1594. {
  1595. return (_contentSize[axis] + (axis == 0 ? ((GList)_owner).columnGap : ((GList)_owner).lineGap)) / division;
  1596. }
  1597. /// <summary>
  1598. /// 对当前的滚动位置进行循环滚动边界检查。当到达边界时,回退一半内容区域(循环滚动内容大小通常是真实内容大小的偶数倍)。
  1599. /// </summary>
  1600. /// <returns></returns>
  1601. bool LoopCheckingCurrent()
  1602. {
  1603. bool changed = false;
  1604. if (_loop == 1 && _overlapSize.x > 0)
  1605. {
  1606. if (_xPos < 0.001f)
  1607. {
  1608. _xPos += GetLoopPartSize(2, 0);
  1609. changed = true;
  1610. }
  1611. else if (_xPos >= _overlapSize.x)
  1612. {
  1613. _xPos -= GetLoopPartSize(2, 0);
  1614. changed = true;
  1615. }
  1616. }
  1617. else if (_loop == 2 && _overlapSize.y > 0)
  1618. {
  1619. if (_yPos < 0.001f)
  1620. {
  1621. _yPos += GetLoopPartSize(2, 1);
  1622. changed = true;
  1623. }
  1624. else if (_yPos >= _overlapSize.y)
  1625. {
  1626. _yPos -= GetLoopPartSize(2, 1);
  1627. changed = true;
  1628. }
  1629. }
  1630. if (changed)
  1631. _container.SetXY((int)-_xPos, (int)-_yPos);
  1632. return changed;
  1633. }
  1634. /// <summary>
  1635. /// 对目标位置进行循环滚动边界检查。当到达边界时,回退一半内容区域(循环滚动内容大小通常是真实内容大小的偶数倍)。
  1636. /// </summary>
  1637. /// <param name="endPos"></param>
  1638. void LoopCheckingTarget(ref Vector2 endPos)
  1639. {
  1640. if (_loop == 1)
  1641. LoopCheckingTarget(ref endPos, 0);
  1642. if (_loop == 2)
  1643. LoopCheckingTarget(ref endPos, 1);
  1644. }
  1645. void LoopCheckingTarget(ref Vector2 endPos, int axis)
  1646. {
  1647. if (endPos[axis] > 0)
  1648. {
  1649. float halfSize = GetLoopPartSize(2, axis);
  1650. float tmp = _tweenStart[axis] - halfSize;
  1651. if (tmp <= 0 && tmp >= -_overlapSize[axis])
  1652. {
  1653. endPos[axis] -= halfSize;
  1654. _tweenStart[axis] = tmp;
  1655. }
  1656. }
  1657. else if (endPos[axis] < -_overlapSize[axis])
  1658. {
  1659. float halfSize = GetLoopPartSize(2, axis);
  1660. float tmp = _tweenStart[axis] + halfSize;
  1661. if (tmp <= 0 && tmp >= -_overlapSize[axis])
  1662. {
  1663. endPos[axis] += halfSize;
  1664. _tweenStart[axis] = tmp;
  1665. }
  1666. }
  1667. }
  1668. void LoopCheckingNewPos(ref float value, int axis)
  1669. {
  1670. if (_overlapSize[axis] == 0)
  1671. return;
  1672. float pos = axis == 0 ? _xPos : _yPos;
  1673. bool changed = false;
  1674. if (value < 0.001f)
  1675. {
  1676. value += GetLoopPartSize(2, axis);
  1677. if (value > pos)
  1678. {
  1679. float v = GetLoopPartSize(6, axis);
  1680. v = Mathf.CeilToInt((value - pos) / v) * v;
  1681. pos = Mathf.Clamp(pos + v, 0, _overlapSize[axis]);
  1682. changed = true;
  1683. }
  1684. }
  1685. else if (value >= _overlapSize[axis])
  1686. {
  1687. value -= GetLoopPartSize(2, axis);
  1688. if (value < pos)
  1689. {
  1690. float v = GetLoopPartSize(6, axis);
  1691. v = Mathf.CeilToInt((pos - value) / v) * v;
  1692. pos = Mathf.Clamp(pos - v, 0, _overlapSize[axis]);
  1693. changed = true;
  1694. }
  1695. }
  1696. if (changed)
  1697. {
  1698. if (axis == 0)
  1699. _container.x = -(int)pos;
  1700. else
  1701. _container.y = -(int)pos;
  1702. }
  1703. }
  1704. /// <summary>
  1705. /// 从oldPos滚动至pos,调整pos位置对齐页面、对齐item等(如果需要)。
  1706. /// </summary>
  1707. /// <param name="pos"></param>
  1708. /// <param name="inertialScrolling"></param>
  1709. void AlignPosition(ref Vector2 pos, bool inertialScrolling)
  1710. {
  1711. if (_pageMode)
  1712. {
  1713. pos.x = AlignByPage(pos.x, 0, inertialScrolling);
  1714. pos.y = AlignByPage(pos.y, 1, inertialScrolling);
  1715. }
  1716. else if (_snapToItem)
  1717. {
  1718. float tmpX = -pos.x;
  1719. float tmpY = -pos.y;
  1720. float xDir = 0;
  1721. float yDir = 0;
  1722. if (inertialScrolling)
  1723. {
  1724. xDir = pos.x - _containerPos.x;
  1725. yDir = pos.y - _containerPos.y;
  1726. }
  1727. _owner.GetSnappingPositionWithDir(ref tmpX, ref tmpY, xDir, yDir);
  1728. if (pos.x < 0 && pos.x > -_overlapSize.x)
  1729. pos.x = -tmpX;
  1730. if (pos.y < 0 && pos.y > -_overlapSize.y)
  1731. pos.y = -tmpY;
  1732. }
  1733. }
  1734. /// <summary>
  1735. /// 从oldPos滚动至pos,调整目标位置到对齐页面。
  1736. /// </summary>
  1737. /// <param name="pos"></param>
  1738. /// <param name="axis"></param>
  1739. /// <param name="inertialScrolling"></param>
  1740. /// <returns></returns>
  1741. float AlignByPage(float pos, int axis, bool inertialScrolling)
  1742. {
  1743. int page;
  1744. if (pos > 0)
  1745. page = 0;
  1746. else if (pos < -_overlapSize[axis])
  1747. page = Mathf.CeilToInt(_contentSize[axis] / _pageSize[axis]) - 1;
  1748. else
  1749. {
  1750. page = Mathf.FloorToInt(-pos / _pageSize[axis]);
  1751. float change = inertialScrolling ? (pos - _containerPos[axis]) : (pos - _container.xy[axis]);
  1752. float testPageSize = Mathf.Min(_pageSize[axis], _contentSize[axis] - (page + 1) * _pageSize[axis]);
  1753. float delta = -pos - page * _pageSize[axis];
  1754. //页面吸附策略
  1755. if (Mathf.Abs(change) > _pageSize[axis])//如果滚动距离超过1页,则需要超过页面的一半,才能到更下一页
  1756. {
  1757. if (delta > testPageSize * 0.5f)
  1758. page++;
  1759. }
  1760. else //否则只需要页面的1/3,当然,需要考虑到左移和右移的情况
  1761. {
  1762. if (delta > testPageSize * (change < 0 ? UIConfig.defaultScrollPagingThreshold : (1 - UIConfig.defaultScrollPagingThreshold)))
  1763. page++;
  1764. }
  1765. //重新计算终点
  1766. pos = -page * _pageSize[axis];
  1767. if (pos < -_overlapSize[axis]) //最后一页未必有pageSize那么大
  1768. pos = -_overlapSize[axis];
  1769. }
  1770. //惯性滚动模式下,会增加判断尽量不要滚动超过一页
  1771. if (inertialScrolling)
  1772. {
  1773. float oldPos = _tweenStart[axis];
  1774. int oldPage;
  1775. if (oldPos > 0)
  1776. oldPage = 0;
  1777. else if (oldPos < -_overlapSize[axis])
  1778. oldPage = Mathf.CeilToInt(_contentSize[axis] / _pageSize[axis]) - 1;
  1779. else
  1780. oldPage = Mathf.FloorToInt(-oldPos / _pageSize[axis]);
  1781. int startPage = Mathf.FloorToInt(-_containerPos[axis] / _pageSize[axis]);
  1782. if (Mathf.Abs(page - startPage) > 1 && Mathf.Abs(oldPage - startPage) <= 1)
  1783. {
  1784. if (page > startPage)
  1785. page = startPage + 1;
  1786. else
  1787. page = startPage - 1;
  1788. pos = -page * _pageSize[axis];
  1789. }
  1790. }
  1791. return pos;
  1792. }
  1793. /// <summary>
  1794. /// 根据当前速度,计算滚动的目标位置,以及到达时间。
  1795. /// </summary>
  1796. /// <param name="orignPos"></param>
  1797. /// <returns></returns>
  1798. Vector2 UpdateTargetAndDuration(Vector2 orignPos)
  1799. {
  1800. Vector2 ret = Vector2.zero;
  1801. ret.x = UpdateTargetAndDuration(orignPos.x, 0);
  1802. ret.y = UpdateTargetAndDuration(orignPos.y, 1);
  1803. return ret;
  1804. }
  1805. float UpdateTargetAndDuration(float pos, int axis)
  1806. {
  1807. float v = _velocity[axis];
  1808. float duration = 0;
  1809. if (pos > 0)
  1810. pos = 0;
  1811. else if (pos < -_overlapSize[axis])
  1812. pos = -_overlapSize[axis];
  1813. else
  1814. {
  1815. //以屏幕像素为基准
  1816. float v2 = Mathf.Abs(v) * _velocityScale;
  1817. //在移动设备上,需要对不同分辨率做一个适配,我们的速度判断以1136分辨率为基准
  1818. if (Stage.touchScreen)
  1819. v2 *= 1136f / Mathf.Max(Screen.width, Screen.height);
  1820. //这里有一些阈值的处理,因为在低速内,不希望产生较大的滚动(甚至不滚动)
  1821. float ratio = 0;
  1822. if (_pageMode || !Stage.touchScreen)
  1823. {
  1824. if (v2 > 500)
  1825. ratio = Mathf.Pow((v2 - 500) / 500, 2);
  1826. }
  1827. else
  1828. {
  1829. if (v2 > 1000)
  1830. ratio = Mathf.Pow((v2 - 1000) / 1000, 2);
  1831. }
  1832. if (ratio != 0)
  1833. {
  1834. if (ratio > 1)
  1835. ratio = 1;
  1836. v2 *= ratio;
  1837. v *= ratio;
  1838. _velocity[axis] = v;
  1839. //算法:v*(_decelerationRate的n次幂)= 60,即在n帧后速度降为60(假设每秒60帧)。
  1840. duration = Mathf.Log(60 / v2, _decelerationRate) / 60;
  1841. //计算距离要使用本地速度
  1842. //理论公式貌似滚动的距离不够,改为经验公式
  1843. //float change = (int)((v/ 60 - 1) / (1 - _decelerationRate));
  1844. float change = (int)(v * duration * 0.4f);
  1845. pos += change;
  1846. }
  1847. }
  1848. if (duration < TWEEN_TIME_DEFAULT)
  1849. duration = TWEEN_TIME_DEFAULT;
  1850. _tweenDuration[axis] = duration;
  1851. return pos;
  1852. }
  1853. /// <summary>
  1854. /// 根据修改后的tweenChange重新计算减速时间。
  1855. /// </summary>
  1856. void FixDuration(int axis, float oldChange)
  1857. {
  1858. if (_tweenChange[axis] == 0 || Mathf.Abs(_tweenChange[axis]) >= Mathf.Abs(oldChange))
  1859. return;
  1860. float newDuration = Mathf.Abs(_tweenChange[axis] / oldChange) * _tweenDuration[axis];
  1861. if (newDuration < TWEEN_TIME_DEFAULT)
  1862. newDuration = TWEEN_TIME_DEFAULT;
  1863. _tweenDuration[axis] = newDuration;
  1864. }
  1865. void StartTween(int type)
  1866. {
  1867. _tweenTime.Set(0, 0);
  1868. _tweening = type;
  1869. Timers.inst.AddUpdate(_tweenUpdateDelegate);
  1870. UpdateScrollBarVisible();
  1871. }
  1872. void KillTween()
  1873. {
  1874. if (_tweening == 1) //取消类型为1的tween需立刻设置到终点
  1875. {
  1876. _container.xy = _tweenStart + _tweenChange;
  1877. _onScroll.Call();
  1878. }
  1879. _tweening = 0;
  1880. Timers.inst.Remove(_tweenUpdateDelegate);
  1881. UpdateScrollBarVisible();
  1882. _onScrollEnd.Call();
  1883. }
  1884. void CheckRefreshBar()
  1885. {
  1886. if (_header == null && _footer == null)
  1887. return;
  1888. float pos = _container.xy[_refreshBarAxis];
  1889. if (_header != null)
  1890. {
  1891. if (pos > 0)
  1892. {
  1893. if (_header.displayObject.parent == null)
  1894. _maskContainer.AddChildAt(_header.displayObject, 0);
  1895. Vector2 vec;
  1896. vec = _header.size;
  1897. vec[_refreshBarAxis] = pos;
  1898. _header.size = vec;
  1899. }
  1900. else
  1901. {
  1902. if (_header.displayObject.parent != null)
  1903. _maskContainer.RemoveChild(_header.displayObject);
  1904. }
  1905. }
  1906. if (_footer != null)
  1907. {
  1908. float max = _overlapSize[_refreshBarAxis];
  1909. if (pos < -max || max == 0 && _footerLockedSize > 0)
  1910. {
  1911. if (_footer.displayObject.parent == null)
  1912. _maskContainer.AddChildAt(_footer.displayObject, 0);
  1913. Vector2 vec;
  1914. vec = _footer.xy;
  1915. if (max > 0)
  1916. vec[_refreshBarAxis] = pos + _contentSize[_refreshBarAxis];
  1917. else
  1918. vec[_refreshBarAxis] = Mathf.Max(Mathf.Min(pos + _viewSize[_refreshBarAxis], _viewSize[_refreshBarAxis] - _footerLockedSize), _viewSize[_refreshBarAxis] - _contentSize[_refreshBarAxis]);
  1919. _footer.xy = vec;
  1920. vec = _footer.size;
  1921. if (max > 0)
  1922. vec[_refreshBarAxis] = -max - pos;
  1923. else
  1924. vec[_refreshBarAxis] = _viewSize[_refreshBarAxis] - _footer.xy[_refreshBarAxis];
  1925. _footer.size = vec;
  1926. }
  1927. else
  1928. {
  1929. if (_footer.displayObject.parent != null)
  1930. _maskContainer.RemoveChild(_footer.displayObject);
  1931. }
  1932. }
  1933. }
  1934. void TweenUpdate(object param)
  1935. {
  1936. if (_owner.displayObject == null || _owner.displayObject.isDisposed)
  1937. {
  1938. Timers.inst.Remove(_tweenUpdateDelegate);
  1939. return;
  1940. }
  1941. float nx = RunTween(0);
  1942. float ny = RunTween(1);
  1943. _container.SetXY(nx, ny);
  1944. if (_tweening == 2)
  1945. {
  1946. if (_overlapSize.x > 0)
  1947. _xPos = Mathf.Clamp(-nx, 0, _overlapSize.x);
  1948. if (_overlapSize.y > 0)
  1949. _yPos = Mathf.Clamp(-ny, 0, _overlapSize.y);
  1950. if (_pageMode)
  1951. UpdatePageController();
  1952. }
  1953. if (_tweenChange.x == 0 && _tweenChange.y == 0)
  1954. {
  1955. _tweening = 0;
  1956. Timers.inst.Remove(_tweenUpdateDelegate);
  1957. LoopCheckingCurrent();
  1958. UpdateScrollBarPos();
  1959. UpdateScrollBarVisible();
  1960. _onScroll.Call();
  1961. _onScrollEnd.Call();
  1962. }
  1963. else
  1964. {
  1965. UpdateScrollBarPos();
  1966. _onScroll.Call();
  1967. }
  1968. }
  1969. float RunTween(int axis)
  1970. {
  1971. float newValue;
  1972. if (_tweenChange[axis] != 0)
  1973. {
  1974. _tweenTime[axis] += Time.unscaledDeltaTime;
  1975. if (_tweenTime[axis] >= _tweenDuration[axis])
  1976. {
  1977. newValue = _tweenStart[axis] + _tweenChange[axis];
  1978. _tweenChange[axis] = 0;
  1979. }
  1980. else
  1981. {
  1982. float ratio = EaseFunc(_tweenTime[axis], _tweenDuration[axis]);
  1983. newValue = _tweenStart[axis] + (int)(_tweenChange[axis] * ratio);
  1984. }
  1985. float threshold1 = 0;
  1986. float threshold2 = -_overlapSize[axis];
  1987. if (_headerLockedSize > 0 && _refreshBarAxis == axis)
  1988. threshold1 = _headerLockedSize;
  1989. if (_footerLockedSize > 0 && _refreshBarAxis == axis)
  1990. {
  1991. float max = _overlapSize[_refreshBarAxis];
  1992. if (max == 0)
  1993. max = Mathf.Max(_contentSize[_refreshBarAxis] + _footerLockedSize - _viewSize[_refreshBarAxis], 0);
  1994. else
  1995. max += _footerLockedSize;
  1996. threshold2 = -max;
  1997. }
  1998. if (_tweening == 2 && _bouncebackEffect)
  1999. {
  2000. if (newValue > 20 + threshold1 && _tweenChange[axis] > 0
  2001. || newValue > threshold1 && _tweenChange[axis] == 0)//开始回弹
  2002. {
  2003. _tweenTime[axis] = 0;
  2004. _tweenDuration[axis] = TWEEN_TIME_DEFAULT;
  2005. _tweenChange[axis] = -newValue + threshold1;
  2006. _tweenStart[axis] = newValue;
  2007. }
  2008. else if (newValue < threshold2 - 20 && _tweenChange[axis] < 0
  2009. || newValue < threshold2 && _tweenChange[axis] == 0)//开始回弹
  2010. {
  2011. _tweenTime[axis] = 0;
  2012. _tweenDuration[axis] = TWEEN_TIME_DEFAULT;
  2013. _tweenChange[axis] = threshold2 - newValue;
  2014. _tweenStart[axis] = newValue;
  2015. }
  2016. }
  2017. else
  2018. {
  2019. if (newValue > threshold1)
  2020. {
  2021. newValue = threshold1;
  2022. _tweenChange[axis] = 0;
  2023. }
  2024. else if (newValue < threshold2)
  2025. {
  2026. newValue = threshold2;
  2027. _tweenChange[axis] = 0;
  2028. }
  2029. }
  2030. }
  2031. else
  2032. newValue = _container.xy[axis];
  2033. return newValue;
  2034. }
  2035. static float EaseFunc(float t, float d)
  2036. {
  2037. return (t = t / d - 1) * t * t + 1;//cubicOut
  2038. }
  2039. }
  2040. }