目錄
- UI框架介紹
- 保存面板信息
- 解析面板信息,開發(fā)配套數(shù)據(jù)模型
- 開發(fā)公共面板類BasePanel
- 開發(fā)UIManager核心管理類
- 開發(fā)菜單面板類和背包類使用UIManager
- 結(jié)束
一,UI框架介紹
為什么要使用UI框架
我們在開發(fā)項(xiàng)目中會有許多面板后德,比如背包面板,技能面板脐往,設(shè)置面板等新博。如此多的面板我們不好統(tǒng)一進(jìn)行管理语稠,當(dāng)需求發(fā)生更變我們需要快速的做出調(diào)整漆弄,UI框架就很好的能改善這一點(diǎn)睦裳,并且使代碼結(jié)構(gòu)更加清晰。
UI框架如何管理
UI框架通過核心類UIManager 1. 解析本地文檔 2. 用棧統(tǒng)一控制面板的顯示和隱藏撼唾。
UI框架UML架構(gòu)圖
UI框架.png
二廉邑, 保存面板信息
1. 將面板做成預(yù)制體保存在本地Resources文件夾下
預(yù)制體.png
2. 將面板類型及路徑寫入Json文件
{
"infoList":
[
{"panelTypeString":"ItemMessage",
"path":"UIPanel/ItemMessagePanel"},
{"panelTypeString":"Knapsack",
"path":"UIPanel/KnapsackPanel"},
{"panelTypeString":"MainMenu",
"path":"UIPanel/MainMenuPanel"},
{"panelTypeString":"Shop",
"path":"UIPanel/ShopPanel"},
{"panelTypeString":"Skill",
"path":"UIPanel/SkillPanel"},
{"panelTypeString":"System",
"path":"UIPanel/SystemPanel"},
{"panelTypeString":"Task",
"path":"UIPanel/TaskPanel"}
]
}
三, 解析面板信息倒谷,開發(fā)配套數(shù)據(jù)模型
通過上面操作我們已經(jīng)將我們的面板保存到本地了蛛蒙,當(dāng)我們使用的時候只需要解析本地文件并做數(shù)據(jù)存儲即可。
- 準(zhǔn)備我們的數(shù)據(jù)模型類UIPanelInfo,一定要標(biāo)注可序列化特性哦渤愁。
[Serializable]
public class UIPanelInfo : ISerializationCallbackReceiver
{
[NonSerialized]
//面板類型
public UIPanelType panelType;
public string panelTypeString;
//面板路徑
public string path;
//字符串轉(zhuǎn)化枚舉類型
public void OnAfterDeserialize()
{
UIPanelType type = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), panelTypeString);
panelType = type;
}
public void OnBeforeSerialize()
{
}
}
- 解析本地文件牵祟,并存入字典方便加載,這里我將其寫入核心類UIManager中抖格。
[Serializable]
class UIPanelTypeJson
{
public List<UIPanelInfo> infoList;
}
//解析Json
private void ParseUIPanelTypeJson()
{
panelPathDict = new Dictionary<UIPanelType, string>();
TextAsset ta = Resources.Load<TextAsset>("UIPanelType");
UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(ta.text);
foreach (UIPanelInfo info in jsonObject.infoList)
{
//Debug.Log(info.panelType);
panelPathDict.Add(info.panelType, info.path);
}
}
小提示:在Unity 5.3中Unity開放了一個JsonUnility序列化類詳情請自查API诺苹。
作用: 1. 目前支持Json轉(zhuǎn)化為對象咕晋。
2. 對象轉(zhuǎn)化為Json格式字符。
四筝尾,開發(fā)公共面板類BasePanel
所有面板都有界面的顯示,暫停办桨。像我們的菜單面板還需要有暫停和繼續(xù)筹淫,當(dāng)其他面板顯示我們可以防止用戶與其他面板繼續(xù)交互。當(dāng)當(dāng)前面板處于隱藏我們才允許菜單面板與用戶繼續(xù)交互呢撞。所以我們將面板都具有的共性做成一個公共的基類损姜。
public class BasePanel : MonoBehaviour
{
/// <summary>
/// 界面被顯示出來
/// </summary>
public virtual void OnEnter()
{
}
/// <summary>
/// 界面暫停
/// </summary>
public virtual void OnPause()
{
}
/// <summary>
/// 界面繼續(xù)
/// </summary>
public virtual void OnResume()
{
}
/// <summary>
/// 界面不顯示,退出這個界面,界面被關(guān)閉
/// </summary>
public virtual void OnExit()
{
}
}
五殊霞,開發(fā)UIManager核心管理類
當(dāng)你看到這里摧阅,恭喜你到了最核心的一部分了。
- 擴(kuò)展Dictionary類獲取Value绷蹲,如果取不到則返回空棒卷。
- 準(zhǔn)備一個字典成員用來存儲路徑和面板實(shí)例,方便獲取面板祝钢。
- 準(zhǔn)備一個數(shù)據(jù)結(jié)構(gòu)棻裙妫控制面板的顯示和隱藏。
- 書寫實(shí)例化面板邏輯的成員函數(shù)拦英。
定義一個根據(jù)面板類型得到實(shí)例化面板
/// <summary>
/// 根據(jù)面板類型 得到實(shí)例化的面板
/// </summary>
/// <returns></returns>
private BasePanel GetPanel(UIPanelType panelType)
{
if (panelDict == null)
{
panelDict = new Dictionary<UIPanelType, BasePanel>();
}
BasePanel panel = panelDict.TryGet(panelType);
if (panel == null)
{
//如果找不到蜒什,那么就找這個面板的prefab的路徑,然后去根據(jù)prefab去實(shí)例化面板
string path = panelPathDict.TryGet(panelType);
GameObject instPanel = GameObject.Instantiate(Resources.Load(path)) as GameObject;
instPanel.transform.SetParent(CanvasTransform, false);
panelDict.Add(panelType, instPanel.GetComponent<BasePanel>());
return instPanel.GetComponent<BasePanel>();
}
else
{
return panel;
}
}
將頁面入棧疤估,顯示面板
/// <summary>
/// 把某個頁面入棧灾常, 把某個頁面顯示在界面上
/// </summary>
public void PushPanel(UIPanelType panelType)
{
if (panelStack == null)
panelStack = new Stack<BasePanel>();
//判斷一下棧里面是否有頁面
if (panelStack.Count > 0)
{
BasePanel topPanel = panelStack.Peek();
topPanel.OnPause();
}
BasePanel panel = GetPanel(panelType);
Debug.Log(panel == null);
panel.OnEnter();
panelStack.Push(panel);
}
出棧,隱藏面板
/// <summary>
/// 出棧 铃拇,把頁面從界面上移除
/// </summary>
public void PopPanel()
{
if (panelStack == null)
panelStack = new Stack<BasePanel>();
if (panelStack.Count <= 0) return;
//關(guān)閉棧頂頁面的顯示
BasePanel topPanel = panelStack.Pop();
topPanel.OnExit();
if (panelStack.Count <= 0) return;
BasePanel topPanel2 = panelStack.Peek();
topPanel2.OnResume();
}
六钞瀑,開發(fā)菜單面板類和背包類使用UIManager
上面所述我們已經(jīng)完成大部分UI框架的核心架構(gòu)了,接下來根據(jù)個人項(xiàng)目來使用該框架慷荔,這里我將舉個例子來使用UI框架仔戈。
開發(fā)菜單面板類
我們先將我們的面板繼承公共基類BasePanel,其次這里我將介紹在菜單面板類重寫暫停拧廊,重啟监徘,以及Button監(jiān)聽事件邏輯。
/// <summary>
/// 界面暫停
/// </summary>
public override void OnPause()
{
canvasGroup.blocksRaycasts = false;//當(dāng)彈出新的面板的時候吧碾,讓主菜單面板 不再和鼠標(biāo)交互
}
/// <summary>
/// 界面重啟
/// </summary>
public override void OnResume()
{
canvasGroup.blocksRaycasts = true;
}
/// <summary>
/// 啟動對應(yīng)面板主要用于監(jiān)聽事件
/// </summary>
/// <param name="panelTypeString"></param>
public void OnPushPanel(string panelTypeString)
{
UIPanelType panelType = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), panelTypeString);
UIManager.Instance.PushPanel(panelType);
}
接下來我們再開發(fā)一個背包面板凰盔,來測試UI框架,這里背包面板主要重寫顯示和隱藏邏輯倦春,暫停和重啟邏輯與菜單面板相似户敬。
/// <summary>
/// 顯示背包
/// </summary>
public override void OnEnter()
{
if (canvasGroup == null) canvasGroup = GetComponent<CanvasGroup>();
canvasGroup.alpha = 1;
canvasGroup.blocksRaycasts = true;
Vector3 temp = transform.localPosition;
temp.x = 600;
transform.localPosition = temp;
transform.DOLocalMoveX(0, .5f);
}
/// <summary>
/// 隱藏背包
/// </summary>
public override void OnExit()
{
//canvasGroup.alpha = 0;
canvasGroup.blocksRaycasts = false;
transform.DOLocalMoveX(600, .5f).OnComplete(() => canvasGroup.alpha = 0);
}
最后我們將菜單面板的Button注冊監(jiān)聽事件OnPushPanel落剪,分配面板類型字符串,即可開啟測試尿庐。
七. 結(jié)束
感謝觀看忠怖,希望這篇文章對你真正有所感悟。