ViewManager.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. using System.Collections.Generic;
  2. using System;
  3. using FairyGUI;
  4. using System.Linq;
  5. using ET;
  6. using UnityEngine;
  7. namespace GFGGame
  8. {
  9. public class ViewStructure
  10. {
  11. public string name;
  12. public object viewData;
  13. public IUIView iUIView;
  14. public bool backRefresh;
  15. public List<String> smallWindow;
  16. }
  17. /// <summary>
  18. /// 视图管理类
  19. /// 管理视图的显示、隐藏
  20. /// </summary>
  21. public class ViewManager
  22. {
  23. private static List<ViewStructure> _viewStack;
  24. private static Dictionary<string, IUIView> _viewDic;
  25. private static GComponent _bottomLayer;
  26. private static GComponent _topLayer;
  27. private static GComponent _guideLayer;
  28. private static GComponent _modalLayer;
  29. private static GComponent _alertLayer;
  30. private static GComponent _debugLayer;
  31. private static GComponent _floatLayer;
  32. private static bool _nowHideOthers = false; //正在关闭所有界面的循环中
  33. private static Dictionary<string, List<object[]>> _goBackDatas = new Dictionary<string, List<object[]>>();
  34. public static void Clear()
  35. {
  36. _viewStack.Clear();
  37. }
  38. private static int _packagesLoaded = 0;
  39. private static int _totalPackagesToLoad = 0;
  40. private static Action _onAllPackagesLoaded;
  41. private static Action<string> _onPackageError;
  42. public static void Init(Action onComplete, Action<string> onError = null)
  43. {
  44. //设置CustomLoader
  45. UIObjectFactory.SetLoaderExtension(typeof(GFGGLoader));
  46. _onAllPackagesLoaded = onComplete;
  47. _onPackageError = onError;
  48. _packagesLoaded = 0;
  49. string[] packagePaths = new string[]
  50. {
  51. "Login",
  52. "Common",
  53. "CommonGame",
  54. "ActivityAfternoonTea",
  55. "ActivityAFuGift",
  56. "ActivityDay7",
  57. "ActivityGetYuanXiao",
  58. "ActivityHuaRongDao",
  59. "ActivityMain",
  60. "ActivityThemeLuckyBox",
  61. "ActivityWanShiLi",
  62. "Arena",
  63. "Bag",
  64. "BlindBox",
  65. "BornLimit",
  66. "Card",
  67. "CardSynthetic",
  68. "ClothingDecompose",
  69. "ClothingFoster",
  70. "ClothingShop",
  71. "ClothingSynthetic",
  72. "ClothingUpgrade",
  73. "CreateRole",
  74. "DailyWelfare",
  75. "DeleteAccount",
  76. "DressUp",
  77. "EnduringGiftBox",
  78. "Field",
  79. "FieldGuide",
  80. "FieldWork",
  81. "Friend",
  82. "Guide",
  83. "InstanceZones",
  84. "League",
  85. "Loading",
  86. "LuckyBox",
  87. "Mail",
  88. "Main",
  89. "MatchingCompetition",
  90. "MiniGame",
  91. "NewYearLogin",
  92. "NewYearRedEnvelope",
  93. "Notice",
  94. "OpenServerActivity",
  95. "Poem",
  96. "PopWindow",
  97. "RoleInfo",
  98. "RoleLvUp",
  99. "Share",
  100. "Store",
  101. "Studio",
  102. "Task",
  103. "TimeTracing",
  104. "Travel",
  105. "TurnTable",
  106. "XiuFang"
  107. };
  108. _totalPackagesToLoad = packagePaths.Length;
  109. foreach (var package in packagePaths)
  110. {
  111. string path = ResPathUtil.GetUIPackagePath(package);
  112. GFGUIPackage.AddPackage(path, () =>
  113. {
  114. _packagesLoaded++;
  115. if (_packagesLoaded == _totalPackagesToLoad)
  116. {
  117. FinalizeInit();
  118. }
  119. },
  120. (error) => { _onPackageError?.Invoke(error); });
  121. }
  122. }
  123. private static void FinalizeInit()
  124. {
  125. UIConfig.buttonSound = (NAudioClip)UIPackage.GetItemAsset("Common", "click");
  126. UIConfig.defaultFont = "FZKTJW--GB1-0";
  127. UIConfig.bringWindowToFrontOnClick = false;
  128. _viewDic = new Dictionary<string, IUIView>();
  129. _viewStack = new List<ViewStructure>();
  130. //初始化视图层容器
  131. _bottomLayer = CreateLayer("BottomLayer");
  132. _topLayer = CreateLayer("TopLayer");
  133. _topLayer.sortingOrder = ConstViewLayerSortingOrder.TOP;
  134. _guideLayer = CreateLayer("GuideLayer");
  135. _guideLayer.sortingOrder = ConstViewLayerSortingOrder.Guide;
  136. _modalLayer = CreateLayer("ModalLayer");
  137. _modalLayer.sortingOrder = ConstViewLayerSortingOrder.Modal;
  138. _alertLayer = CreateLayer("AlertLayer");
  139. _alertLayer.sortingOrder = ConstViewLayerSortingOrder.Alert;
  140. //debug层
  141. _debugLayer = CreateLayer("DebugLayer");
  142. _debugLayer.sortingOrder = ConstViewLayerSortingOrder.Debug;
  143. _floatLayer = CreateLayer("FloatLayer");
  144. _floatLayer.sortingOrder = ConstViewLayerSortingOrder.Float;
  145. SetMaskAlpha(0.6f);
  146. _onAllPackagesLoaded?.Invoke();
  147. }
  148. public static void AddChildToBottomLayer(GObject gObject)
  149. {
  150. _bottomLayer.AddChild(gObject);
  151. }
  152. public static void AddChildToTopLayer(GObject gObject)
  153. {
  154. _topLayer.AddChild(gObject);
  155. }
  156. public static void AddChildToGuideLayer(GObject gObject)
  157. {
  158. _guideLayer.AddChild(gObject);
  159. }
  160. public static void AddChildToModalLayer(GObject gObject)
  161. {
  162. _modalLayer.AddChild(gObject);
  163. }
  164. public static void AddChildToAlertLayer(GObject gObject)
  165. {
  166. _alertLayer.AddChild(gObject);
  167. }
  168. public static void AddChildToDebugLayer(GObject gObject)
  169. {
  170. _debugLayer.AddChild(gObject);
  171. }
  172. public static void AddChildToFloatLayer(GObject gObject)
  173. {
  174. _floatLayer.AddChild(gObject);
  175. }
  176. public static float ViewWidth
  177. {
  178. get
  179. {
  180. //这里做了最大宽度适配
  181. float maxAspectRatio = 1080 * 1.0f / 1920;
  182. if (Screen.width * 1.0f / Screen.height > maxAspectRatio)
  183. {
  184. return GRoot.inst.height * maxAspectRatio;
  185. }
  186. return GRoot.inst.width;
  187. }
  188. }
  189. /// <summary>
  190. /// 显示一个视图
  191. /// </summary>
  192. /// <param name="viewName">要显示的视图名称</param>
  193. /// <param name="viewData">要传递给视图的参数</param>
  194. /// <param name="goBackParams">从该视图返回的视图信息</param>
  195. /// <param name="hideOthers">是否关闭其他视图</param>
  196. /// <param name="backRefresh">返回上一个界面的时候,上一个界面是否需要刷新界面</param>
  197. public static bool Show(string fullViewName, object viewData = null, bool hideOthers = false,
  198. bool backRefresh = true, bool isHideToShow = false)
  199. {
  200. string name = GetName(fullViewName);
  201. if (!GameGlobal.skipCheckOpen && !FunctionOpenDataManager.Instance.CheckIsFunOpenById(name))
  202. {
  203. return false;
  204. }
  205. if (hideOthers)
  206. {
  207. HideAllView(name);
  208. }
  209. IUIView obj = null;
  210. if (_viewDic.ContainsKey(name))
  211. {
  212. obj = _viewDic[name];
  213. }
  214. else
  215. {
  216. obj = CreateViewInstance(fullViewName) as IUIView;
  217. obj.viewName = name;
  218. _viewDic.Add(name, obj);
  219. }
  220. if (obj != null)
  221. {
  222. IUIView view = (IUIView)obj;
  223. view.viewData = viewData;
  224. if (!view.isShowing)
  225. {
  226. if (isHideToShow && _viewStack.Count > 0)
  227. {
  228. view.backRefresh = _viewStack[_viewStack.Count - 1].backRefresh;
  229. _viewStack[_viewStack.Count - 1].iUIView = obj;
  230. }
  231. else
  232. view.backRefresh = true;
  233. view.Show();
  234. }
  235. else
  236. {
  237. view.Refresh();
  238. }
  239. LogUtil.LogDev("当前打开:" + name);
  240. }
  241. if (name == "MainUIView")
  242. {
  243. _viewStack.Clear();
  244. }
  245. //判断是否需要保存界面数据, 会帮助关闭上一个保存界面
  246. if (obj.isReturnView && (_viewStack.Count <= 0 ||
  247. (_viewStack.Count > 0 && _viewStack[_viewStack.Count - 1].name != name)))
  248. {
  249. //保存上一个界面是否需要返回刷新
  250. if (!isHideToShow && _viewStack.Count > 1)
  251. _viewStack[_viewStack.Count - 1].backRefresh = backRefresh;
  252. ViewStructure viewStructure = new ViewStructure();
  253. viewStructure.name = name;
  254. viewStructure.viewData = viewData;
  255. viewStructure.iUIView = obj;
  256. _viewStack.Add(viewStructure);
  257. if (_viewStack.Count > 1 && !hideOthers)
  258. {
  259. if (_viewStack[_viewStack.Count - 2].smallWindow == null)
  260. _viewStack[_viewStack.Count - 2].smallWindow = new List<string>();
  261. _viewStack[_viewStack.Count - 2].smallWindow.Clear();
  262. //把开着的小弹窗存起来
  263. foreach (var objName in _viewDic.Keys)
  264. {
  265. IUIView view = (IUIView)_viewDic[objName];
  266. if (view.isReturnWindow)
  267. {
  268. if (view.isShowing)
  269. {
  270. _viewStack[_viewStack.Count - 2].smallWindow.Add(objName);
  271. view.Hide();
  272. }
  273. }
  274. }
  275. _viewStack[_viewStack.Count - 2].iUIView.Hide();
  276. }
  277. }
  278. return true;
  279. }
  280. //
  281. /// <summary>
  282. /// 界面可返回栈里的跳转
  283. /// </summary>
  284. /// <param name="viewName">跳转到界面缓存栈里的某个界面,使用这个参数时写在打开下一个界面后</param>
  285. /// <param name="count">删除队列中的倒数几个,较灵活应对更多种情况,可自由控制</param>
  286. public static void DeleteViewStackCountDown(string viewName, int count = 0)
  287. {
  288. if (viewName != null && viewName != "")
  289. {
  290. for (int i = _viewStack.Count - 2; i > 0; i--)
  291. {
  292. ViewStructure viewStructure = _viewStack[i];
  293. if (viewStructure.name == viewName)
  294. break;
  295. _viewStack.RemoveAt(i);
  296. }
  297. return;
  298. }
  299. for (int i = 0; i < count; i++)
  300. {
  301. if (_viewStack.Count <= 1)
  302. break;
  303. _viewStack.RemoveAt(_viewStack.Count - 1);
  304. }
  305. }
  306. public static bool isViewOpen(string fullViewName)
  307. {
  308. string name = GetName(fullViewName);
  309. IUIView obj = null;
  310. if (_viewDic.ContainsKey(name))
  311. {
  312. obj = _viewDic[name];
  313. if (obj != null)
  314. {
  315. IUIView view = (IUIView)obj;
  316. if (view.isShowing) return true;
  317. }
  318. }
  319. return false;
  320. }
  321. public static bool Show<T>(object viewData = null, bool hideOthers = false, bool backRefresh = true)
  322. where T : class, new()
  323. {
  324. // string[] names = typeof(T).FullName.Split('.');
  325. // string viewName = names[names.Length - 1];
  326. //string name = GetName(typeof(T).FullName);
  327. return ViewManager.Show(typeof(T).FullName, viewData, hideOthers, backRefresh);
  328. }
  329. public static void HideWin(string viewName)
  330. {
  331. if (_nowHideOthers)
  332. return;
  333. if (_viewStack.Count >= 1)
  334. {
  335. bool hasShowingView = false;
  336. bool needShowNextView = false;
  337. bool backRefresh = true;
  338. foreach (var info in _viewDic.Keys)
  339. {
  340. IUIView objIsShowing = _viewDic[info];
  341. if (objIsShowing != null && objIsShowing.isShowing)
  342. {
  343. hasShowingView = true;
  344. break;
  345. }
  346. }
  347. ViewStructure viewStructure = _viewStack[_viewStack.Count - 1];
  348. if (_viewStack.Count == 1)
  349. {
  350. //没有界面显示了,栈被清除剩1个的时候,做保底
  351. if (!hasShowingView)
  352. needShowNextView = true;
  353. }
  354. else
  355. {
  356. if (!hasShowingView || (viewStructure.iUIView.isReturnView && viewStructure.name == viewName))
  357. {
  358. //关闭自己,在队列里去除
  359. if (viewStructure.iUIView.isReturnView && viewStructure.name == viewName)
  360. {
  361. backRefresh = viewStructure.backRefresh;
  362. _viewStack.RemoveAt(_viewStack.Count - 1);
  363. }
  364. if (_viewStack.Count >= 1)
  365. needShowNextView = true;
  366. }
  367. }
  368. if (needShowNextView)
  369. {
  370. viewStructure = _viewStack[_viewStack.Count - 1];
  371. ViewManager.Show($"GFGGame.{viewStructure.name}", viewStructure.viewData, false, backRefresh, true);
  372. //重新打开小弹窗
  373. if (viewStructure.smallWindow != null)
  374. {
  375. foreach (var objName in viewStructure.smallWindow)
  376. {
  377. ViewManager.Show($"GFGGame.{objName}");
  378. }
  379. }
  380. //foreach (var objName in _viewDic.Keys)
  381. //{
  382. // if (objName != viewStructure.name)
  383. // {
  384. // IUIView view = (IUIView)_viewDic[objName];
  385. // if (view.isShowing)
  386. // view.Show();
  387. // }
  388. //}
  389. }
  390. }
  391. }
  392. public static void Hide(string fullViewName)
  393. {
  394. string name = GetName(fullViewName);
  395. if (!_viewDic.ContainsKey(name))
  396. {
  397. return;
  398. }
  399. object obj = _viewDic[name];
  400. if (obj != null)
  401. {
  402. IUIView view = (IUIView)obj;
  403. view.Hide();
  404. LogUtil.LogDev("当前关闭:" + name);
  405. }
  406. }
  407. public static void Hide<T>()
  408. {
  409. //string name = GetName(typeof(T).FullName);
  410. Hide(typeof(T).FullName);
  411. }
  412. public static void GoBackFrom(string fullViewName, bool hideOther = true)
  413. {
  414. string name = GetName(fullViewName);
  415. ViewManager.Hide(name);
  416. foreach (var info in _viewDic.Keys)
  417. {
  418. IUIView objIsShowing = _viewDic[info];
  419. if (objIsShowing != null && objIsShowing.isShowing)
  420. {
  421. return;
  422. }
  423. }
  424. MainDataManager.Instance.ViewType = 0;
  425. ViewManager.Show<MainUIView>(null, true);
  426. }
  427. public static object[] GetGoBackDatas(string fullViewName)
  428. {
  429. //string name = GetName(fullViewName);
  430. object[] value = null;
  431. //if (_goBackDatas.ContainsKey(name) && _goBackDatas[name].Count > 0)
  432. //{
  433. // value = _goBackDatas[name][_goBackDatas[name].Count - 1];
  434. //}
  435. return value;
  436. }
  437. public static IUIView GetUIView(string viewName)
  438. {
  439. if (_viewDic.ContainsKey(viewName))
  440. {
  441. IUIView obj = _viewDic[viewName];
  442. if (obj != null && obj.isShowing)
  443. {
  444. return obj as IUIView;
  445. }
  446. }
  447. return null;
  448. }
  449. public static void ClearUIView(string viewName)
  450. {
  451. if (!string.IsNullOrEmpty(viewName) && _viewDic.ContainsKey(viewName))
  452. {
  453. if (_viewDic[viewName] != null && !_viewDic[viewName].isShowing)
  454. {
  455. // _viewDic[viewName] = null;
  456. _viewDic.Remove(viewName);
  457. }
  458. }
  459. }
  460. public static void HideAllView(string excludeViewName = null)
  461. {
  462. for (int i = _viewDic.Keys.Count - 1; i >= 0; i--) //不用foreach是因为:循环过程中可能会触发dispose,导致_viewDic.Keys变化,最终报错
  463. {
  464. int index = i > _viewDic.Keys.Count - 1
  465. ? _viewDic.Keys.Count - 1
  466. : i; //直接去最后一个,不用i是因为关闭一个界面可能会连带关闭其他界面,最终i比_viewDic.Keys.Count大而报错
  467. KeyValuePair<string, IUIView> kv = _viewDic.ElementAt(index);
  468. if (kv.Key != excludeViewName)
  469. {
  470. if (kv.Key == typeof(FunctionOpenView).Name) continue; //功能开启界面不能强制关闭
  471. _nowHideOthers = true;
  472. Hide(kv.Key);
  473. }
  474. }
  475. _nowHideOthers = false;
  476. // _viewDic.Clear();
  477. // foreach (string viewName in _viewDic.Keys)
  478. // {
  479. // if (viewName != excludeViewName)
  480. // {
  481. // if (viewName == typeof(FunctionOpenView).Name) continue;//功能开启界面不能强制关闭
  482. // Hide(viewName);
  483. // }
  484. // }
  485. }
  486. public static void CheckDispose()
  487. {
  488. for (int i = _viewDic.Keys.Count - 1; i >= 0; i--) //不用foreach是因为:循环过程中可能会触发dispose,导致_viewDic.Keys变化,最终报错
  489. {
  490. int index = i > _viewDic.Keys.Count - 1
  491. ? _viewDic.Keys.Count - 1
  492. : i; //直接去最后一个,不用i是因为关闭一个界面可能会连带关闭其他界面,最终i比_viewDic.Keys.Count大而报错
  493. KeyValuePair<string, IUIView> kv = _viewDic.ElementAt(index);
  494. if (kv.Value.isShowing == true) continue;
  495. // if (kv.Value.packageName == ResPathUtil.GetUIPackagePath("CommonGame") || kv.Value.packageName == ResPathUtil.GetUIPackagePath("Common") || kv.Value.packageName == ResPathUtil.GetUIPackagePath("Main")) return;//这几个包不释放
  496. if (_viewDic.Keys.Count <= 10) return; //打开界面小于10个就不销毁了
  497. long currentTime = TimeHelper.ClientNowSeconds();
  498. long closeTime = kv.Value.closeTime;
  499. if (closeTime > 0 && currentTime - closeTime >= TimeUtil.SECOND_PER_MUNITE * 1)
  500. {
  501. kv.Value.closeTime = 0;
  502. kv.Value.Dispose();
  503. }
  504. }
  505. }
  506. private static object CreateViewInstance(string name)
  507. {
  508. //LogUtil.LogFormatDev("CreateViewInstance {0}", name);
  509. Type type = Type.GetType(name);
  510. if (type != null)
  511. {
  512. return Activator.CreateInstance(type);
  513. }
  514. return null;
  515. }
  516. private static GComponent CreateLayer(string name)
  517. {
  518. GComponent layer = new GComponent();
  519. layer.name = name;
  520. GRoot.inst.AddChild(layer);
  521. layer.SetSize(GRoot.inst.size.x, GRoot.inst.size.y);
  522. layer.AddRelation(GRoot.inst, RelationType.Size);
  523. return layer;
  524. }
  525. public static bool CheckIsTopView(GComponent viewCom)
  526. {
  527. if (ViewManager.isViewOpen(typeof(GuideView).Name)) return false;
  528. if (viewCom.parent != null)
  529. {
  530. int index = viewCom.parent.GetChildIndex(viewCom);
  531. if (index == viewCom.parent.numChildren - 1 && GRoot.inst.GetTopWindow() == null)
  532. {
  533. return true;
  534. }
  535. }
  536. if (GRoot.inst.GetTopWindow() == viewCom)
  537. {
  538. return true;
  539. }
  540. return false;
  541. }
  542. public static string GetName(string fullName)
  543. {
  544. string[] names = fullName.Split('.');
  545. string name = names[names.Length - 1];
  546. return name;
  547. }
  548. public static void SetMaskAlpha(float alpha)
  549. {
  550. GRoot.inst.modalLayer.alpha = alpha;
  551. }
  552. /// <summary>
  553. /// 任务界面跳转
  554. /// </summary>
  555. /// <param name="jumpId"></param>
  556. public static void JumpToView(string jumpId, object[] param, bool hideOther = false, bool backRefresh = true,
  557. Action onSuccess = null)
  558. {
  559. switch (jumpId)
  560. {
  561. case nameof(LeagueAnswerView):
  562. if (LeagueDataManager.Instance.Type == LeagueJoinType.Join)
  563. {
  564. ViewManager.Show<LeagueView>(null, hideOther, backRefresh);
  565. ViewManager.Show($"GFGGame.{jumpId}");
  566. }
  567. else
  568. {
  569. if (!FunctionOpenDataManager.Instance.CheckIsFunOpenById(nameof(LeagueView))) return;
  570. ViewManager.Show<LeagueJoinView>(null, hideOther, backRefresh);
  571. }
  572. break;
  573. case nameof(LeagueView):
  574. if (!FunctionOpenDataManager.Instance.CheckIsFunOpenById(nameof(LeagueView))) return;
  575. if (LeagueDataManager.Instance.Type == LeagueJoinType.Join)
  576. {
  577. ViewManager.Show<LeagueView>(null, hideOther, backRefresh);
  578. }
  579. else
  580. {
  581. ViewManager.Show<LeagueJoinView>(null, hideOther, backRefresh);
  582. }
  583. break;
  584. case nameof(StoreView):
  585. ViewManager.Show<StoreView>(param, hideOther, backRefresh);
  586. break;
  587. case nameof(StoryChapterListView):
  588. ViewManager.Show($"GFGGame.{jumpId}", param, hideOther, backRefresh);
  589. break;
  590. case nameof(StoryChapterView):
  591. ViewManager.Show<StoryChapterView>(param[0], hideOther, backRefresh);
  592. break;
  593. case nameof(FirstChargeBonusView):
  594. ViewManager.Show<FirstChargeBonusView>(param, false, backRefresh);
  595. break;
  596. case nameof(ClothingSyntheticView):
  597. ViewManager.Show<ClothingSyntheticView>(param, hideOther, backRefresh);
  598. break;
  599. case nameof(LuckyBoxView):
  600. if (param.Length > 0)
  601. ViewManager.Show<LuckyBoxView>(param[0], hideOther, backRefresh);
  602. else
  603. ViewManager.Show<LuckyBoxView>(null, hideOther, backRefresh);
  604. break;
  605. default:
  606. ViewManager.Show($"GFGGame.{jumpId}", null, hideOther, backRefresh);
  607. break;
  608. }
  609. onSuccess?.Invoke();
  610. }
  611. }
  612. }