ListUtil.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. import EventMng from "../../manager/EventMng";
  2. import LevelRender from "../compment/LevelRender";
  3. import { AutowiredItem } from "./Autowire";
  4. import { BtnEvent } from "./mvc/FguiViewCtrl";
  5. export enum VirtualListType {
  6. /**
  7. * 实列表
  8. */
  9. Real = 1,
  10. /**
  11. * 虚拟列表(非循环
  12. */
  13. Virtual = 2,
  14. /**
  15. * 虚拟循环列表
  16. */
  17. VirtualAndLoop = 3,
  18. }
  19. export class ListUtil {
  20. // static readonly TweenInTime = 0.19;
  21. static readonly TweenInTime = 0.5;
  22. static readonly TweenDelayTime = 0.11;
  23. dataList: any[];
  24. gList: fgui.GList;
  25. param: any;
  26. private needTween: number;
  27. private aniName: string;
  28. private delay: number = ListUtil.TweenDelayTime;
  29. /**
  30. * 列表管理类(需要注意同一个fgui资源不应该被不同的类重复拓展)
  31. * @param glist 管理的列表
  32. * @param uiClass 拓展的列表资源类(自己定义一个类,继承Itemrender类)
  33. * @param listType 列表类型,见ListType 1.(默认开启虚拟列表,如果要开启虚拟列表,必须设置滚动 2.(虚拟循环列表不支持横向或纵向流动
  34. * @param levelrender 开启分层渲染,(内容物包含遮罩的禁止使用!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)
  35. */
  36. constructor(glist: fgui.GList, uiClass: (new () => ItemRender) | (new () => ItemLabelRender) = null, listType: VirtualListType = VirtualListType.Virtual, levelrender: boolean = false) {
  37. this.gList = glist;
  38. if (levelrender) glist._container.addComponent(LevelRender);
  39. if (uiClass) {
  40. let item = glist.getFromPool();
  41. if (!item) {
  42. if (CC_PREVIEW) console.error("列表内没有添加默认资源");
  43. return;
  44. }
  45. if (item.packageItem.extensionType && item.packageItem.extensionType != uiClass) {
  46. if (CC_PREVIEW) console.warn(`列表${this.gList.name}内的默认资源资源${item.resourceURL}, 已经被`, item.packageItem.extensionType, "拓展");
  47. return;
  48. }
  49. item.packageItem.extensionType = uiClass;
  50. fgui.UIObjectFactory.extensions[item.resourceURL] = uiClass;
  51. }
  52. switch (listType) {
  53. case VirtualListType.Virtual:
  54. this.gList.setVirtual();
  55. break;
  56. case VirtualListType.VirtualAndLoop:
  57. this.gList.setVirtualAndLoop();
  58. break;
  59. }
  60. }
  61. /**
  62. * 列表内容可变时需要自己预先根据url预先拓展(fgui.UIObjectFactory.setExtension
  63. * @param cb 提供item的url回调
  64. * @param target 绑定
  65. */
  66. setItemProvider(cb: (index: number) => string, target: any = this) {
  67. this.gList.itemProvider = cb.bind(target);
  68. }
  69. /**
  70. * 刷新列表
  71. * @param list 数据
  72. * @param param 额外参数
  73. */
  74. refreshItems(list: any[], param?: any) {
  75. this.dataList = list;
  76. this.param = param;
  77. this.gList.itemRenderer = this.refreshItem.bind(this);
  78. this.gList.numItems = list.length;
  79. this.gList.ensureBoundsCorrect();
  80. this.clearTween();
  81. }
  82. private refreshItem(index: number, render: ItemRender) {
  83. let data = this.dataList[index];
  84. try {
  85. render.__refreshData(data, index, this.param, this.needTween, this.aniName, this.delay);
  86. } catch (err) {
  87. if (CC_PREVIEW) console.warn(err);
  88. }
  89. }
  90. setTween(line: number, aniName: string = null, delay: number = ListUtil.TweenDelayTime) {
  91. this.needTween = line;
  92. this.aniName = aniName;
  93. this.delay = delay;
  94. }
  95. clearTween() {
  96. this.needTween = 0;
  97. this.aniName = null;
  98. this.delay = ListUtil.TweenDelayTime;
  99. }
  100. }
  101. export abstract class ItemRender extends fairygui.GButton implements AutowiredItem {
  102. __autowired: string[];
  103. private __tween__: cc.Tween;
  104. index: number;
  105. __AutoGetItem() {
  106. this.__autowired?.forEach((key: string) => {
  107. this[key] = this.getChild(key);
  108. });
  109. }
  110. __refreshData(data: any, index: number, param: any, needTween: number, aniName: string = null, delay: number = ListUtil.TweenDelayTime) {
  111. if (needTween) this.__ShowTween(index, needTween, aniName, delay);
  112. else this.__clearTween();
  113. this.index = index;
  114. this.setData(data, index, param);
  115. }
  116. /**
  117. * @param data 列表数据
  118. * @param index 列表内资源对应下标,从0开始
  119. * @param param 额外参数
  120. */
  121. abstract setData(data: any, index?: number, param?: any);
  122. /**通知事件列表 */
  123. private _notifyEventList: Map<string, Function> = new Map<string, Function>();
  124. //计时器ID列表
  125. private m_Timers: Set<number> = new Set();
  126. /** 按钮点击注册器 */
  127. private btnClicks: BtnEvent[] = [];
  128. protected onConstruct(): void {
  129. this.__AutoGetItem();
  130. this.onInit();
  131. }
  132. protected onEnable(): void {
  133. this.onShow();
  134. }
  135. protected onDisable(): void {
  136. this.offEvent();
  137. this.RemoveAllClick();
  138. this.RemoveTimers();
  139. this.__clearTween();
  140. this.onHide();
  141. }
  142. onShow() { }
  143. onHide() { }
  144. onInit() { }
  145. /**
  146. * 获取所有控制器并赋值
  147. */
  148. initControllers() {
  149. for (let i of this.controllers) {
  150. this[i.name] = i;
  151. }
  152. }
  153. offEvent() {
  154. try {
  155. let self = this;
  156. this._notifyEventList.forEach((f, key) => {
  157. EventMng.off(key, f, self);
  158. }, this);
  159. this._notifyEventList.clear();
  160. } catch (error) {
  161. if (CC_PREVIEW) console.error("onDisable->" + error);
  162. }
  163. }
  164. /**注册notice事件,disable的时候会自动移除 */
  165. initEvent(eventName: string, cb: Function) {
  166. if (this._notifyEventList.get(eventName) != null) return;
  167. this._notifyEventList.set(eventName, cb);
  168. EventMng.on(eventName, cb, this);
  169. }
  170. /**
  171. * 增加定时器
  172. * @param callback
  173. * @param delta 单位毫秒ms
  174. */
  175. AddTimer(callback: Function, delta: number) {
  176. let timer = setInterval(() => {
  177. callback.apply(this);
  178. }, delta);
  179. this.m_Timers.add(timer);
  180. }
  181. /** 移除所有定时器 */
  182. RemoveTimers() {
  183. this.m_Timers.forEach((element) => {
  184. clearInterval(element);
  185. });
  186. this.m_Timers.clear();
  187. }
  188. /**
  189. * 一次性定时器
  190. * @param callback
  191. * @param delta 单位毫秒ms
  192. */
  193. AddTimerOnce(callback: Function, delta: number) {
  194. let timer = setInterval(() => {
  195. clearInterval(timer);
  196. this.m_Timers.delete(timer);
  197. callback();
  198. }, delta);
  199. this.m_Timers.add(timer);
  200. return timer;
  201. }
  202. RegisterClick(btn: fairygui.GObject, func: Function) {
  203. btn.onClick(func, this);
  204. this.btnClicks.push({ btn: btn, func: func });
  205. }
  206. RemoveAllClick() {
  207. this.btnClicks.forEach((element) => {
  208. element.btn.offClick(element.func, this);
  209. });
  210. }
  211. private __fguiTweentimer = null;
  212. private __ShowTween(index: number, needTween: number, aniName: string = null, delayTime: number = ListUtil.TweenDelayTime) {
  213. if (this.__tween__) {
  214. this.__tween__.stop();
  215. }
  216. let delay = Math.floor(index / needTween) * delayTime;
  217. if (aniName != null) {
  218. if (this.__fguiTweentimer) clearInterval(this.__fguiTweentimer);
  219. this.alpha = 0;
  220. this.__fguiTweentimer = this.AddTimerOnce(() => {
  221. this.alpha = 1;
  222. this.getTransition(aniName).play();
  223. this.__fguiTweentimer = null;
  224. }, delay * 1000);
  225. } else {
  226. this.alpha = 0;
  227. this.__tween__ = cc
  228. .tween(this as fairygui.GObject)
  229. .delay(delay)
  230. .to(ListUtil.TweenInTime, {
  231. alpha: 1,
  232. })
  233. .call(() => {
  234. this.alpha = 1;
  235. })
  236. .start();
  237. }
  238. }
  239. private __clearTween() {
  240. this.__tween__?.stop();
  241. this.alpha = 1;
  242. }
  243. }
  244. export abstract class ItemLabelRender extends fairygui.GLabel implements AutowiredItem {
  245. __autowired: string[];
  246. private __tween__: cc.Tween;
  247. __AutoGetItem() {
  248. this.__autowired?.forEach((key: string) => {
  249. this[key] = this.getChild(key);
  250. });
  251. }
  252. __refreshData(data: any, index: number, param: any, needTween: number, aniName: string = null, delay: number = ListUtil.TweenDelayTime) {
  253. if (needTween > 0) this.__ShowTween(index, needTween, aniName, delay);
  254. else this.__clearTween();
  255. this.setData(data, index, param);
  256. }
  257. /**
  258. * @param data 列表数据
  259. * @param index 列表内资源对应下标,从0开始
  260. * @param param 额外参数
  261. */
  262. abstract setData(data: any, index?: number, param?: any);
  263. /**通知事件列表 */
  264. private _notifyEventList: Map<string, Function> = new Map<string, Function>();
  265. //计时器ID列表
  266. private m_Timers: Set<number> = new Set();
  267. /** 按钮点击注册器 */
  268. private btnClicks: BtnEvent[] = [];
  269. protected onConstruct(): void {
  270. this.__AutoGetItem();
  271. this.onInit();
  272. }
  273. protected onEnable(): void {
  274. this.onShow();
  275. }
  276. protected onDisable(): void {
  277. this.offEvent();
  278. this.RemoveAllClick();
  279. this.RemoveTimers();
  280. this.__clearTween();
  281. this.onHide();
  282. }
  283. onShow() { }
  284. onHide() { }
  285. onInit() { }
  286. /**
  287. * 获取所有控制器并赋值
  288. */
  289. initControllers() {
  290. for (let i of this.controllers) {
  291. this[i.name] = i;
  292. }
  293. }
  294. offEvent() {
  295. try {
  296. let self = this;
  297. this._notifyEventList.forEach((f, key) => {
  298. EventMng.off(key, f, self);
  299. }, this);
  300. this._notifyEventList.clear();
  301. } catch (error) {
  302. if (CC_PREVIEW) console.error("onDisable->" + error);
  303. }
  304. }
  305. /**注册notice事件,disable的时候会自动移除 */
  306. initEvent(eventName: string, cb: Function) {
  307. if (this._notifyEventList.get(eventName) != null) return;
  308. this._notifyEventList.set(eventName, cb);
  309. EventMng.on(eventName, cb, this);
  310. }
  311. /**
  312. * 增加定时器
  313. * @param callback
  314. * @param delta 单位毫秒ms
  315. */
  316. AddTimer(callback: Function, delta: number) {
  317. let timer = setInterval(() => {
  318. callback.apply(this);
  319. }, delta);
  320. this.m_Timers.add(timer);
  321. }
  322. /** 移除所有定时器 */
  323. RemoveTimers() {
  324. this.m_Timers.forEach((element) => {
  325. clearInterval(element);
  326. });
  327. this.m_Timers.clear();
  328. }
  329. /**
  330. * 一次性定时器
  331. * @param callback
  332. * @param delta 单位毫秒ms
  333. */
  334. AddTimerOnce(callback: Function, delta: number) {
  335. let timer = setInterval(() => {
  336. clearInterval(timer);
  337. this.m_Timers.delete(timer);
  338. callback();
  339. }, delta);
  340. this.m_Timers.add(timer);
  341. return timer;
  342. }
  343. RegisterClick(btn: fairygui.GObject, func: Function) {
  344. btn.onClick(func, this);
  345. this.btnClicks.push({ btn: btn, func: func });
  346. }
  347. RemoveAllClick() {
  348. this.btnClicks.forEach((element) => {
  349. element.btn.offClick(element.func, this);
  350. });
  351. }
  352. private __fguiTweentimer = null;
  353. private __ShowTween(index: number, needTween: number, aniName: string = null, delayTime: number = ListUtil.TweenDelayTime) {
  354. if (this.__tween__) {
  355. this.__tween__.stop();
  356. }
  357. let delay = Math.floor(index / needTween) * delayTime;
  358. if (aniName != null) {
  359. if (this.__fguiTweentimer) clearInterval(this.__fguiTweentimer);
  360. this.alpha = 0;
  361. this.__fguiTweentimer = this.AddTimerOnce(() => {
  362. this.alpha = 1;
  363. this.getTransition("aniName")?.play();
  364. this.__fguiTweentimer = null;
  365. }, delay * 1000);
  366. } else {
  367. this.alpha = 0;
  368. this.__tween__ = cc
  369. .tween(this as fairygui.GObject)
  370. .delay(delay)
  371. .to(ListUtil.TweenInTime, {
  372. alpha: 1,
  373. })
  374. .call(() => {
  375. this.alpha = 1;
  376. })
  377. .start();
  378. }
  379. }
  380. private __clearTween() {
  381. this.__tween__?.stop();
  382. this.__tween__ = null;
  383. this.alpha = 1;
  384. }
  385. }