LoopGridView.cs 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. using UnityEngine.EventSystems;
  6. namespace SuperScrollView
  7. {
  8. [System.Serializable]
  9. public class GridViewItemPrefabConfData
  10. {
  11. public GameObject mItemPrefab = null;
  12. public int mInitCreateCount = 0;
  13. }
  14. public class LoopGridViewInitParam
  15. {
  16. // all the default values
  17. public float mSmoothDumpRate = 0.3f;
  18. public float mSnapFinishThreshold = 0.01f;
  19. public float mSnapVecThreshold = 145;
  20. public static LoopGridViewInitParam CopyDefaultInitParam()
  21. {
  22. return new LoopGridViewInitParam();
  23. }
  24. }
  25. public class LoopGridViewSettingParam
  26. {
  27. public object mItemSize = null;
  28. public object mPadding = null;
  29. public object mItemPadding = null;
  30. public object mGridFixedType = null;
  31. public object mFixedRowOrColumnCount = null;
  32. }
  33. public class LoopGridView : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
  34. {
  35. class SnapData
  36. {
  37. public SnapStatus mSnapStatus = SnapStatus.NoTargetSet;
  38. public RowColumnPair mSnapTarget;
  39. public Vector2 mSnapNeedMoveDir;
  40. public float mTargetSnapVal = 0;
  41. public float mCurSnapVal = 0;
  42. public bool mIsForceSnapTo = false;
  43. public void Clear()
  44. {
  45. mSnapStatus = SnapStatus.NoTargetSet;
  46. mIsForceSnapTo = false;
  47. }
  48. }
  49. class ItemRangeData
  50. {
  51. public int mMaxRow;
  52. public int mMinRow;
  53. public int mMaxColumn;
  54. public int mMinColumn;
  55. public Vector2 mCheckedPosition;
  56. }
  57. Dictionary<string, GridItemPool> mItemPoolDict = new Dictionary<string, GridItemPool>();
  58. List<GridItemPool> mItemPoolList = new List<GridItemPool>();
  59. [SerializeField]
  60. List<GridViewItemPrefabConfData> mItemPrefabDataList = new List<GridViewItemPrefabConfData>();
  61. [SerializeField]
  62. private GridItemArrangeType mArrangeType = GridItemArrangeType.TopLeftToBottomRight;
  63. public GridItemArrangeType ArrangeType { get { return mArrangeType; } set { mArrangeType = value; } }
  64. [SerializeField]
  65. private bool mNeedReverse = false;
  66. public bool NeedReverse { get { return mNeedReverse; } set { mNeedReverse = value; } }
  67. RectTransform mContainerTrans;
  68. ScrollRect mScrollRect = null;
  69. RectTransform mScrollRectTransform = null;
  70. RectTransform mViewPortRectTransform = null;
  71. int mItemTotalCount = 0;
  72. int mRealItemTotalCount = 0;
  73. [SerializeField]
  74. int mKeepFillShow = -1;
  75. [SerializeField]
  76. int mFixedRowOrColumnCount = 0;
  77. bool mRefreshRawOrColumn = false;
  78. int mRealFixedRowOrColumnCount = 0;
  79. Vector2 mItemAlginOffset = Vector2.zero;
  80. [SerializeField]
  81. RectOffset mPadding = new RectOffset();
  82. [SerializeField]
  83. Vector2 mItemPadding = Vector2.zero;
  84. [SerializeField]
  85. Vector2 mItemSize = Vector2.zero;
  86. [SerializeField]
  87. Vector2 mItemRecycleDistance = new Vector2(50, 50);
  88. Vector2 mItemSizeWithPadding = Vector2.zero;
  89. Vector2 mStartPadding;
  90. Vector2 mEndPadding;
  91. System.Func<LoopGridView, int, int, int, LoopGridViewItem> mOnGetItemByRowColumn;
  92. System.Action<LoopGridView, int, int, int, LoopGridViewItem> mOnRecycleItem;
  93. List<GridItemGroup> mItemGroupObjPool = new List<GridItemGroup>();
  94. //if GridFixedType is GridFixedType.ColumnCountFixed, then the GridItemGroup is one row of the GridView
  95. //if GridFixedType is GridFixedType.RowCountFixed, then the GridItemGroup is one column of the GridView
  96. //so mItemGroupList is current all shown rows or columns
  97. List<GridItemGroup> mItemGroupList = new List<GridItemGroup>();
  98. bool mIsDraging = false;
  99. int mRowCount = 0;
  100. int mColumnCount = 0;
  101. public System.Action<LoopGridView> mOnBeginDragAction = null;
  102. public System.Action<LoopGridView> mOnDragingAction = null;
  103. public System.Action<LoopGridView> mOnEndDragAction = null;
  104. float mSmoothDumpVel = 0;
  105. float mSmoothDumpRate = 0.3f;
  106. float mSnapFinishThreshold = 0.1f;
  107. float mSnapVecThreshold = 145;
  108. [SerializeField]
  109. bool mItemSnapEnable = false;
  110. [SerializeField]
  111. GridFixedType mGridFixedType = GridFixedType.ColumnCountFixed;
  112. public System.Action<LoopGridView, LoopGridViewItem> mOnSnapItemFinished = null;
  113. //in this callback, use CurSnapNearestItemRowColumn to get cur snaped item row column.
  114. public System.Action<LoopGridView> mOnSnapNearestChanged = null;
  115. int mLeftSnapUpdateExtraCount = 1;
  116. [SerializeField]
  117. Vector2 mViewPortSnapPivot = Vector2.zero;
  118. [SerializeField]
  119. Vector2 mItemSnapPivot = Vector2.zero;
  120. SnapData mCurSnapData = new SnapData();
  121. Vector3 mLastSnapCheckPos = Vector3.zero;
  122. bool mListViewInited = false;
  123. int mListUpdateCheckFrameCount = 0;
  124. ItemRangeData mCurFrameItemRangeData = new ItemRangeData();
  125. int mNeedCheckContentPosLeftCount = 1;
  126. ClickEventListener mScrollBarClickEventListener1 = null;
  127. ClickEventListener mScrollBarClickEventListener2 = null;
  128. [SerializeField]
  129. private int mSortStartIdx = -1;
  130. RowColumnPair mCurSnapNearestItemRowColumn;
  131. public List<GridViewItemPrefabConfData> ItemPrefabDataList
  132. {
  133. get
  134. {
  135. return mItemPrefabDataList;
  136. }
  137. }
  138. public int ItemTotalCount
  139. {
  140. get
  141. {
  142. return mItemTotalCount;
  143. }
  144. }
  145. public int RealItemTotalCount
  146. {
  147. get
  148. {
  149. return mRealItemTotalCount;
  150. }
  151. }
  152. public RectTransform ContainerTrans
  153. {
  154. get
  155. {
  156. return mContainerTrans;
  157. }
  158. }
  159. public float ViewPortWidth
  160. {
  161. get { return mViewPortRectTransform.rect.width; }
  162. }
  163. public float ViewPortHeight
  164. {
  165. get { return mViewPortRectTransform.rect.height; }
  166. }
  167. public ScrollRect ScrollRect
  168. {
  169. get
  170. {
  171. return mScrollRect;
  172. }
  173. }
  174. public bool IsDraging
  175. {
  176. get
  177. {
  178. return mIsDraging;
  179. }
  180. }
  181. public bool ItemSnapEnable
  182. {
  183. get { return mItemSnapEnable; }
  184. set { mItemSnapEnable = value; }
  185. }
  186. public Vector2 ItemSnapPivot
  187. {
  188. get { return mItemSnapPivot; }
  189. set { mItemSnapPivot = value; }
  190. }
  191. public Vector2 ViewPortSnapPivot
  192. {
  193. get { return mViewPortSnapPivot; }
  194. set { mViewPortSnapPivot = value; }
  195. }
  196. public Vector2 ItemSize
  197. {
  198. get
  199. {
  200. return mItemSize;
  201. }
  202. set
  203. {
  204. SetItemSize(value);
  205. }
  206. }
  207. public Vector2 ItemPadding
  208. {
  209. get
  210. {
  211. return mItemPadding;
  212. }
  213. set
  214. {
  215. SetItemPadding(value);
  216. }
  217. }
  218. public Vector2 ItemSizeWithPadding
  219. {
  220. get
  221. {
  222. return mItemSizeWithPadding;
  223. }
  224. }
  225. public RectOffset Padding
  226. {
  227. get
  228. {
  229. return mPadding;
  230. }
  231. set
  232. {
  233. SetPadding(value);
  234. }
  235. }
  236. public GridViewItemPrefabConfData GetItemPrefabConfData(string prefabName)
  237. {
  238. foreach (GridViewItemPrefabConfData data in mItemPrefabDataList)
  239. {
  240. if (data.mItemPrefab == null)
  241. {
  242. Debug.LogError("A item prefab is null ");
  243. continue;
  244. }
  245. if (prefabName == data.mItemPrefab.name)
  246. {
  247. return data;
  248. }
  249. }
  250. return null;
  251. }
  252. /*
  253. LoopGridView method is to initiate the LoopGridView component. There are 4 parameters:
  254. itemTotalCount: the total item count in the GridView, this parameter must be set a value >=0 , then the ItemIndex can be from 0 to itemTotalCount -1.
  255. onGetItemByRowColumn: when a item is getting in the ScrollRect viewport, and this Action will be called with the item' index and the row and column index as the parameters, to let you create the item and update its content.
  256. settingParam: You can use this parameter to override the values in the Inspector Setting
  257. */
  258. public void InitGridView(int itemTotalCount,
  259. System.Func<LoopGridView, int, int, int, LoopGridViewItem> onGetItemByRowColumn,
  260. System.Action<LoopGridView, int, int, int, LoopGridViewItem> onRecycleItem,
  261. LoopGridViewSettingParam settingParam = null,
  262. LoopGridViewInitParam initParam = null)
  263. {
  264. if (mListViewInited == true)
  265. {
  266. Debug.LogError("LoopGridView.InitListView method can be called only once.");
  267. return;
  268. }
  269. mListViewInited = true;
  270. if (itemTotalCount < 0)
  271. {
  272. Debug.LogError("itemTotalCount is < 0");
  273. itemTotalCount = 0;
  274. }
  275. if (settingParam != null)
  276. {
  277. UpdateFromSettingParam(settingParam);
  278. }
  279. if (initParam != null)
  280. {
  281. mSmoothDumpRate = initParam.mSmoothDumpRate;
  282. mSnapFinishThreshold = initParam.mSnapFinishThreshold;
  283. mSnapVecThreshold = initParam.mSnapVecThreshold;
  284. }
  285. mScrollRect = gameObject.GetComponent<ScrollRect>();
  286. if (mScrollRect == null)
  287. {
  288. Debug.LogError("ListView Init Failed! ScrollRect component not found!");
  289. return;
  290. }
  291. mCurSnapData.Clear();
  292. mScrollRectTransform = mScrollRect.GetComponent<RectTransform>();
  293. mContainerTrans = mScrollRect.content;
  294. mViewPortRectTransform = mScrollRect.viewport;
  295. if (mViewPortRectTransform == null)
  296. {
  297. mViewPortRectTransform = mScrollRectTransform;
  298. }
  299. if (mScrollRect.horizontalScrollbarVisibility == ScrollRect.ScrollbarVisibility.AutoHideAndExpandViewport && mScrollRect.horizontalScrollbar != null)
  300. {
  301. Debug.LogError("ScrollRect.horizontalScrollbarVisibility cannot be set to AutoHideAndExpandViewport");
  302. }
  303. if (mScrollRect.verticalScrollbarVisibility == ScrollRect.ScrollbarVisibility.AutoHideAndExpandViewport && mScrollRect.verticalScrollbar != null)
  304. {
  305. Debug.LogError("ScrollRect.verticalScrollbarVisibility cannot be set to AutoHideAndExpandViewport");
  306. }
  307. SetScrollbarListener();
  308. AdjustViewPortPivot();
  309. AdjustContainerAnchorAndPivot();
  310. InitItemPool();
  311. mOnGetItemByRowColumn = onGetItemByRowColumn;
  312. mOnRecycleItem = onRecycleItem;
  313. mNeedCheckContentPosLeftCount = 4;
  314. mCurSnapData.Clear();
  315. mItemTotalCount = itemTotalCount;
  316. UpdateAllGridSetting();
  317. }
  318. /*
  319. This method may use to set the item total count of the GridView at runtime.
  320. this parameter must be set a value >=0 , and the ItemIndex can be from 0 to itemCount -1.
  321. If resetPos is set false, then the ScrollRect’s content position will not changed after this method finished.
  322. */
  323. public void SetListItemCount(int itemCount, bool resetPos = true)
  324. {
  325. if (itemCount < 0)
  326. {
  327. return;
  328. }
  329. if (itemCount == mItemTotalCount)
  330. {
  331. return;
  332. }
  333. mCurSnapData.Clear();
  334. mItemTotalCount = itemCount;
  335. UpdateKeepFillShowItem();
  336. UpdateColumnRowCount();
  337. UpdateContentSize();
  338. ForceToCheckContentPos();
  339. if (mRealItemTotalCount == 0)
  340. {
  341. RecycleAllItem();
  342. ClearAllTmpRecycledItem();
  343. return;
  344. }
  345. VaildAndSetContainerPos();
  346. UpdateGridViewContent();
  347. ClearAllTmpRecycledItem();
  348. if (resetPos)
  349. {
  350. MovePanelToItemByRowColumn(0, 0, 0, 0);
  351. return;
  352. }
  353. }
  354. /// <summary>
  355. /// 单纯刷新数据,如果需要刷新显示,需要手动调用其它方法
  356. /// ClearSnapData(); -- 清除当前滚动
  357. /// MovePanelToItemByRowColumn(0, 0, 0, 0); -- 移动到定位目标
  358. /// RecycleAllItem(); -- 回收当前显示
  359. /// UpdateGridViewContent(); -- 刷新当前显示
  360. /// 这样可以避免Item重复刷新
  361. /// </summary>
  362. /// <param name="itemCount"></param>
  363. private void RefreshListItemCount(int itemCount)
  364. {
  365. if (itemCount < 0)
  366. {
  367. return;
  368. }
  369. if (itemCount == mItemTotalCount)
  370. {
  371. return;
  372. }
  373. mItemTotalCount = itemCount;
  374. UpdateKeepFillShowItem();
  375. UpdateColumnRowCount();
  376. UpdateContentSize();
  377. ForceToCheckContentPos();
  378. if (mRealItemTotalCount == 0)
  379. {
  380. RecycleAllItem();
  381. ClearAllTmpRecycledItem();
  382. return;
  383. }
  384. }
  385. public void RefreshListByIndex(int itemCount, int itemIndex = -1, float offsetX = 0, float offsetY = 0)
  386. {
  387. RefreshListItemCount(itemCount);
  388. mCurSnapData.Clear();
  389. if (mRealItemTotalCount == 0) return;
  390. if (itemIndex >= 0)
  391. {
  392. MovePanelToItemByIndex(itemIndex, offsetX, offsetY);
  393. }
  394. else
  395. {
  396. VaildAndSetContainerPos();
  397. }
  398. RecycleAllItem();
  399. UpdateGridViewContent();
  400. ClearAllTmpRecycledItem();
  401. }
  402. public void RefreshListByRowColumn(int itemCount, int row = -1, int column = -1, float offsetX = 0, float offsetY = 0)
  403. {
  404. RefreshListItemCount(itemCount);
  405. mCurSnapData.Clear();
  406. if (mRealItemTotalCount == 0) return;
  407. if (row >= 0 && column >= 0)
  408. {
  409. MovePanelToItemByRowColumn(row, column, offsetX, offsetY);
  410. }
  411. else
  412. {
  413. VaildAndSetContainerPos();
  414. }
  415. RecycleAllItem();
  416. UpdateGridViewContent();
  417. ClearAllTmpRecycledItem();
  418. }
  419. //fetch or create a new item form the item pool.
  420. public LoopGridViewItem NewListViewItem(string itemPrefabName)
  421. {
  422. GridItemPool pool = null;
  423. if (mItemPoolDict.TryGetValue(itemPrefabName, out pool) == false)
  424. {
  425. return null;
  426. }
  427. LoopGridViewItem item = pool.GetItem();
  428. RectTransform rf = item.GetComponent<RectTransform>();
  429. rf.SetParent(mContainerTrans);
  430. rf.localScale = Vector3.one;
  431. rf.anchoredPosition3D = Vector3.zero;
  432. rf.localEulerAngles = Vector3.zero;
  433. item.ParentGridView = this;
  434. return item;
  435. }
  436. /*
  437. To update a item by itemIndex.if the itemIndex-th item is not visible, then this method will do nothing.
  438. Otherwise this method will call RefreshItemByRowColumn to do real work.
  439. */
  440. public void RefreshItemByItemIndex(int itemIndex)
  441. {
  442. if (itemIndex < 0 || itemIndex >= mRealItemTotalCount)
  443. {
  444. return;
  445. }
  446. int count = mItemGroupList.Count;
  447. if (count == 0)
  448. {
  449. return;
  450. }
  451. RowColumnPair val = GetRowColumnByItemIndex(itemIndex);
  452. RefreshItemByRowColumn(val.mRow, val.mColumn);
  453. }
  454. /*
  455. To update a item by (row,column).if the item is not visible, then this method will do nothing.
  456. Otherwise this method will call mOnGetItemByRowColumn(row,column) to get a new updated item.
  457. */
  458. public void RefreshItemByRowColumn(int row, int column)
  459. {
  460. int count = mItemGroupList.Count;
  461. if (count == 0)
  462. {
  463. return;
  464. }
  465. if (mGridFixedType == GridFixedType.ColumnCountFixed)
  466. {
  467. GridItemGroup group = GetShownGroup(row);
  468. if (group == null)
  469. {
  470. return;
  471. }
  472. LoopGridViewItem curItem = group.GetItemByColumn(column);
  473. if (curItem == null)
  474. {
  475. return;
  476. }
  477. LoopGridViewItem newItem = GetNewItemByRowColumn(row, column);
  478. if (newItem == null)
  479. {
  480. return;
  481. }
  482. Vector3 pos = curItem.CachedRectTransform.anchoredPosition3D;
  483. group.ReplaceItem(curItem, newItem);
  484. if (mSortStartIdx >= 0)
  485. {
  486. newItem.CachedRectTransform.SetSiblingIndex(curItem.CachedRectTransform.GetSiblingIndex());
  487. }
  488. RecycleItemTmp(curItem);
  489. newItem.CachedRectTransform.anchoredPosition3D = pos;
  490. ClearAllTmpRecycledItem();
  491. }
  492. else
  493. {
  494. GridItemGroup group = GetShownGroup(column);
  495. if (group == null)
  496. {
  497. return;
  498. }
  499. LoopGridViewItem curItem = group.GetItemByRow(row);
  500. if (curItem == null)
  501. {
  502. return;
  503. }
  504. LoopGridViewItem newItem = GetNewItemByRowColumn(row, column);
  505. if (newItem == null)
  506. {
  507. return;
  508. }
  509. Vector3 pos = curItem.CachedRectTransform.anchoredPosition3D;
  510. group.ReplaceItem(curItem, newItem);
  511. if (mSortStartIdx >= 0)
  512. {
  513. newItem.CachedRectTransform.SetSiblingIndex(curItem.CachedRectTransform.GetSiblingIndex());
  514. }
  515. RecycleItemTmp(curItem);
  516. newItem.CachedRectTransform.anchoredPosition3D = pos;
  517. ClearAllTmpRecycledItem();
  518. }
  519. }
  520. //Clear current snap target and then the GridView will auto snap to the CurSnapNearestItem.
  521. public void ClearSnapData()
  522. {
  523. mCurSnapData.Clear();
  524. }
  525. //set cur snap target
  526. public void SetSnapTargetItemRowColumn(int row, int column)
  527. {
  528. if (row < 0)
  529. {
  530. row = 0;
  531. }
  532. if (column < 0)
  533. {
  534. column = 0;
  535. }
  536. mCurSnapData.mSnapTarget.mRow = row;
  537. mCurSnapData.mSnapTarget.mColumn = column;
  538. mCurSnapData.mSnapStatus = SnapStatus.TargetHasSet;
  539. mCurSnapData.mIsForceSnapTo = true;
  540. }
  541. //Get the nearest item row and column with the viewport snap point.
  542. public RowColumnPair CurSnapNearestItemRowColumn
  543. {
  544. get { return mCurSnapNearestItemRowColumn; }
  545. }
  546. //force to update the mCurSnapNearestItemRowColumn value
  547. public void ForceSnapUpdateCheck()
  548. {
  549. if (mLeftSnapUpdateExtraCount <= 0)
  550. {
  551. mLeftSnapUpdateExtraCount = 1;
  552. }
  553. }
  554. //force to refresh the mCurFrameItemRangeData that what items should be shown in viewport.
  555. public void ForceToCheckContentPos()
  556. {
  557. if (mNeedCheckContentPosLeftCount <= 0)
  558. {
  559. mNeedCheckContentPosLeftCount = 1;
  560. }
  561. }
  562. /*
  563. This method will move the panel's position to ( the position of itemIndex'th item + offset ).
  564. */
  565. public void MovePanelToItemByIndex(int itemIndex, float offsetX = 0, float offsetY = 0)
  566. {
  567. if (mRealItemTotalCount == 0)
  568. {
  569. return;
  570. }
  571. if (itemIndex >= mRealItemTotalCount)
  572. {
  573. itemIndex = mRealItemTotalCount - 1;
  574. }
  575. if (itemIndex < 0)
  576. {
  577. itemIndex = 0;
  578. }
  579. RowColumnPair val = GetRowColumnByItemIndex(itemIndex);
  580. MovePanelToItemByRowColumn(val.mRow, val.mColumn, offsetX, offsetY);
  581. }
  582. /*
  583. This method will move the panel's position to ( the position of (row,column) item + offset ).
  584. */
  585. public void MovePanelToItemByRowColumn(int row, int column, float offsetX = 0, float offsetY = 0)
  586. {
  587. mScrollRect.StopMovement();
  588. mCurSnapData.Clear();
  589. if (mRealItemTotalCount == 0)
  590. {
  591. return;
  592. }
  593. Vector2 itemPos = GetItemPos(row, column);
  594. Vector3 pos = mContainerTrans.anchoredPosition3D;
  595. if (mScrollRect.horizontal)
  596. {
  597. float maxCanMoveX = Mathf.Max(ContainerTrans.rect.width - ViewPortWidth, 0);
  598. if (maxCanMoveX > 0)
  599. {
  600. float x = -itemPos.x + offsetX + mStartPadding.x + mItemAlginOffset.x;
  601. x = Mathf.Min(Mathf.Abs(x), maxCanMoveX) * Mathf.Sign(x);
  602. pos.x = x;
  603. }
  604. }
  605. if (mScrollRect.vertical)
  606. {
  607. float maxCanMoveY = Mathf.Max(ContainerTrans.rect.height - ViewPortHeight, 0);
  608. if (maxCanMoveY > 0)
  609. {
  610. float y = -itemPos.y + offsetY - mStartPadding.y - mItemAlginOffset.y;
  611. y = Mathf.Min(Mathf.Abs(y), maxCanMoveY) * Mathf.Sign(y);
  612. pos.y = y;
  613. }
  614. }
  615. if (pos != mContainerTrans.anchoredPosition3D)
  616. {
  617. mContainerTrans.anchoredPosition3D = pos;
  618. }
  619. VaildAndSetContainerPos();
  620. ForceToCheckContentPos();
  621. }
  622. //update all visible items.
  623. public void RefreshAllShownItem()
  624. {
  625. int count = mItemGroupList.Count;
  626. if (count == 0)
  627. {
  628. return;
  629. }
  630. ForceToCheckContentPos();
  631. RecycleAllItem();
  632. UpdateGridViewContent();
  633. }
  634. public virtual void OnBeginDrag(PointerEventData eventData)
  635. {
  636. if (eventData.button != PointerEventData.InputButton.Left)
  637. {
  638. return;
  639. }
  640. mCurSnapData.Clear();
  641. mIsDraging = true;
  642. if (mOnBeginDragAction != null)
  643. {
  644. mOnBeginDragAction(this);
  645. }
  646. }
  647. public virtual void OnEndDrag(PointerEventData eventData)
  648. {
  649. if (eventData.button != PointerEventData.InputButton.Left)
  650. {
  651. return;
  652. }
  653. mIsDraging = false;
  654. ForceSnapUpdateCheck();
  655. if (mOnEndDragAction != null)
  656. {
  657. mOnEndDragAction(this);
  658. }
  659. }
  660. public virtual void OnDrag(PointerEventData eventData)
  661. {
  662. if (eventData.button != PointerEventData.InputButton.Left)
  663. {
  664. return;
  665. }
  666. if (mOnDragingAction != null)
  667. {
  668. mOnDragingAction(this);
  669. }
  670. }
  671. public int GetItemIndexByRowColumn(int row, int column)
  672. {
  673. if (mGridFixedType == GridFixedType.ColumnCountFixed)
  674. {
  675. return row * mRealFixedRowOrColumnCount + column;
  676. }
  677. else
  678. {
  679. return column * mRealFixedRowOrColumnCount + row;
  680. }
  681. }
  682. public RowColumnPair GetRowColumnByItemIndex(int itemIndex)
  683. {
  684. if (itemIndex < 0)
  685. {
  686. itemIndex = 0;
  687. }
  688. if (mGridFixedType == GridFixedType.ColumnCountFixed)
  689. {
  690. int row = itemIndex / mRealFixedRowOrColumnCount;
  691. int column = itemIndex % mRealFixedRowOrColumnCount;
  692. return new RowColumnPair(row, column);
  693. }
  694. else
  695. {
  696. int column = itemIndex / mRealFixedRowOrColumnCount;
  697. int row = itemIndex % mRealFixedRowOrColumnCount;
  698. return new RowColumnPair(row, column);
  699. }
  700. }
  701. public Vector2 GetItemAbsPos(int itemIndex)
  702. {
  703. RowColumnPair pair = GetRowColumnByItemIndex(itemIndex);
  704. float x = mStartPadding.x + mItemAlginOffset.x + pair.mColumn * mItemSizeWithPadding.x;
  705. float y = mStartPadding.y + mItemAlginOffset.y + pair.mRow * mItemSizeWithPadding.y;
  706. return new Vector2(x, y);
  707. }
  708. public Vector2 GetItemAbsPos(int row, int column)
  709. {
  710. float x = mStartPadding.x + mItemAlginOffset.x + column * mItemSizeWithPadding.x;
  711. float y = mStartPadding.y + mItemAlginOffset.y + row * mItemSizeWithPadding.y;
  712. return new Vector2(x, y);
  713. }
  714. public Vector2 GetItemPos(int row, int column)
  715. {
  716. Vector2 absPos = GetItemAbsPos(row, column);
  717. float x = absPos.x;
  718. float y = absPos.y;
  719. if (ArrangeType == GridItemArrangeType.TopLeftToBottomRight)
  720. {
  721. return new Vector2(x, !mNeedReverse ? -y : y);
  722. }
  723. else if (ArrangeType == GridItemArrangeType.BottomLeftToTopRight)
  724. {
  725. return new Vector2(x, !mNeedReverse ? y : -y);
  726. }
  727. else if (ArrangeType == GridItemArrangeType.TopRightToBottomLeft)
  728. {
  729. return new Vector2(-x, !mNeedReverse ? -y : y);
  730. }
  731. else if (ArrangeType == GridItemArrangeType.BottomRightToTopLeft)
  732. {
  733. return new Vector2(-x, !mNeedReverse ? y : -y);
  734. }
  735. return Vector2.zero;
  736. }
  737. //get the shown item of itemIndex, if this item is not shown,then return null.
  738. public LoopGridViewItem GetShownItemByItemIndex(int itemIndex)
  739. {
  740. if (itemIndex < 0 || itemIndex >= mRealItemTotalCount)
  741. {
  742. return null;
  743. }
  744. if (mItemGroupList.Count == 0)
  745. {
  746. return null;
  747. }
  748. RowColumnPair val = GetRowColumnByItemIndex(itemIndex);
  749. return GetShownItemByRowColumn(val.mRow, val.mColumn);
  750. }
  751. //get the shown item of (row, column), if this item is not shown,then return null.
  752. public LoopGridViewItem GetShownItemByRowColumn(int row, int column)
  753. {
  754. if (mItemGroupList.Count == 0)
  755. {
  756. return null;
  757. }
  758. if (mGridFixedType == GridFixedType.ColumnCountFixed)
  759. {
  760. GridItemGroup group = GetShownGroup(row);
  761. if (group == null)
  762. {
  763. return null;
  764. }
  765. return group.GetItemByColumn(column);
  766. }
  767. else
  768. {
  769. GridItemGroup group = GetShownGroup(column);
  770. if (group == null)
  771. {
  772. return null;
  773. }
  774. return group.GetItemByRow(row);
  775. }
  776. }
  777. public void UpdateAllGridSetting()
  778. {
  779. UpdateStartEndPadding();
  780. UpdateItemSize();
  781. CalcRealFixedRowOrColumnCount();
  782. UpdateKeepFillShowItem();
  783. UpdateColumnRowCount();
  784. UpdateContentSize();
  785. ForceSnapUpdateCheck();
  786. ForceToCheckContentPos();
  787. }
  788. //set mGridFixedType and mFixedRowOrColumnCount at runtime
  789. public void SetGridFixedGroupCount(GridFixedType fixedType, int count)
  790. {
  791. if (mGridFixedType == fixedType && mFixedRowOrColumnCount == count)
  792. {
  793. return;
  794. }
  795. mGridFixedType = fixedType;
  796. mFixedRowOrColumnCount = count;
  797. CalcRealFixedRowOrColumnCount();
  798. UpdateKeepFillShowItem();
  799. UpdateColumnRowCount();
  800. UpdateContentSize();
  801. if (mItemGroupList.Count == 0)
  802. {
  803. return;
  804. }
  805. RecycleAllItem();
  806. ForceSnapUpdateCheck();
  807. ForceToCheckContentPos();
  808. }
  809. public void UpdateRealFixedRowOrColumnCount()
  810. {
  811. if (!CalcRealFixedRowOrColumnCount())
  812. {
  813. return;
  814. }
  815. if (mItemSnapEnable)
  816. {
  817. if (mCurSnapData.mSnapStatus == SnapStatus.NoTargetSet || mCurSnapData.mSnapStatus == SnapStatus.SnapMoveFinish)
  818. {
  819. SetSnapTargetItemRowColumn(mCurSnapNearestItemRowColumn.mRow, mCurSnapNearestItemRowColumn.mColumn);
  820. }
  821. }
  822. UpdateKeepFillShowItem();
  823. UpdateColumnRowCount();
  824. UpdateContentSize();
  825. if (mItemGroupList.Count == 0)
  826. {
  827. return;
  828. }
  829. RecycleAllItem();
  830. ForceSnapUpdateCheck();
  831. ForceToCheckContentPos();
  832. }
  833. private void UpdateKeepFillShowItem()
  834. {
  835. mRealItemTotalCount = mItemTotalCount;
  836. if (mKeepFillShow < 0) return;
  837. int rowOrColumn = 0;
  838. int rowOrColumnNeed = Mathf.CeilToInt((float)mItemTotalCount / mRealFixedRowOrColumnCount) + mKeepFillShow;
  839. if (mGridFixedType == GridFixedType.ColumnCountFixed)
  840. {
  841. float height = ViewPortHeight - mStartPadding.y - mEndPadding.y + mItemPadding.y;
  842. rowOrColumn = Mathf.CeilToInt(height / mItemSizeWithPadding.y);
  843. }
  844. else
  845. {
  846. float width = ViewPortWidth - mStartPadding.x - mEndPadding.x + mItemPadding.x;
  847. rowOrColumn = Mathf.CeilToInt(width / mItemSizeWithPadding.x);
  848. }
  849. if (rowOrColumnNeed < rowOrColumn)
  850. {
  851. mRealItemTotalCount = mRealFixedRowOrColumnCount * rowOrColumn;
  852. }
  853. else
  854. {
  855. mRealItemTotalCount = mRealFixedRowOrColumnCount * rowOrColumnNeed;
  856. }
  857. }
  858. private bool CalcRealFixedRowOrColumnCount()
  859. {
  860. int lastRealFixedRowOrColumnCount = mRealFixedRowOrColumnCount;
  861. if (mFixedRowOrColumnCount <= 0)
  862. {
  863. if (mGridFixedType == GridFixedType.ColumnCountFixed)
  864. {
  865. float width = ViewPortWidth - mStartPadding.x - mEndPadding.x + mItemPadding.x;
  866. mRealFixedRowOrColumnCount = Mathf.FloorToInt(width / mItemSizeWithPadding.x);
  867. if (mRealFixedRowOrColumnCount <= 0)
  868. {
  869. mRealFixedRowOrColumnCount = 1;
  870. }
  871. float offset = (width - mRealFixedRowOrColumnCount * mItemSizeWithPadding.x) * 0.5f;
  872. mItemAlginOffset.Set(offset > 0 ? offset : 0, 0);
  873. }
  874. else
  875. {
  876. float height = ViewPortHeight - mStartPadding.y - mEndPadding.y + mItemPadding.y;
  877. mRealFixedRowOrColumnCount = Mathf.FloorToInt(height / mItemSizeWithPadding.y);
  878. if (mRealFixedRowOrColumnCount <= 0)
  879. {
  880. mRealFixedRowOrColumnCount = 1;
  881. }
  882. float offset = (height - mRealFixedRowOrColumnCount * mItemSizeWithPadding.y) * 0.5f;
  883. mItemAlginOffset.Set(0, offset > 0 ? offset : 0);
  884. }
  885. }
  886. else
  887. {
  888. mRealFixedRowOrColumnCount = mFixedRowOrColumnCount;
  889. mItemAlginOffset.Set(0, 0);
  890. }
  891. return lastRealFixedRowOrColumnCount != mFixedRowOrColumnCount;
  892. }
  893. //change item size at runtime
  894. public void SetItemSize(Vector2 newSize)
  895. {
  896. if (newSize == mItemSize)
  897. {
  898. return;
  899. }
  900. mItemSize = newSize;
  901. UpdateItemSize();
  902. UpdateContentSize();
  903. if (mItemGroupList.Count == 0)
  904. {
  905. return;
  906. }
  907. RecycleAllItem();
  908. ForceSnapUpdateCheck();
  909. ForceToCheckContentPos();
  910. }
  911. //change item padding at runtime
  912. public void SetItemPadding(Vector2 newPadding)
  913. {
  914. if (newPadding == mItemPadding)
  915. {
  916. return;
  917. }
  918. mItemPadding = newPadding;
  919. UpdateItemSize();
  920. UpdateContentSize();
  921. if (mItemGroupList.Count == 0)
  922. {
  923. return;
  924. }
  925. RecycleAllItem();
  926. ForceSnapUpdateCheck();
  927. ForceToCheckContentPos();
  928. }
  929. //change padding at runtime
  930. public void SetPadding(RectOffset newPadding)
  931. {
  932. if (newPadding == mPadding)
  933. {
  934. return;
  935. }
  936. mPadding = newPadding;
  937. UpdateStartEndPadding();
  938. UpdateContentSize();
  939. if (mItemGroupList.Count == 0)
  940. {
  941. return;
  942. }
  943. RecycleAllItem();
  944. ForceSnapUpdateCheck();
  945. ForceToCheckContentPos();
  946. }
  947. public void UpdateContentSize()
  948. {
  949. float width = mStartPadding.x + mItemAlginOffset.x + mColumnCount * mItemSizeWithPadding.x - mItemPadding.x + mEndPadding.x;
  950. float height = mStartPadding.y + mItemAlginOffset.x + mRowCount * mItemSizeWithPadding.y - mItemPadding.y + mEndPadding.y;
  951. if (mContainerTrans.rect.height != height)
  952. {
  953. mContainerTrans.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
  954. }
  955. if (mContainerTrans.rect.width != width)
  956. {
  957. mContainerTrans.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, width);
  958. }
  959. }
  960. public void VaildAndSetContainerPos()
  961. {
  962. Vector3 pos = mContainerTrans.anchoredPosition3D;
  963. mContainerTrans.anchoredPosition3D = GetContainerVaildPos(pos.x, pos.y);
  964. }
  965. public void ClearAllTmpRecycledItem()
  966. {
  967. int count = mItemPoolList.Count;
  968. for (int i = 0; i < count; ++i)
  969. {
  970. mItemPoolList[i].ClearTmpRecycledItem();
  971. }
  972. }
  973. public void RecycleAllItem()
  974. {
  975. foreach (GridItemGroup group in mItemGroupList)
  976. {
  977. RecycleItemGroupTmp(group);
  978. }
  979. mItemGroupList.Clear();
  980. }
  981. public void UpdateGridViewContent()
  982. {
  983. mListUpdateCheckFrameCount++;
  984. if (mRealItemTotalCount == 0)
  985. {
  986. if (mItemGroupList.Count > 0)
  987. {
  988. RecycleAllItem();
  989. }
  990. return;
  991. }
  992. UpdateCurFrameItemRangeData();
  993. if (mGridFixedType == GridFixedType.ColumnCountFixed)
  994. {
  995. int groupCount = mItemGroupList.Count;
  996. int minRow = mCurFrameItemRangeData.mMinRow;
  997. int maxRow = mCurFrameItemRangeData.mMaxRow;
  998. for (int i = groupCount - 1; i >= 0; --i)
  999. {
  1000. GridItemGroup group = mItemGroupList[i];
  1001. if (group.GroupIndex < minRow || group.GroupIndex > maxRow)
  1002. {
  1003. RecycleItemGroupTmp(group);
  1004. mItemGroupList.RemoveAt(i);
  1005. }
  1006. }
  1007. if (mItemGroupList.Count == 0)
  1008. {
  1009. GridItemGroup group = CreateItemGroup(minRow);
  1010. mItemGroupList.Add(group);
  1011. }
  1012. while (mItemGroupList[0].GroupIndex > minRow)
  1013. {
  1014. GridItemGroup group = CreateItemGroup(mItemGroupList[0].GroupIndex - 1);
  1015. mItemGroupList.Insert(0, group);
  1016. }
  1017. while (mItemGroupList[mItemGroupList.Count - 1].GroupIndex < maxRow)
  1018. {
  1019. GridItemGroup group = CreateItemGroup(mItemGroupList[mItemGroupList.Count - 1].GroupIndex + 1);
  1020. mItemGroupList.Add(group);
  1021. }
  1022. int count = mItemGroupList.Count;
  1023. for (int i = 0; i < count; ++i)
  1024. {
  1025. UpdateRowItemGroupForRecycleAndNew(mItemGroupList[i], i);
  1026. }
  1027. }
  1028. else
  1029. {
  1030. int groupCount = mItemGroupList.Count;
  1031. int minColumn = mCurFrameItemRangeData.mMinColumn;
  1032. int maxColumn = mCurFrameItemRangeData.mMaxColumn;
  1033. for (int i = groupCount - 1; i >= 0; --i)
  1034. {
  1035. GridItemGroup group = mItemGroupList[i];
  1036. if (group.GroupIndex < minColumn || group.GroupIndex > maxColumn)
  1037. {
  1038. RecycleItemGroupTmp(group);
  1039. mItemGroupList.RemoveAt(i);
  1040. }
  1041. }
  1042. if (mItemGroupList.Count == 0)
  1043. {
  1044. GridItemGroup group = CreateItemGroup(minColumn);
  1045. mItemGroupList.Add(group);
  1046. }
  1047. while (mItemGroupList[0].GroupIndex > minColumn)
  1048. {
  1049. GridItemGroup group = CreateItemGroup(mItemGroupList[0].GroupIndex - 1);
  1050. mItemGroupList.Insert(0, group);
  1051. }
  1052. while (mItemGroupList[mItemGroupList.Count - 1].GroupIndex < maxColumn)
  1053. {
  1054. GridItemGroup group = CreateItemGroup(mItemGroupList[mItemGroupList.Count - 1].GroupIndex + 1);
  1055. mItemGroupList.Add(group);
  1056. }
  1057. int count = mItemGroupList.Count;
  1058. for (int i = 0; i < count; ++i)
  1059. {
  1060. UpdateColumnItemGroupForRecycleAndNew(mItemGroupList[i], i);
  1061. }
  1062. }
  1063. }
  1064. public void UpdateStartEndPadding()
  1065. {
  1066. if (ArrangeType == GridItemArrangeType.TopLeftToBottomRight)
  1067. {
  1068. mStartPadding.x = mPadding.left;
  1069. mStartPadding.y = mPadding.top;
  1070. mEndPadding.x = mPadding.right;
  1071. mEndPadding.y = mPadding.bottom;
  1072. if (mNeedReverse)
  1073. {
  1074. mStartPadding.y = mPadding.bottom;
  1075. mEndPadding.y = mPadding.top;
  1076. }
  1077. }
  1078. else if (ArrangeType == GridItemArrangeType.BottomLeftToTopRight)
  1079. {
  1080. mStartPadding.x = mPadding.left;
  1081. mStartPadding.y = mPadding.bottom;
  1082. mEndPadding.x = mPadding.right;
  1083. mEndPadding.y = mPadding.top;
  1084. if (mNeedReverse)
  1085. {
  1086. mStartPadding.y = mPadding.top;
  1087. mEndPadding.y = mPadding.bottom;
  1088. }
  1089. }
  1090. else if (ArrangeType == GridItemArrangeType.TopRightToBottomLeft)
  1091. {
  1092. mStartPadding.x = mPadding.right;
  1093. mStartPadding.y = mPadding.top;
  1094. mEndPadding.x = mPadding.left;
  1095. mEndPadding.y = mPadding.bottom;
  1096. if (mNeedReverse)
  1097. {
  1098. mStartPadding.y = mPadding.bottom;
  1099. mEndPadding.y = mPadding.top;
  1100. }
  1101. }
  1102. else if (ArrangeType == GridItemArrangeType.BottomRightToTopLeft)
  1103. {
  1104. mStartPadding.x = mPadding.right;
  1105. mStartPadding.y = mPadding.bottom;
  1106. mEndPadding.x = mPadding.left;
  1107. mEndPadding.y = mPadding.top;
  1108. if (mNeedReverse)
  1109. {
  1110. mStartPadding.y = mPadding.top;
  1111. mEndPadding.y = mPadding.bottom;
  1112. }
  1113. }
  1114. }
  1115. public void UpdateItemSize()
  1116. {
  1117. if (mItemSize.x > 0f && mItemSize.y > 0f)
  1118. {
  1119. mItemSizeWithPadding = mItemSize + mItemPadding;
  1120. return;
  1121. }
  1122. do
  1123. {
  1124. if (mItemPrefabDataList.Count == 0)
  1125. {
  1126. break;
  1127. }
  1128. GameObject obj = mItemPrefabDataList[0].mItemPrefab;
  1129. if (obj == null)
  1130. {
  1131. break;
  1132. }
  1133. RectTransform rtf = obj.GetComponent<RectTransform>();
  1134. if (rtf == null)
  1135. {
  1136. break;
  1137. }
  1138. mItemSize = rtf.rect.size;
  1139. mItemSizeWithPadding = mItemSize + mItemPadding;
  1140. } while (false);
  1141. if (mItemSize.x <= 0 || mItemSize.y <= 0)
  1142. {
  1143. Debug.LogError("Error, ItemSize is invaild.");
  1144. }
  1145. }
  1146. public void UpdateColumnRowCount()
  1147. {
  1148. if (mGridFixedType == GridFixedType.ColumnCountFixed)
  1149. {
  1150. mColumnCount = mRealFixedRowOrColumnCount;
  1151. mRowCount = mRealItemTotalCount / mColumnCount;
  1152. if (mRealItemTotalCount % mColumnCount > 0)
  1153. {
  1154. mRowCount++;
  1155. }
  1156. if (mRealItemTotalCount <= mColumnCount)
  1157. {
  1158. mColumnCount = mRealItemTotalCount;
  1159. }
  1160. }
  1161. else
  1162. {
  1163. mRowCount = mRealFixedRowOrColumnCount;
  1164. mColumnCount = mRealItemTotalCount / mRowCount;
  1165. if (mRealItemTotalCount % mRowCount > 0)
  1166. {
  1167. mColumnCount++;
  1168. }
  1169. if (mRealItemTotalCount <= mRowCount)
  1170. {
  1171. mRowCount = mRealItemTotalCount;
  1172. }
  1173. }
  1174. }
  1175. /// ///////////////////////////////////////////////////////////////////////////////////////////////////////
  1176. /// </summary>
  1177. bool IsContainerTransCanMove()
  1178. {
  1179. if (mRealItemTotalCount == 0)
  1180. {
  1181. return false;
  1182. }
  1183. if (mScrollRect.horizontal && ContainerTrans.rect.width > ViewPortWidth)
  1184. {
  1185. return true;
  1186. }
  1187. if (mScrollRect.vertical && ContainerTrans.rect.height > ViewPortHeight)
  1188. {
  1189. return true;
  1190. }
  1191. return false;
  1192. }
  1193. void RecycleItemGroupTmp(GridItemGroup group)
  1194. {
  1195. if (group == null)
  1196. {
  1197. return;
  1198. }
  1199. while (group.First != null)
  1200. {
  1201. LoopGridViewItem item = group.RemoveFirst();
  1202. RecycleItemTmp(item);
  1203. }
  1204. group.Clear();
  1205. RecycleOneItemGroupObj(group);
  1206. }
  1207. void RecycleItemTmp(LoopGridViewItem item)
  1208. {
  1209. if (item == null)
  1210. {
  1211. return;
  1212. }
  1213. if (string.IsNullOrEmpty(item.ItemPrefabName))
  1214. {
  1215. return;
  1216. }
  1217. GridItemPool pool = null;
  1218. if (mItemPoolDict.TryGetValue(item.ItemPrefabName, out pool) == false)
  1219. {
  1220. return;
  1221. }
  1222. if (mOnRecycleItem != null) mOnRecycleItem(this, item.ItemIndex, item.Row, item.Column, item);
  1223. pool.RecycleItem(item);
  1224. if (mSortStartIdx >= 0)
  1225. {
  1226. item.CachedRectTransform.SetAsLastSibling();
  1227. }
  1228. }
  1229. void AdjustViewPortPivot()
  1230. {
  1231. RectTransform rtf = mViewPortRectTransform;
  1232. if (ArrangeType == GridItemArrangeType.TopLeftToBottomRight)
  1233. {
  1234. rtf.pivot = new Vector2(0, 1);
  1235. }
  1236. else if (ArrangeType == GridItemArrangeType.BottomLeftToTopRight)
  1237. {
  1238. rtf.pivot = new Vector2(0, 0);
  1239. }
  1240. else if (ArrangeType == GridItemArrangeType.TopRightToBottomLeft)
  1241. {
  1242. rtf.pivot = new Vector2(1, 1);
  1243. }
  1244. else if (ArrangeType == GridItemArrangeType.BottomRightToTopLeft)
  1245. {
  1246. rtf.pivot = new Vector2(1, 0);
  1247. }
  1248. }
  1249. void AdjustContainerAnchorAndPivot()
  1250. {
  1251. RectTransform rtf = ContainerTrans;
  1252. if (ArrangeType == GridItemArrangeType.TopLeftToBottomRight)
  1253. {
  1254. rtf.anchorMin = new Vector2(0, 1);
  1255. rtf.anchorMax = new Vector2(0, 1);
  1256. rtf.pivot = new Vector2(0, 1);
  1257. }
  1258. else if (ArrangeType == GridItemArrangeType.BottomLeftToTopRight)
  1259. {
  1260. rtf.anchorMin = new Vector2(0, 0);
  1261. rtf.anchorMax = new Vector2(0, 0);
  1262. rtf.pivot = new Vector2(0, 0);
  1263. }
  1264. else if (ArrangeType == GridItemArrangeType.TopRightToBottomLeft)
  1265. {
  1266. rtf.anchorMin = new Vector2(1, 1);
  1267. rtf.anchorMax = new Vector2(1, 1);
  1268. rtf.pivot = new Vector2(1, 1);
  1269. }
  1270. else if (ArrangeType == GridItemArrangeType.BottomRightToTopLeft)
  1271. {
  1272. rtf.anchorMin = new Vector2(1, 0);
  1273. rtf.anchorMax = new Vector2(1, 0);
  1274. rtf.pivot = new Vector2(1, 0);
  1275. }
  1276. }
  1277. void AdjustItemAnchorAndPivot(RectTransform rtf)
  1278. {
  1279. if (ArrangeType == GridItemArrangeType.TopLeftToBottomRight)
  1280. {
  1281. rtf.anchorMin = new Vector2(0, 1);
  1282. rtf.anchorMax = new Vector2(0, 1);
  1283. rtf.pivot = new Vector2(0, 1);
  1284. if (mNeedReverse)
  1285. {
  1286. rtf.anchorMin = new Vector2(0, 0);
  1287. rtf.anchorMax = new Vector2(0, 0);
  1288. rtf.pivot = new Vector2(0, 0);
  1289. }
  1290. }
  1291. else if (ArrangeType == GridItemArrangeType.BottomLeftToTopRight)
  1292. {
  1293. rtf.anchorMin = new Vector2(0, 0);
  1294. rtf.anchorMax = new Vector2(0, 0);
  1295. rtf.pivot = new Vector2(0, 0);
  1296. if (mNeedReverse)
  1297. {
  1298. rtf.anchorMin = new Vector2(0, 1);
  1299. rtf.anchorMax = new Vector2(0, 1);
  1300. rtf.pivot = new Vector2(0, 1);
  1301. }
  1302. }
  1303. else if (ArrangeType == GridItemArrangeType.TopRightToBottomLeft)
  1304. {
  1305. rtf.anchorMin = new Vector2(1, 1);
  1306. rtf.anchorMax = new Vector2(1, 1);
  1307. rtf.pivot = new Vector2(1, 1);
  1308. if (mNeedReverse)
  1309. {
  1310. rtf.anchorMin = new Vector2(1, 0);
  1311. rtf.anchorMax = new Vector2(1, 0);
  1312. rtf.pivot = new Vector2(1, 0);
  1313. }
  1314. }
  1315. else if (ArrangeType == GridItemArrangeType.BottomRightToTopLeft)
  1316. {
  1317. rtf.anchorMin = new Vector2(1, 0);
  1318. rtf.anchorMax = new Vector2(1, 0);
  1319. rtf.pivot = new Vector2(1, 0);
  1320. if (mNeedReverse)
  1321. {
  1322. rtf.anchorMin = new Vector2(1, 1);
  1323. rtf.anchorMax = new Vector2(1, 1);
  1324. rtf.pivot = new Vector2(1, 1);
  1325. }
  1326. }
  1327. }
  1328. void InitItemPool()
  1329. {
  1330. foreach (GridViewItemPrefabConfData data in mItemPrefabDataList)
  1331. {
  1332. if (data.mItemPrefab == null)
  1333. {
  1334. Debug.LogError("A item prefab is null ");
  1335. continue;
  1336. }
  1337. string prefabName = data.mItemPrefab.name;
  1338. if (mItemPoolDict.ContainsKey(prefabName))
  1339. {
  1340. Debug.LogError("A item prefab with name " + prefabName + " has existed!");
  1341. continue;
  1342. }
  1343. RectTransform rtf = data.mItemPrefab.GetComponent<RectTransform>();
  1344. if (rtf == null)
  1345. {
  1346. Debug.LogError("RectTransform component is not found in the prefab " + prefabName);
  1347. continue;
  1348. }
  1349. AdjustItemAnchorAndPivot(rtf);
  1350. LoopGridViewItem tItem = data.mItemPrefab.GetComponent<LoopGridViewItem>();
  1351. if (tItem == null)
  1352. {
  1353. data.mItemPrefab.AddComponent<LoopGridViewItem>();
  1354. }
  1355. GridItemPool pool = new GridItemPool();
  1356. pool.Init(data.mItemPrefab, data.mInitCreateCount, mContainerTrans);
  1357. mItemPoolDict.Add(prefabName, pool);
  1358. mItemPoolList.Add(pool);
  1359. }
  1360. }
  1361. LoopGridViewItem GetNewItemByRowColumn(int row, int column)
  1362. {
  1363. int itemIndex = GetItemIndexByRowColumn(row, column);
  1364. if (itemIndex < 0 || itemIndex >= mRealItemTotalCount)
  1365. {
  1366. return null;
  1367. }
  1368. LoopGridViewItem newItem = mOnGetItemByRowColumn(this, itemIndex, row, column);
  1369. if (newItem == null)
  1370. {
  1371. return null;
  1372. }
  1373. newItem.NextItem = null;
  1374. newItem.PrevItem = null;
  1375. newItem.Row = row;
  1376. newItem.Column = column;
  1377. newItem.ItemIndex = itemIndex;
  1378. newItem.ItemCreatedCheckFrameCount = mListUpdateCheckFrameCount;
  1379. return newItem;
  1380. }
  1381. RowColumnPair GetCeilItemRowColumnAtGivenAbsPos(float ax, float ay)
  1382. {
  1383. ax = Mathf.Abs(ax);
  1384. ay = Mathf.Abs(ay);
  1385. int row = Mathf.CeilToInt((ay - mStartPadding.y - mItemAlginOffset.y) / mItemSizeWithPadding.y) - 1;
  1386. int column = Mathf.CeilToInt((ax - mStartPadding.x - mItemAlginOffset.x) / mItemSizeWithPadding.x) - 1;
  1387. if (row < 0)
  1388. {
  1389. row = 0;
  1390. }
  1391. if (row >= mRowCount)
  1392. {
  1393. row = mRowCount - 1;
  1394. }
  1395. if (column < 0)
  1396. {
  1397. column = 0;
  1398. }
  1399. if (column >= mColumnCount)
  1400. {
  1401. column = mColumnCount - 1;
  1402. }
  1403. return new RowColumnPair(row, column);
  1404. }
  1405. void Update()
  1406. {
  1407. if (mListViewInited == false)
  1408. {
  1409. return;
  1410. }
  1411. if (mRefreshRawOrColumn)
  1412. {
  1413. mRefreshRawOrColumn = false;
  1414. UpdateRealFixedRowOrColumnCount();
  1415. }
  1416. UpdateSnapMove();
  1417. UpdateGridViewContent();
  1418. ClearAllTmpRecycledItem();
  1419. }
  1420. GridItemGroup CreateItemGroup(int groupIndex)
  1421. {
  1422. GridItemGroup ret = GetOneItemGroupObj();
  1423. ret.GroupIndex = groupIndex;
  1424. return ret;
  1425. }
  1426. Vector2 GetContainerMovedDistance()
  1427. {
  1428. Vector2 pos = GetContainerVaildPos(ContainerTrans.anchoredPosition3D.x, ContainerTrans.anchoredPosition3D.y);
  1429. return new Vector2(Mathf.Abs(pos.x), Mathf.Abs(pos.y));
  1430. }
  1431. Vector2 GetContainerVaildPos(float curX, float curY)
  1432. {
  1433. float maxCanMoveX = Mathf.Max(ContainerTrans.rect.width - ViewPortWidth, 0);
  1434. float maxCanMoveY = Mathf.Max(ContainerTrans.rect.height - ViewPortHeight, 0);
  1435. if (mArrangeType == GridItemArrangeType.TopLeftToBottomRight)
  1436. {
  1437. curX = Mathf.Clamp(curX, -maxCanMoveX, 0);
  1438. curY = Mathf.Clamp(curY, 0, maxCanMoveY);
  1439. }
  1440. else if (mArrangeType == GridItemArrangeType.BottomLeftToTopRight)
  1441. {
  1442. curX = Mathf.Clamp(curX, -maxCanMoveX, 0);
  1443. curY = Mathf.Clamp(curY, -maxCanMoveY, 0);
  1444. }
  1445. else if (mArrangeType == GridItemArrangeType.BottomRightToTopLeft)
  1446. {
  1447. curX = Mathf.Clamp(curX, 0, maxCanMoveX);
  1448. curY = Mathf.Clamp(curY, -maxCanMoveY, 0);
  1449. }
  1450. else if (mArrangeType == GridItemArrangeType.TopRightToBottomLeft)
  1451. {
  1452. curX = Mathf.Clamp(curX, 0, maxCanMoveX);
  1453. curY = Mathf.Clamp(curY, 0, maxCanMoveY);
  1454. }
  1455. return new Vector2(curX, curY);
  1456. }
  1457. void UpdateCurFrameItemRangeData()
  1458. {
  1459. Vector2 distVector2 = GetContainerMovedDistance();
  1460. if (mNeedCheckContentPosLeftCount <= 0 && mCurFrameItemRangeData.mCheckedPosition == distVector2)
  1461. {
  1462. return;
  1463. }
  1464. if (mNeedCheckContentPosLeftCount > 0)
  1465. {
  1466. mNeedCheckContentPosLeftCount--;
  1467. }
  1468. float distX = distVector2.x - mItemRecycleDistance.x;
  1469. float distY = distVector2.y - mItemRecycleDistance.y;
  1470. if (distX < 0)
  1471. {
  1472. distX = 0;
  1473. }
  1474. if (distY < 0)
  1475. {
  1476. distY = 0;
  1477. }
  1478. RowColumnPair val = GetCeilItemRowColumnAtGivenAbsPos(distX, distY);
  1479. mCurFrameItemRangeData.mMinColumn = val.mColumn;
  1480. mCurFrameItemRangeData.mMinRow = val.mRow;
  1481. distX = distVector2.x + mItemRecycleDistance.x + ViewPortWidth;
  1482. distY = distVector2.y + mItemRecycleDistance.y + ViewPortHeight;
  1483. val = GetCeilItemRowColumnAtGivenAbsPos(distX, distY);
  1484. mCurFrameItemRangeData.mMaxColumn = val.mColumn;
  1485. mCurFrameItemRangeData.mMaxRow = val.mRow;
  1486. mCurFrameItemRangeData.mCheckedPosition = distVector2;
  1487. }
  1488. void UpdateRowItemGroupForRecycleAndNew(GridItemGroup group, int idx)
  1489. {
  1490. int minColumn = mCurFrameItemRangeData.mMinColumn;
  1491. int maxColumn = mCurFrameItemRangeData.mMaxColumn;
  1492. int row = group.GroupIndex;
  1493. while (group.First != null && group.First.Column < minColumn)
  1494. {
  1495. RecycleItemTmp(group.RemoveFirst());
  1496. }
  1497. while (group.Last != null && ((group.Last.Column > maxColumn) || (group.Last.ItemIndex >= mRealItemTotalCount)))
  1498. {
  1499. RecycleItemTmp(group.RemoveLast());
  1500. }
  1501. if (group.First == null)
  1502. {
  1503. LoopGridViewItem item = GetNewItemByRowColumn(row, minColumn);
  1504. if (item == null)
  1505. {
  1506. return;
  1507. }
  1508. item.CachedRectTransform.anchoredPosition3D = GetItemPos(item.Row, item.Column);
  1509. if (mSortStartIdx >= 0)
  1510. item.CachedRectTransform.SetSiblingIndex(mSortStartIdx + idx * (maxColumn - minColumn + 1));
  1511. group.AddFirst(item);
  1512. }
  1513. while (group.First.Column > minColumn)
  1514. {
  1515. LoopGridViewItem item = GetNewItemByRowColumn(row, group.First.Column - 1);
  1516. if (item == null)
  1517. {
  1518. break;
  1519. }
  1520. item.CachedRectTransform.anchoredPosition3D = GetItemPos(item.Row, item.Column);
  1521. if (mSortStartIdx >= 0)
  1522. item.CachedRectTransform.SetSiblingIndex(mSortStartIdx + idx * (maxColumn - minColumn + 1) + 1);
  1523. group.AddFirst(item);
  1524. }
  1525. while (group.Last.Column < maxColumn)
  1526. {
  1527. LoopGridViewItem item = GetNewItemByRowColumn(row, group.Last.Column + 1);
  1528. if (item == null)
  1529. {
  1530. break;
  1531. }
  1532. item.CachedRectTransform.anchoredPosition3D = GetItemPos(item.Row, item.Column);
  1533. if (mSortStartIdx >= 0)
  1534. item.CachedRectTransform.SetSiblingIndex(mSortStartIdx + idx * (maxColumn - minColumn + 1) + (item.Column - minColumn));
  1535. group.AddLast(item);
  1536. }
  1537. }
  1538. void UpdateColumnItemGroupForRecycleAndNew(GridItemGroup group, int idx)
  1539. {
  1540. int minRow = mCurFrameItemRangeData.mMinRow;
  1541. int maxRow = mCurFrameItemRangeData.mMaxRow;
  1542. int column = group.GroupIndex;
  1543. while (group.First != null && group.First.Row < minRow)
  1544. {
  1545. RecycleItemTmp(group.RemoveFirst());
  1546. }
  1547. while (group.Last != null && ((group.Last.Row > maxRow) || (group.Last.ItemIndex >= mRealItemTotalCount)))
  1548. {
  1549. RecycleItemTmp(group.RemoveLast());
  1550. }
  1551. if (group.First == null)
  1552. {
  1553. LoopGridViewItem item = GetNewItemByRowColumn(minRow, column);
  1554. if (item == null)
  1555. {
  1556. return;
  1557. }
  1558. item.CachedRectTransform.anchoredPosition3D = GetItemPos(item.Row, item.Column);
  1559. if (mSortStartIdx >= 0)
  1560. item.CachedRectTransform.SetSiblingIndex(mSortStartIdx + idx * (maxRow - minRow + 1));
  1561. group.AddFirst(item);
  1562. }
  1563. while (group.First.Row > minRow)
  1564. {
  1565. LoopGridViewItem item = GetNewItemByRowColumn(group.First.Row - 1, column);
  1566. if (item == null)
  1567. {
  1568. break;
  1569. }
  1570. item.CachedRectTransform.anchoredPosition3D = GetItemPos(item.Row, item.Column);
  1571. if (mSortStartIdx >= 0)
  1572. item.CachedRectTransform.SetSiblingIndex(mSortStartIdx + idx * (maxRow - minRow + 1) + 1);
  1573. group.AddFirst(item);
  1574. }
  1575. while (group.Last.Row < maxRow)
  1576. {
  1577. LoopGridViewItem item = GetNewItemByRowColumn(group.Last.Row + 1, column);
  1578. if (item == null)
  1579. {
  1580. break;
  1581. }
  1582. item.CachedRectTransform.anchoredPosition3D = GetItemPos(item.Row, item.Column);
  1583. if (mSortStartIdx >= 0)
  1584. item.CachedRectTransform.SetSiblingIndex(mSortStartIdx + idx * (maxRow - minRow + 1) + (item.Row - minRow));
  1585. group.AddLast(item);
  1586. }
  1587. }
  1588. void SetScrollbarListener()
  1589. {
  1590. if (ItemSnapEnable == false)
  1591. {
  1592. return;
  1593. }
  1594. mScrollBarClickEventListener1 = null;
  1595. mScrollBarClickEventListener2 = null;
  1596. Scrollbar curScrollBar1 = null;
  1597. Scrollbar curScrollBar2 = null;
  1598. if (mScrollRect.vertical && mScrollRect.verticalScrollbar != null)
  1599. {
  1600. curScrollBar1 = mScrollRect.verticalScrollbar;
  1601. }
  1602. if (mScrollRect.horizontal && mScrollRect.horizontalScrollbar != null)
  1603. {
  1604. curScrollBar2 = mScrollRect.horizontalScrollbar;
  1605. }
  1606. if (curScrollBar1 != null)
  1607. {
  1608. ClickEventListener listener = ClickEventListener.Get(curScrollBar1.gameObject);
  1609. mScrollBarClickEventListener1 = listener;
  1610. listener.SetPointerUpHandler(OnPointerUpInScrollBar);
  1611. listener.SetPointerDownHandler(OnPointerDownInScrollBar);
  1612. }
  1613. if (curScrollBar2 != null)
  1614. {
  1615. ClickEventListener listener = ClickEventListener.Get(curScrollBar2.gameObject);
  1616. mScrollBarClickEventListener2 = listener;
  1617. listener.SetPointerUpHandler(OnPointerUpInScrollBar);
  1618. listener.SetPointerDownHandler(OnPointerDownInScrollBar);
  1619. }
  1620. }
  1621. void OnPointerDownInScrollBar(GameObject obj)
  1622. {
  1623. mCurSnapData.Clear();
  1624. }
  1625. void OnPointerUpInScrollBar(GameObject obj)
  1626. {
  1627. ForceSnapUpdateCheck();
  1628. }
  1629. RowColumnPair FindNearestItemWithLocalPos(float x, float y)
  1630. {
  1631. Vector2 targetPos = new Vector2(x, y);
  1632. RowColumnPair val = GetCeilItemRowColumnAtGivenAbsPos(targetPos.x, targetPos.y);
  1633. int row = val.mRow;
  1634. int column = val.mColumn;
  1635. float distance = 0;
  1636. RowColumnPair ret = new RowColumnPair(-1, -1);
  1637. Vector2 pos = Vector2.zero;
  1638. float minDistance = float.MaxValue;
  1639. for (int r = row - 1; r <= row + 1; ++r)
  1640. {
  1641. for (int c = column - 1; c <= column + 1; ++c)
  1642. {
  1643. if (r >= 0 && r < mRowCount && c >= 0 && c < mColumnCount)
  1644. {
  1645. pos = GetItemSnapPivotLocalPos(r, c);
  1646. distance = (pos - targetPos).sqrMagnitude;
  1647. if (distance < minDistance)
  1648. {
  1649. minDistance = distance;
  1650. ret.mRow = r;
  1651. ret.mColumn = c;
  1652. }
  1653. }
  1654. }
  1655. }
  1656. return ret;
  1657. }
  1658. public int FindNearestItemIndex()
  1659. {
  1660. Vector2 pos = GetContainerVaildPos(ContainerTrans.anchoredPosition3D.x, ContainerTrans.anchoredPosition3D.y);
  1661. Vector2 snapTartetPos = GetViewPortSnapPivotLocalPos(pos);
  1662. RowColumnPair curVal = FindNearestItemWithLocalPos(snapTartetPos.x, snapTartetPos.y);
  1663. int index = GetItemIndexByRowColumn(curVal.mRow, curVal.mColumn);
  1664. return index;
  1665. }
  1666. public void FindItemIdxInWorldRect(Vector2 min, Vector2 max, out int startItemIdx, out int endItemIdx)
  1667. {
  1668. if (mArrangeType == GridItemArrangeType.TopLeftToBottomRight)
  1669. {
  1670. min = mContainerTrans.InverseTransformPoint(min);
  1671. max = mContainerTrans.InverseTransformPoint(max);
  1672. int column1 = Mathf.CeilToInt((min.x - mStartPadding.x - mItemAlginOffset.x) / mItemSizeWithPadding.x);
  1673. int row1 = Mathf.CeilToInt((-max.y - mStartPadding.y - mItemAlginOffset.y) / mItemSizeWithPadding.y);
  1674. int column2 = Mathf.FloorToInt((max.x - mStartPadding.x - mItemAlginOffset.x) / mItemSizeWithPadding.x);
  1675. int row2 = Mathf.FloorToInt((-min.y - mStartPadding.y - mItemAlginOffset.y) / mItemSizeWithPadding.y);
  1676. startItemIdx = GetItemIndexByRowColumn(row1, column1);
  1677. startItemIdx = Mathf.Clamp(startItemIdx, 0, mRealItemTotalCount);
  1678. endItemIdx = GetItemIndexByRowColumn(row2, column2);
  1679. endItemIdx = Mathf.Clamp(endItemIdx, 0, mRealItemTotalCount);
  1680. }
  1681. else if (mArrangeType == GridItemArrangeType.BottomLeftToTopRight)
  1682. {
  1683. min = mContainerTrans.InverseTransformPoint(min);
  1684. max = mContainerTrans.InverseTransformPoint(max);
  1685. int column1 = Mathf.CeilToInt((min.x - mEndPadding.x - mItemAlginOffset.x) / mItemSizeWithPadding.x);
  1686. int row1 = Mathf.CeilToInt((max.y - mEndPadding.y - mItemAlginOffset.y) / mItemSizeWithPadding.y);
  1687. int column2 = Mathf.FloorToInt((max.x - mEndPadding.x - mItemAlginOffset.x) / mItemSizeWithPadding.x);
  1688. int row2 = Mathf.FloorToInt((min.y - mEndPadding.y - mItemAlginOffset.y) / mItemSizeWithPadding.y);
  1689. startItemIdx = GetItemIndexByRowColumn(row2, column2);
  1690. startItemIdx = Mathf.Clamp(startItemIdx, 0, mRealItemTotalCount);
  1691. endItemIdx = GetItemIndexByRowColumn(row1, column1);
  1692. endItemIdx = Mathf.Clamp(endItemIdx, 0, mRealItemTotalCount);
  1693. }
  1694. else
  1695. {
  1696. startItemIdx = -1;
  1697. endItemIdx = -1;
  1698. }
  1699. }
  1700. Vector2 GetItemSnapPivotLocalPos(int row, int column)
  1701. {
  1702. Vector2 absPos = GetItemAbsPos(row, column);
  1703. if (mArrangeType == GridItemArrangeType.TopLeftToBottomRight)
  1704. {
  1705. float x = absPos.x + mItemSize.x * mItemSnapPivot.x;
  1706. float y = -absPos.y - mItemSize.y * (1 - mItemSnapPivot.y);
  1707. return new Vector2(x, y);
  1708. }
  1709. else if (mArrangeType == GridItemArrangeType.BottomLeftToTopRight)
  1710. {
  1711. float x = absPos.x + mItemSize.x * mItemSnapPivot.x;
  1712. float y = absPos.y + mItemSize.y * mItemSnapPivot.y;
  1713. return new Vector2(x, y);
  1714. }
  1715. else if (mArrangeType == GridItemArrangeType.TopRightToBottomLeft)
  1716. {
  1717. float x = -absPos.x - mItemSize.x * (1 - mItemSnapPivot.x);
  1718. float y = -absPos.y - mItemSize.y * (1 - mItemSnapPivot.y);
  1719. return new Vector2(x, y);
  1720. }
  1721. else if (mArrangeType == GridItemArrangeType.BottomRightToTopLeft)
  1722. {
  1723. float x = -absPos.x - mItemSize.x * (1 - mItemSnapPivot.x);
  1724. float y = absPos.y + mItemSize.y * mItemSnapPivot.y;
  1725. return new Vector2(x, y);
  1726. }
  1727. return Vector2.zero;
  1728. }
  1729. Vector2 GetViewPortSnapPivotLocalPos(Vector2 pos)
  1730. {
  1731. float pivotLocalPosX = 0;
  1732. float pivotLocalPosY = 0;
  1733. if (mArrangeType == GridItemArrangeType.TopLeftToBottomRight)
  1734. {
  1735. pivotLocalPosX = -pos.x + ViewPortWidth * mViewPortSnapPivot.x;
  1736. pivotLocalPosY = -pos.y - ViewPortHeight * (1 - mViewPortSnapPivot.y);
  1737. }
  1738. else if (mArrangeType == GridItemArrangeType.BottomLeftToTopRight)
  1739. {
  1740. pivotLocalPosX = -pos.x + ViewPortWidth * mViewPortSnapPivot.x;
  1741. pivotLocalPosY = -pos.y + ViewPortHeight * mViewPortSnapPivot.y;
  1742. }
  1743. else if (mArrangeType == GridItemArrangeType.TopRightToBottomLeft)
  1744. {
  1745. pivotLocalPosX = -pos.x - ViewPortWidth * (1 - mViewPortSnapPivot.x);
  1746. pivotLocalPosY = -pos.y - ViewPortHeight * (1 - mViewPortSnapPivot.y);
  1747. }
  1748. else if (mArrangeType == GridItemArrangeType.BottomRightToTopLeft)
  1749. {
  1750. pivotLocalPosX = -pos.x - ViewPortWidth * (1 - mViewPortSnapPivot.x);
  1751. pivotLocalPosY = -pos.y + ViewPortHeight * mViewPortSnapPivot.y;
  1752. }
  1753. return new Vector2(pivotLocalPosX, pivotLocalPosY);
  1754. }
  1755. void UpdateNearestSnapItem(bool forceSendEvent)
  1756. {
  1757. if (mItemSnapEnable == false)
  1758. {
  1759. return;
  1760. }
  1761. int count = mItemGroupList.Count;
  1762. if (count == 0)
  1763. {
  1764. return;
  1765. }
  1766. if (IsContainerTransCanMove() == false)
  1767. {
  1768. return;
  1769. }
  1770. Vector2 pos = GetContainerVaildPos(ContainerTrans.anchoredPosition3D.x, ContainerTrans.anchoredPosition3D.y);
  1771. bool needCheck = (pos.y != mLastSnapCheckPos.y || pos.x != mLastSnapCheckPos.x);
  1772. mLastSnapCheckPos = pos;
  1773. if (!needCheck)
  1774. {
  1775. if (mLeftSnapUpdateExtraCount > 0)
  1776. {
  1777. mLeftSnapUpdateExtraCount--;
  1778. needCheck = true;
  1779. }
  1780. }
  1781. if (needCheck)
  1782. {
  1783. RowColumnPair curVal = new RowColumnPair(-1, -1);
  1784. Vector2 snapTartetPos = GetViewPortSnapPivotLocalPos(pos);
  1785. curVal = FindNearestItemWithLocalPos(snapTartetPos.x, snapTartetPos.y);
  1786. if (curVal.mRow >= 0)
  1787. {
  1788. RowColumnPair oldNearestItem = mCurSnapNearestItemRowColumn;
  1789. mCurSnapNearestItemRowColumn = curVal;
  1790. if (forceSendEvent || oldNearestItem != mCurSnapNearestItemRowColumn)
  1791. {
  1792. if (mOnSnapNearestChanged != null)
  1793. {
  1794. mOnSnapNearestChanged(this);
  1795. }
  1796. }
  1797. }
  1798. else
  1799. {
  1800. mCurSnapNearestItemRowColumn.mRow = -1;
  1801. mCurSnapNearestItemRowColumn.mColumn = -1;
  1802. }
  1803. }
  1804. }
  1805. void UpdateFromSettingParam(LoopGridViewSettingParam param)
  1806. {
  1807. if (param == null)
  1808. {
  1809. return;
  1810. }
  1811. if (param.mItemSize != null)
  1812. {
  1813. mItemSize = (Vector2)(param.mItemSize);
  1814. }
  1815. if (param.mItemPadding != null)
  1816. {
  1817. mItemPadding = (Vector2)(param.mItemPadding);
  1818. }
  1819. if (param.mPadding != null)
  1820. {
  1821. mPadding = (RectOffset)(param.mPadding);
  1822. }
  1823. if (param.mGridFixedType != null)
  1824. {
  1825. mGridFixedType = (GridFixedType)(param.mGridFixedType);
  1826. }
  1827. if (param.mFixedRowOrColumnCount != null)
  1828. {
  1829. mFixedRowOrColumnCount = System.Convert.ToInt32(param.mFixedRowOrColumnCount);
  1830. }
  1831. }
  1832. //snap move will finish at once.
  1833. public void FinishSnapImmediately()
  1834. {
  1835. UpdateSnapMove(true);
  1836. }
  1837. //update snap move. if immediate is set true, then the snap move will finish at once.
  1838. void UpdateSnapMove(bool immediate = false, bool forceSendEvent = false)
  1839. {
  1840. if (mItemSnapEnable == false)
  1841. {
  1842. return;
  1843. }
  1844. UpdateNearestSnapItem(false);
  1845. Vector2 pos = mContainerTrans.anchoredPosition3D;
  1846. if (CanSnap() == false)
  1847. {
  1848. ClearSnapData();
  1849. return;
  1850. }
  1851. UpdateCurSnapData();
  1852. if (mCurSnapData.mSnapStatus != SnapStatus.SnapMoving)
  1853. {
  1854. return;
  1855. }
  1856. float v = Mathf.Abs(mScrollRect.velocity.x) + Mathf.Abs(mScrollRect.velocity.y);
  1857. if (v > 0)
  1858. {
  1859. mScrollRect.StopMovement();
  1860. }
  1861. float old = mCurSnapData.mCurSnapVal;
  1862. mCurSnapData.mCurSnapVal = Mathf.SmoothDamp(mCurSnapData.mCurSnapVal, mCurSnapData.mTargetSnapVal, ref mSmoothDumpVel, mSmoothDumpRate);
  1863. float dt = mCurSnapData.mCurSnapVal - old;
  1864. if (immediate || Mathf.Abs(mCurSnapData.mTargetSnapVal - mCurSnapData.mCurSnapVal) < mSnapFinishThreshold)
  1865. {
  1866. pos = pos + (mCurSnapData.mTargetSnapVal - old) * mCurSnapData.mSnapNeedMoveDir;
  1867. mCurSnapData.mSnapStatus = SnapStatus.SnapMoveFinish;
  1868. if (mOnSnapItemFinished != null)
  1869. {
  1870. LoopGridViewItem targetItem = GetShownItemByRowColumn(mCurSnapNearestItemRowColumn.mRow, mCurSnapNearestItemRowColumn.mColumn);
  1871. if (targetItem != null)
  1872. {
  1873. mOnSnapItemFinished(this, targetItem);
  1874. }
  1875. }
  1876. }
  1877. else
  1878. {
  1879. pos = pos + dt * mCurSnapData.mSnapNeedMoveDir;
  1880. }
  1881. mContainerTrans.anchoredPosition3D = GetContainerVaildPos(pos.x, pos.y);
  1882. }
  1883. GridItemGroup GetShownGroup(int groupIndex)
  1884. {
  1885. if (groupIndex < 0)
  1886. {
  1887. return null;
  1888. }
  1889. int count = mItemGroupList.Count;
  1890. if (count == 0)
  1891. {
  1892. return null;
  1893. }
  1894. if (groupIndex < mItemGroupList[0].GroupIndex || groupIndex > mItemGroupList[count - 1].GroupIndex)
  1895. {
  1896. return null;
  1897. }
  1898. int i = groupIndex - mItemGroupList[0].GroupIndex;
  1899. return mItemGroupList[i];
  1900. }
  1901. void FillCurSnapData(int row, int column)
  1902. {
  1903. Vector2 itemSnapPivotLocalPos = GetItemSnapPivotLocalPos(row, column);
  1904. Vector2 containerPos = GetContainerVaildPos(ContainerTrans.anchoredPosition3D.x, ContainerTrans.anchoredPosition3D.y);
  1905. Vector2 snapTartetPos = GetViewPortSnapPivotLocalPos(containerPos);
  1906. Vector2 dir = snapTartetPos - itemSnapPivotLocalPos;
  1907. if (mScrollRect.horizontal == false)
  1908. {
  1909. dir.x = 0;
  1910. }
  1911. if (mScrollRect.vertical == false)
  1912. {
  1913. dir.y = 0;
  1914. }
  1915. mCurSnapData.mTargetSnapVal = dir.magnitude;
  1916. mCurSnapData.mCurSnapVal = 0;
  1917. mCurSnapData.mSnapNeedMoveDir = dir.normalized;
  1918. }
  1919. void UpdateCurSnapData()
  1920. {
  1921. int count = mItemGroupList.Count;
  1922. if (count == 0)
  1923. {
  1924. mCurSnapData.Clear();
  1925. return;
  1926. }
  1927. if (mCurSnapData.mSnapStatus == SnapStatus.SnapMoveFinish)
  1928. {
  1929. if (mCurSnapData.mSnapTarget == mCurSnapNearestItemRowColumn)
  1930. {
  1931. return;
  1932. }
  1933. mCurSnapData.mSnapStatus = SnapStatus.NoTargetSet;
  1934. }
  1935. if (mCurSnapData.mSnapStatus == SnapStatus.SnapMoving)
  1936. {
  1937. if ((mCurSnapData.mSnapTarget == mCurSnapNearestItemRowColumn) || mCurSnapData.mIsForceSnapTo)
  1938. {
  1939. return;
  1940. }
  1941. mCurSnapData.mSnapStatus = SnapStatus.NoTargetSet;
  1942. }
  1943. if (mCurSnapData.mSnapStatus == SnapStatus.NoTargetSet)
  1944. {
  1945. LoopGridViewItem nearestItem = GetShownItemByRowColumn(mCurSnapNearestItemRowColumn.mRow, mCurSnapNearestItemRowColumn.mColumn);
  1946. if (nearestItem == null)
  1947. {
  1948. return;
  1949. }
  1950. mCurSnapData.mSnapTarget = mCurSnapNearestItemRowColumn;
  1951. mCurSnapData.mSnapStatus = SnapStatus.TargetHasSet;
  1952. mCurSnapData.mIsForceSnapTo = false;
  1953. }
  1954. if (mCurSnapData.mSnapStatus == SnapStatus.TargetHasSet)
  1955. {
  1956. LoopGridViewItem targetItem = GetShownItemByRowColumn(mCurSnapData.mSnapTarget.mRow, mCurSnapData.mSnapTarget.mColumn);
  1957. if (targetItem == null)
  1958. {
  1959. mCurSnapData.Clear();
  1960. return;
  1961. }
  1962. FillCurSnapData(targetItem.Row, targetItem.Column);
  1963. mCurSnapData.mSnapStatus = SnapStatus.SnapMoving;
  1964. }
  1965. }
  1966. bool CanSnap()
  1967. {
  1968. if (mIsDraging)
  1969. {
  1970. return false;
  1971. }
  1972. if (mScrollBarClickEventListener1 != null)
  1973. {
  1974. if (mScrollBarClickEventListener1.IsPressd)
  1975. {
  1976. return false;
  1977. }
  1978. }
  1979. if (mScrollBarClickEventListener2 != null)
  1980. {
  1981. if (mScrollBarClickEventListener2.IsPressd)
  1982. {
  1983. return false;
  1984. }
  1985. }
  1986. if (IsContainerTransCanMove() == false)
  1987. {
  1988. return false;
  1989. }
  1990. if (Mathf.Abs(mScrollRect.velocity.x) > mSnapVecThreshold)
  1991. {
  1992. return false;
  1993. }
  1994. if (Mathf.Abs(mScrollRect.velocity.y) > mSnapVecThreshold)
  1995. {
  1996. return false;
  1997. }
  1998. Vector3 pos = mContainerTrans.anchoredPosition3D;
  1999. Vector2 vPos = GetContainerVaildPos(pos.x, pos.y);
  2000. if (Mathf.Abs(pos.x - vPos.x) > 3)
  2001. {
  2002. return false;
  2003. }
  2004. if (Mathf.Abs(pos.y - vPos.y) > 3)
  2005. {
  2006. return false;
  2007. }
  2008. return true;
  2009. }
  2010. GridItemGroup GetOneItemGroupObj()
  2011. {
  2012. int count = mItemGroupObjPool.Count;
  2013. if (count == 0)
  2014. {
  2015. return new GridItemGroup();
  2016. }
  2017. GridItemGroup ret = mItemGroupObjPool[count - 1];
  2018. mItemGroupObjPool.RemoveAt(count - 1);
  2019. return ret;
  2020. }
  2021. void RecycleOneItemGroupObj(GridItemGroup obj)
  2022. {
  2023. mItemGroupObjPool.Add(obj);
  2024. }
  2025. public void Dispose()
  2026. {
  2027. RecycleAllItem();
  2028. int count = mItemPoolList.Count;
  2029. for (int i = 0; i < count; ++i)
  2030. {
  2031. mItemPoolList[i].DestroyAllItem();
  2032. }
  2033. mItemPoolList.Clear();
  2034. mItemPoolDict.Clear();
  2035. mListViewInited = false;
  2036. mScrollBarClickEventListener1 = null;
  2037. mScrollBarClickEventListener2 = null;
  2038. mOnGetItemByRowColumn = null;
  2039. mOnRecycleItem = null;
  2040. mOnBeginDragAction = null;
  2041. mOnDragingAction = null;
  2042. mOnEndDragAction = null;
  2043. mOnSnapItemFinished = null;
  2044. mOnSnapNearestChanged = null;
  2045. if (mContainerTrans != null)
  2046. {
  2047. mContainerTrans.anchoredPosition3D = Vector3.zero;
  2048. mContainerTrans.sizeDelta = Vector2.zero;
  2049. }
  2050. }
  2051. protected void OnRectTransformDimensionsChange()
  2052. {
  2053. if (!mListViewInited) return;
  2054. mRefreshRawOrColumn = true;
  2055. }
  2056. }
  2057. }