1. 程式人生 > >UI框架簡介(四)

UI框架簡介(四)

繼續上篇內容哦!那麼我們就先看Basepanel類,它是所有面板的父類,提供了一些共同的方法。

這裡寫圖片描述

六大子類:那麼我們就以任務面板模組為例子吧!進行講解哦!下面的程式碼我們一字一句的看哦!看看到底是幹啥的!後面我會帶大家開發揹包模組時再進行重點講解揹包模組的哦!它的功能要多一些的。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class TaskPanel : BasePanel
{

    //任務面板上面的元件引用
    private
Button btnClose; private CanvasGroup canvasGroup; /// <summary> /// 初始化方法 /// </summary> void Awake() { RegisterComponent(); RegisterEvent(); } void Start() { if (canvasGroup == null) canvasGroup = GetComponent<CanvasGroup>(); } ///
<summary>
/// 複寫父類的方法,在進入時要處理的事情 /// </summary> public override void OnEnter() { if (canvasGroup == null) canvasGroup = GetComponent<CanvasGroup>(); canvasGroup.alpha = 1; canvasGroup.blocksRaycasts = true; } /// <summary> ///
複寫父類的方法,在退出時要處理的事情
/// </summary> public override void OnExit() { canvasGroup.alpha = 0; canvasGroup.blocksRaycasts = false; } /// <summary> /// 查詢元件方法 /// </summary> public void RegisterComponent() { btnClose = transform.Find("btnClose").GetComponent<Button>(); } /// <summary> /// 註冊偵聽方法 /// </summary> public void RegisterEvent() { btnClose.onClick.AddListener(delegate () { UIManager.Instance.PopPanel(); }); } }

這個只是任務面板的簡單演示哦!看完了它們自己的類和父類,我們來看UIManager類吧!這個是核心類哦!要認真看哦!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

/// <summary>
/// UI管理單例類(整個UI框架的核心管理類)
/// </summary>
public class UIManager
{
    #region 單例模式

    private static UIManager _instance;

    public static UIManager Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new UIManager();
            }
            return _instance;
        }
    }

    #endregion

    #region 所有的UI元素的父容器Canvas

    /// <summary>
    /// 欄位,獲取Canvas的位置
    /// </summary>
    private Transform canvasTransform;
    /// <summary>
    /// 屬性,給欄位提供一個可讀的get屬性
    /// </summary>
    private Transform CanvasTransform
    {
        get
        {
            if (canvasTransform == null)
            {
                canvasTransform = GameObject.Find("Canvas").transform;
            }
            return canvasTransform;
        }
    }

    #endregion

    /// <summary>
    /// 字典 管理UIPanelprefab的路徑< 列舉型別 字串型別>
    /// </summary>
    private Dictionary<UIPanelType, string> panelPatDic; //儲存所有面板prefab的路徑

    /// <summary>
    /// 字典 管理每個UIPanel上面的BasePanel指令碼
    /// <列舉型別,儲存是是遊戲物件上的元件>
    /// </summary>
    private Dictionary<UIPanelType, BasePanel> panelDic;//儲存所有例項化的面板(儲存所有例項化面板的遊戲物體身上的BasePanel元件)

    /// <summary>
    /// 棧 用來管理UIPanel面板的
    /// 這裡說一下為什麼要用棧來管理UI面板哦!
    /// 因為棧這種資料結構啊!具有先進後出,你想啊!我們最後開啟的UI面板需要最先關閉的吧!
    /// 所以我這裡選用了棧這種資料結構
    /// </summary>
    private Stack<BasePanel> panelStack;

    #region 建構函式
    private UIManager()
    {
        ParseUIPanelTypeJosn();
    }

    #endregion

    #region UI面板入棧操作

    /// <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);
        panel.OnEnter();
        panelStack.Push(panel);
    }

    #endregion

    #region UI面板出棧操作

    /// <summary>
    /// 出棧  把最上面的頁面從介面移除
    /// </summary>
    public void PopPanel()
    {
        if (panelStack == null)
            panelStack = new Stack<BasePanel>();

        if (panelStack.Count <= 0)
            return;

        //關閉棧頂頁面的顯示
        BasePanel topPanel = panelStack.Pop();
        topPanel.OnExit();

        if (panelStack.Count <= 0)
            return;
        //如果下面還有頁面,就讓下面的頁面開啟
        BasePanel topPanel2 = panelStack.Peek();
        topPanel2.OnResume();

    }

    #endregion

    #region 返回BasePanel物件方法

    /// <summary>
    /// 根據面板型別得到例項化的面板上面的BasePanel
    /// 核心哦!
    /// </summary>
    /// <param name="panelType"></param>
    /// <returns></returns>
    private BasePanel GetPanel(UIPanelType panelType)
    {
        if (panelDic == null)
        {
            panelDic = new Dictionary<UIPanelType, BasePanel>();//初始化字典
        }

        BasePanel panel;
        panelDic.TryGetValue(panelType, out panel);

        if (panel == null)
        {
            string path;
            panelPatDic.TryGetValue(panelType, out path);
            //Debug.Log(path);
            GameObject instPanel = GameObject.Instantiate(Resources.Load(path)) as GameObject;
            //如果為true,則相對於父級位置、縮放和旋轉修改該物件,使得該物件保持與之前世界座標空間一樣的位置,旋轉和縮放。
            instPanel.transform.SetParent(CanvasTransform, false);
            panelDic.Add(panelType, instPanel.GetComponent<BasePanel>());
            return instPanel.GetComponent<BasePanel>();
        }
        else
        {
            return panel;
        }
    }

    #endregion

    [Serializable]//序列化
    class UIPanelTypeJson
    {
        public List<UIPanelInfo> infoList;
    }

    /// <summary>
    /// 解析我們的json檔案 向字典中新增路徑
    /// </summary>
    private void ParseUIPanelTypeJosn()
    {
        panelPatDic = new Dictionary<UIPanelType, string>();//儲存所有面板prefab的路徑的字典的初始化

        TextAsset ta = Resources.Load<TextAsset>("UIType.json");

        UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(ta.text);//解析json檔案的核心程式碼

        foreach (UIPanelInfo info in jsonObject.infoList)
        {
            panelPatDic.Add(info.panelType, info.path);
        }
    }

}

上面的程式碼中會涉及到一個序列化和反序列的地方。這裡我簡單講解一下,大家不懂的話,自己去百度一下即可哦!

/*
 * 指令碼名:UI面板資訊型別管理
 * 
 */
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

//序列化
[Serializable]
public class UIPanelInfo : ISerializationCallbackReceiver
{
    [NonSerialized]
    public UIPanelType panelType;//這個欄位不會進行序列化了[NonSerialized]
    public string panelTypeString;
    public string path;

    /// <summary>
    /// 反序列化:從文字資訊到物件的過程
    /// </summary>
    public void OnAfterDeserialize()
    {
        //Enum.Parse 將一個或多個列舉常數的名稱或數字值的字串表示轉換成等效的列舉物件。
        UIPanelType type = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), panelTypeString);
        panelType = type;
    }

    public void OnBeforeSerialize()
    {

    }
}

本篇小結:本篇主要講解了我們UI框架的核心管理類哦!一定要明白這個類是幹嘛!不然後面無法進行開發的哦!