UIManager.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. /***
  2. * Title: "SUIFW" UI框架项目
  3. * 主题: UI管理器
  4. * Description:
  5. * 功能:整个UI框架的核心,用户程序通过调用本类,来调用本框架的大多数功能。
  6. * 功能1:关于入“栈”与出“栈”的UI窗体4个状态的定义逻辑
  7. * 入栈状态:
  8. * Freeze(); (上一个UI窗体)冻结
  9. * Display(); (本UI窗体)显示
  10. * 出栈状态:
  11. * Hiding(); (本UI窗体) 隐藏
  12. * Redisplay(); (上一个UI窗体) 重新显示
  13. * 功能2:增加“非栈”缓存集合。
  14. */
  15. using UnityEngine;
  16. using UnityEngine.UI;
  17. using System;
  18. using System.Collections.Generic;
  19. namespace SUIFW
  20. {
  21. public class UIManager : MonoBehaviour
  22. {
  23. /* 字段 */
  24. //本类实例
  25. private static UIManager _Instance = null;
  26. //存储所有“UI窗体预设(Prefab)”路径
  27. //参数含义: 第1个string 表示“窗体预设”名称,后一个string 表示对应的路径
  28. private Dictionary<string, string> _DicUIFormsPaths;
  29. //缓存所有已经打开的“UI窗体预设(Prefab)”
  30. //参数含义: 第1个string 表示“窗体预设”名称,后一个BaseUI 表示对应的“窗体预设”
  31. private Dictionary<string, BaseUIForms> _DicALLUIForms;
  32. //“栈”结构表示的“当前UI窗体”集合。
  33. private Stack<BaseUIForms> _StaCurrentUIForms;
  34. //当前显示状态的UI窗体集合
  35. private Dictionary<string, BaseUIForms> _DicCurrentShowUIForms;
  36. //UI根节点
  37. public Transform _CanvasTransform = null;
  38. //普通全屏界面节点
  39. private Transform _CanTransformNormal = null;
  40. //固定界面节点
  41. private Transform _CanTransformFixed = null;
  42. //弹出模式节点
  43. private Transform _CanTransformPopUp = null;
  44. //UI脚本节点(加载各种管理脚本的节点)
  45. private Transform _CanTransformUIScripts = null;
  46. /// <summary>
  47. /// 得到本类实例
  48. /// </summary>
  49. /// <returns></returns>
  50. public static UIManager GetInstance()
  51. {
  52. if (_Instance == null)
  53. {
  54. _Instance = new GameObject("_UIManager").AddComponent<UIManager>();
  55. }
  56. return _Instance;
  57. }
  58. void Awake()
  59. {
  60. //字段初始化
  61. _DicUIFormsPaths = new Dictionary<string, string>();
  62. _DicALLUIForms = new Dictionary<string, BaseUIForms>();
  63. _StaCurrentUIForms = new Stack<BaseUIForms>();
  64. _DicCurrentShowUIForms = new Dictionary<string, BaseUIForms>();
  65. //初始化项目开始必须的资源加载
  66. InitRootCanvasLoading();
  67. //得到UI根节点、及其重要子节点
  68. _CanvasTransform = GameObject.FindGameObjectWithTag(SysDefine.SYS_TAG_CANVAS).transform;
  69. //得到普通全屏界面节点、固定界面节点、弹出模式节点、UI脚本节点
  70. _CanTransformNormal = UnityHelper.FindTheChild(_CanvasTransform.gameObject, SysDefine.SYS_CANVAS_NORMAL_NODE_NAME);
  71. _CanTransformFixed = UnityHelper.FindTheChild(_CanvasTransform.gameObject, SysDefine.SYS_CANVAS_FIXED_NODE_NAME);
  72. _CanTransformPopUp = UnityHelper.FindTheChild(_CanvasTransform.gameObject, SysDefine.SYS_CANVAS_POPUP_NODE_NAME);
  73. _CanTransformUIScripts = UnityHelper.FindTheChild(_CanvasTransform.gameObject, SysDefine.SYS_CANVAS_UISCRIPTS_NODE_NAME);
  74. //把本脚本实例,作为Canvas的子节点
  75. UnityHelper.AddChildToParent(_CanTransformUIScripts, this.gameObject.transform);
  76. //本UI节点信息,场景转换时,不允许销毁
  77. DontDestroyOnLoad(_CanvasTransform);
  78. //初始化“UI窗体预设”路径数据
  79. InitUIFormsPathsData();
  80. }
  81. /// <summary>
  82. /// 显示UI窗体
  83. /// </summary>
  84. /// <param name="strUIFormName">UI窗体的名称</param>
  85. public void ShowUIForms(string strUIFormName)
  86. {
  87. BaseUIForms baseUIForms; //UI窗体基类
  88. //参数检查
  89. if (string.IsNullOrEmpty(strUIFormName)) return;
  90. //加载“UI窗体名称”,到“所有UI窗体缓存”中
  91. baseUIForms = LoadUIFormsToAllUIFormsCatch(strUIFormName);
  92. if (baseUIForms == null) return;
  93. //判断是否清空“栈”结构体集合
  94. if (baseUIForms.CurrentUIType.IsClearReverseChange)
  95. {
  96. ClearStackArray();
  97. }
  98. //判断不同的窗体显示模式,分别进行处理
  99. switch (baseUIForms.CurrentUIType.UIForms_ShowMode)
  100. {
  101. case UIFormsShowMode.Normal:
  102. EnterUIFormsCache(strUIFormName);
  103. break;
  104. case UIFormsShowMode.ReverseChange:
  105. PushUIForms(strUIFormName);
  106. break;
  107. case UIFormsShowMode.HideOther:
  108. EnterUIFormstToCacheHideOther(strUIFormName);
  109. break;
  110. default:
  111. break;
  112. }
  113. }
  114. /// <summary>
  115. /// 关闭或返回上一个UI窗体(关闭当前UI窗体)
  116. /// </summary>
  117. public void CloseOrReturnUIForms(string strUIFormName)
  118. {
  119. BaseUIForms baseUIForms = null; //UI窗体基类
  120. /* 参数检查 */
  121. if (string.IsNullOrEmpty(strUIFormName)) return;
  122. //“所有UI窗体缓存”如果没有记录,则直接返回。
  123. _DicALLUIForms.TryGetValue(strUIFormName, out baseUIForms);
  124. if (baseUIForms == null) return;
  125. /* 判断不同的窗体显示模式,分别进行处理 */
  126. switch (baseUIForms.CurrentUIType.UIForms_ShowMode)
  127. {
  128. case UIFormsShowMode.Normal:
  129. ExitUIFormsCache(strUIFormName);
  130. break;
  131. case UIFormsShowMode.ReverseChange:
  132. PopUIForms();
  133. break;
  134. case UIFormsShowMode.HideOther:
  135. ExitUIFormsFromCacheAndShowOther(strUIFormName);
  136. break;
  137. default:
  138. break;
  139. }
  140. }
  141. public string GetCurrentShowUIForms()
  142. {
  143. if (_DicCurrentShowUIForms.Count == 1)
  144. {
  145. foreach (string baseUIFormsItemName in _DicCurrentShowUIForms.Keys)
  146. {
  147. return baseUIFormsItemName;
  148. }
  149. }
  150. return "";
  151. }
  152. #region 私有方法
  153. /// <summary>
  154. /// 根据指定UI窗体名称,加载到“所有UI窗体”缓存中。
  155. /// </summary>
  156. /// <param name="strUIFormName">UI窗体名称</param>
  157. /// <returns></returns>
  158. private BaseUIForms LoadUIFormsToAllUIFormsCatch(string strUIFormName)
  159. {
  160. BaseUIForms baseUI; //UI窗体
  161. //判断“UI预设缓存集合”是否有指定的UI窗体,否则新加载窗体
  162. _DicALLUIForms.TryGetValue(strUIFormName, out baseUI);
  163. if (baseUI == null)
  164. {
  165. //加载指定路径的“UI窗体”
  166. baseUI = LoadUIForms(strUIFormName);
  167. }
  168. return baseUI;
  169. }
  170. /// <summary>
  171. /// 加载UI窗体到“当前显示窗体集合”缓存中。
  172. /// </summary>
  173. /// <param name="strUIFormsName"></param>
  174. private void EnterUIFormsCache(string strUIFormsName)
  175. {
  176. BaseUIForms baseUIForms; //UI窗体基类
  177. BaseUIForms baseUIFormsFromAllCache; //"所有窗体集合"中的窗体基类
  178. //“正在显示UI窗体缓存”集合里有记录,则直接返回。
  179. _DicCurrentShowUIForms.TryGetValue(strUIFormsName, out baseUIForms);
  180. if (baseUIForms != null) return;
  181. //把当前窗体,加载到“正在显示UI窗体缓存”集合里
  182. _DicALLUIForms.TryGetValue(strUIFormsName, out baseUIFormsFromAllCache);
  183. if (baseUIFormsFromAllCache != null)
  184. {
  185. _DicCurrentShowUIForms.Add(strUIFormsName, baseUIFormsFromAllCache);
  186. baseUIFormsFromAllCache.Display();
  187. }
  188. }
  189. /// <summary>
  190. /// 卸载UI窗体从“当前显示窗体集合”缓存中。
  191. /// </summary>
  192. /// <param name="strUIFormsName"></param>
  193. private void ExitUIFormsCache(string strUIFormsName)
  194. {
  195. BaseUIForms baseUIForms; //UI窗体基类
  196. //“正在显示UI窗体缓存”集合没有记录,则直接返回。
  197. _DicCurrentShowUIForms.TryGetValue(strUIFormsName, out baseUIForms);
  198. if (baseUIForms == null) return;
  199. //指定UI窗体,运行隐藏状态,且从“正在显示UI窗体缓存”集合中移除。
  200. baseUIForms.Hiding();
  201. _DicCurrentShowUIForms.Remove(strUIFormsName);
  202. }
  203. /// <summary>
  204. /// 加载UI窗体到“当前显示窗体集合”缓存中,且隐藏其他正在显示的页面
  205. /// </summary>
  206. /// <param name="strUIFormsName"></param>
  207. private void EnterUIFormstToCacheHideOther(string strUIFormsName)
  208. {
  209. BaseUIForms baseUIForms; //UI窗体基类
  210. BaseUIForms baseUIFormsFromAllCache; //"所有窗体集合"中的窗体基类
  211. //“正在显示UI窗体缓存”集合里有记录,则直接返回。
  212. _DicCurrentShowUIForms.TryGetValue(strUIFormsName, out baseUIForms);
  213. if (baseUIForms != null) return;
  214. //“正在显示UI窗体缓存”与“栈缓存”集合里所有窗体进行隐藏处理。
  215. foreach (BaseUIForms baseUIFormsItem in _DicCurrentShowUIForms.Values)
  216. {
  217. baseUIFormsItem.Hiding();
  218. }
  219. foreach (BaseUIForms basUIFormsItem in _StaCurrentUIForms)
  220. {
  221. basUIFormsItem.Hiding();
  222. }
  223. //把当前窗体,加载到“正在显示UI窗体缓存”集合里
  224. _DicALLUIForms.TryGetValue(strUIFormsName, out baseUIFormsFromAllCache);
  225. if (baseUIFormsFromAllCache != null)
  226. {
  227. _DicCurrentShowUIForms.Add(strUIFormsName, baseUIFormsFromAllCache);
  228. baseUIFormsFromAllCache.Display();
  229. }
  230. }
  231. /// <summary>
  232. /// 卸载UI窗体从“当前显示窗体集合”缓存中,且显示其他原本需要显示的页面
  233. /// </summary>
  234. /// <param name="strUIFormsName"></param>
  235. private void ExitUIFormsFromCacheAndShowOther(string strUIFormsName)
  236. {
  237. BaseUIForms baseUIForms; //UI窗体基类
  238. //“正在显示UI窗体缓存”集合没有记录,则直接返回。
  239. _DicCurrentShowUIForms.TryGetValue(strUIFormsName, out baseUIForms);
  240. if (baseUIForms == null) return;
  241. //指定UI窗体,运行隐藏状态,且从“正在显示UI窗体缓存”集合中移除。
  242. baseUIForms.Hiding();
  243. _DicCurrentShowUIForms.Remove(strUIFormsName);
  244. //“正在显示UI窗体缓存”与“栈缓存”集合里所有窗体进行再次显示处理。
  245. foreach (BaseUIForms baseUIFormsItem in _DicCurrentShowUIForms.Values)
  246. {
  247. baseUIFormsItem.Redisplay();
  248. }
  249. foreach (BaseUIForms basUIFormsItem in _StaCurrentUIForms)
  250. {
  251. basUIFormsItem.Redisplay();
  252. }
  253. }
  254. /// <summary>
  255. /// UI窗体入栈
  256. /// 功能1: 判断栈里是否已经有窗体,有则“冻结”
  257. /// 2: 先判断“UI预设缓存集合”是否有指定的UI窗体,有则处理。
  258. /// 3: 指定UI窗体入"栈"
  259. /// </summary>
  260. /// <param name="strUIFormsName"></param>
  261. private void PushUIForms(string strUIFormsName)
  262. {
  263. BaseUIForms baseUI; //UI预设窗体
  264. //判断栈里是否已经有窗体,有则“冻结”
  265. if (_StaCurrentUIForms.Count > 0)
  266. {
  267. BaseUIForms topUIForms = _StaCurrentUIForms.Peek();
  268. topUIForms.Freeze();
  269. }
  270. //先判断“UI预设缓存集合”是否有指定的UI窗体,有则处理。
  271. _DicALLUIForms.TryGetValue(strUIFormsName, out baseUI);
  272. if (baseUI != null)
  273. {
  274. baseUI.Display();
  275. }
  276. else
  277. {
  278. Log.Write(GetType() + string.Format("/PushUIForms()/ baseUI==null! 核心错误,请检查 strUIFormsName={0} ", strUIFormsName), Log.Level.High);
  279. }
  280. //指定UI窗体入"栈"
  281. _StaCurrentUIForms.Push(baseUI);
  282. }
  283. /// <summary>
  284. /// UI窗体出栈逻辑
  285. /// </summary>
  286. private void PopUIForms()
  287. {
  288. if (_StaCurrentUIForms.Count >= 2)
  289. {
  290. /* 出栈逻辑 */
  291. BaseUIForms topUIForms = _StaCurrentUIForms.Pop();
  292. //出栈的窗体,进行隐藏处理
  293. topUIForms.Hiding();
  294. //出栈窗体的下一个窗体逻辑
  295. BaseUIForms nextUIForms = _StaCurrentUIForms.Peek();
  296. //下一个窗体"重新显示"处理
  297. nextUIForms.Redisplay();
  298. }
  299. else if (_StaCurrentUIForms.Count == 1)
  300. {
  301. /* 出栈逻辑 */
  302. BaseUIForms topUIForms = _StaCurrentUIForms.Pop();
  303. //出栈的窗体,进行"隐藏"处理
  304. topUIForms.Hiding();
  305. }
  306. }
  307. /// <summary>
  308. /// 加载与显示UI窗体
  309. /// 功能:
  310. /// 1:根据“UI窗体预设”名称,加载预设克隆体。
  311. /// 2:预设克隆体添加UI“根节点”为父节点。
  312. /// 3:隐藏刚创建的UI克隆体。
  313. /// 4:新创建的“UI窗体”,加入“UI窗体缓存”中
  314. /// </summary>
  315. private BaseUIForms LoadUIForms(string strUIFormsName)
  316. {
  317. string strUIFormsPaths = null; //UI窗体的路径
  318. GameObject goCloneUIPrefab = null; //克隆的"窗体预设"
  319. BaseUIForms baseUIForm; //UI窗体
  320. //得到UI窗体的路径
  321. _DicUIFormsPaths.TryGetValue(strUIFormsName, out strUIFormsPaths);
  322. //加载指定路径的“UI窗体”
  323. if (!string.IsNullOrEmpty(strUIFormsPaths))
  324. {
  325. goCloneUIPrefab = ResourcesMgr.GetInstance().LoadAsset(strUIFormsPaths, false);
  326. }
  327. //设置“UI窗体”克隆体的父节点,以及隐藏处理与加入“UI窗体缓存”中
  328. if (_CanvasTransform != null && goCloneUIPrefab != null)
  329. {
  330. baseUIForm = goCloneUIPrefab.GetComponent<BaseUIForms>();
  331. if (baseUIForm == null)
  332. {
  333. Log.Write(GetType() + string.Format("/LoadUIForms()/ baseUIForm==null!,请先确认克隆对象上是否加载了BaseUIForms的子类。参数 strUIFormsName='{0}' ", strUIFormsName), Log.Level.High);
  334. return null;
  335. }
  336. switch (baseUIForm.CurrentUIType.UIForms_Type)
  337. {
  338. case UIFormsType.Normal:
  339. goCloneUIPrefab.transform.SetParent(_CanTransformNormal, false);
  340. break;
  341. case UIFormsType.Fixed:
  342. goCloneUIPrefab.transform.SetParent(_CanTransformFixed, false);
  343. break;
  344. case UIFormsType.PopUp:
  345. goCloneUIPrefab.transform.SetParent(_CanTransformPopUp, false);
  346. break;
  347. default:
  348. break;
  349. }
  350. goCloneUIPrefab.SetActive(false);
  351. //新创建的“UI窗体”,加入“UI窗体缓存”中
  352. _DicALLUIForms.Add(strUIFormsName, baseUIForm);
  353. return baseUIForm;
  354. }
  355. else
  356. {
  357. Log.Write(GetType() + string.Format("/LoadUIForms()/‘_CanvasTransform’ Or ‘goCloneUIPrefab’==NULL! , 方法参数 strUIFormsName={0},请检查!", strUIFormsName), Log.Level.High);
  358. }
  359. Log.Write(GetType() + string.Format("/LoadUIForms()/ 出现不可预知错误,请检查! 方法参数 strUIFormsName={0} ", strUIFormsName), Log.Level.High);
  360. return null;
  361. }
  362. /// <summary>
  363. /// 初始化项目开始必须的资源加载
  364. /// </summary>
  365. private void InitRootCanvasLoading()
  366. {
  367. if (UnityHelper.isFirstLoad)
  368. {
  369. ResourcesMgr.GetInstance().LoadAsset("UIPrefabs/Canvas", false);
  370. }
  371. }
  372. /// <summary>
  373. /// 初始化“UI窗体预设”路径数据
  374. /// </summary>
  375. private void InitUIFormsPathsData()
  376. {
  377. //测试也成功
  378. //IConfigManager configMgr = new ConfigManagerByJson(SysDefine.SYS_PATH_UIFormConfigJson);
  379. //if (_DicUIFormsPaths != null)
  380. //{
  381. // _DicUIFormsPaths = configMgr.AppSetting;
  382. //}
  383. if (_DicUIFormsPaths != null)
  384. {
  385. _DicUIFormsPaths.Add("StarAppForms", "UIPrefabs/StarAppForms");
  386. _DicUIFormsPaths.Add("LoginForms", "UIPrefabs/LoginForms");
  387. _DicUIFormsPaths.Add("PhoneLoginForms", "UIPrefabs/PhoneLoginForms");
  388. _DicUIFormsPaths.Add("MainPanelForms", "UIPrefabs/MainPanelForms");
  389. _DicUIFormsPaths.Add("CreatRoomForms", "UIPrefabs/CreatRoomForms");
  390. _DicUIFormsPaths.Add("JoinRoomForms", "UIPrefabs/JoinRoomForms");
  391. _DicUIFormsPaths.Add("RoomMainForms", "UIPrefabs/RoomMainForms");
  392. _DicUIFormsPaths.Add("SystemSettingForms", "UIPrefabs/SystemSettingForms");
  393. _DicUIFormsPaths.Add("MyCenterForms", "UIPrefabs/MyCenterForms");
  394. _DicUIFormsPaths.Add("ListenForms", "UIPrefabs/ListenForms");
  395. _DicUIFormsPaths.Add("PopForms", "UIPrefabs/PopForms");
  396. }
  397. }
  398. /// <summary>
  399. /// 清空“栈”结构体集合
  400. /// </summary>
  401. /// <returns></returns>
  402. private bool ClearStackArray()
  403. {
  404. if (_StaCurrentUIForms != null && _StaCurrentUIForms.Count >= 1)
  405. {
  406. _StaCurrentUIForms.Clear();
  407. return true;
  408. }
  409. return false;
  410. }
  411. #endregion
  412. #region 测试方法
  413. //测试核心集合中数量
  414. public void Test_DisplayArrayCount()
  415. {
  416. if (_DicALLUIForms != null)
  417. {
  418. Log.Write(GetType() + "/Test_DisplayArrayCount()/_DicALLUIForms.count=" + _DicALLUIForms.Count);
  419. }
  420. if (_DicCurrentShowUIForms != null)
  421. {
  422. Log.Write(GetType() + "/Test_DisplayArrayCount()/_DicCurrentShowUIForms.count=" + _DicCurrentShowUIForms.Count);
  423. }
  424. if (_StaCurrentUIForms != null)
  425. {
  426. Log.Write(GetType() + "/Test_DisplayArrayCount()/_StaCurrentUIForms.count=" + _StaCurrentUIForms.Count);
  427. }
  428. }
  429. #endregion
  430. }//Class_end
  431. }