UI管理器

UI管理器

用于显示面板,隐藏面板,添加自定义事件。

1.怎样能存储所有面板? ———— 字典,面板名为Key , 面板基类为Value
2.怎样在字典中存储不同面板脚本 ———— 所有面板继承面板基类,用里氏替换在字典中记录

构造函数:进行初始化加载Canvas和EventSystem

显示面板:如果字典中已经存在该面板,则直接执行面板显示后的逻辑,否则先异步加载面板,然后初始化该面板,再加入字典。

隐藏面板:如果字典存在该面板,则执行对应面板逻辑后直接销毁并从字典中删除。

自定义事件监听:UI控件继承UIBehaviour基类,因此,传入控件类型,控件响应类型,响应函数即可。

public enum E_UI_Layer
{
    Top,
    Bot,
    Mid,
    System,
}
public class UIManager : BaseManager<UIManager>
{
    //字典容器
    Dictionary<string,BasePanel> panelDic = new Dictionary<string,BasePanel>();
    //各层
    private Transform top;
    private Transform bot;
    private Transform mid;
    private Transform system;
    //初始化
    public UIManager()
    {
        //加载Canvas 过场景不移除
        GameObject canvas = ResManager.Instance.Load<GameObject>("UI/Canvas");
        GameObject.DontDestroyOnLoad(canvas);
        //加载EventSystem
        GameObject eventSystem = ResManager.Instance.Load<GameObject>("UI/EventSystem");
        GameObject.DontDestroyOnLoad(canvas);

        //找到各层
        top = canvas.transform.Find("Top");
        bot = canvas.transform.Find("Bot");
        mid = canvas.transform.Find("Mid");
        system = canvas.transform.Find("System");
    }


    //显示面板
    public void ShowPanel<T>(string panelName , E_UI_Layer layer = E_UI_Layer.Mid , UnityAction<T> callBack = null) where T : BasePanel
    {
        if(panelDic.ContainsKey(panelName))
        {
            panelDic[panelName].ShowMe();
            if(callBack != null)
            {
                callBack(panelDic[panelName] as T);
            }
            return;
        }
        //加载面板
        ResManager.Instance.LoadAsync<GameObject>(panelName, (obj) =>
        {
            
            //得到panel挂载的脚本
            T panel = obj.GetComponent<T>();
            if(callBack != null)
                callBack(panel);

            Transform father = mid;
            switch (layer)
            {
                case E_UI_Layer.Bot:
                    father = bot;
                    break;
                case E_UI_Layer.System:
                    father = system;
                    break;
                case E_UI_Layer.Top:
                    father = top;
                    break;
            }
            obj.transform.SetParent(father, false);
            //显示面板
            panel.ShowMe();

            //存起来
            panelDic.Add(panelName, panel);
        });

    }

    //隐藏面板

    public void HidePanel(string panelName)
    {
        if (panelDic.ContainsKey(panelName))
        {
            //隐藏自己要执行的逻辑
            panelDic[panelName].HideMe();
            GameObject.Destroy(panelDic[panelName].gameObject);
            //字典中移除
            panelDic.Remove(panelName);
        }
    }
    //得到层级
    public Transform GetLayerFather(E_UI_Layer layer)
    {
        switch (layer)
        {
            case E_UI_Layer.Bot:
                return this.bot;
            case E_UI_Layer.Mid:
                return this.mid;
            case E_UI_Layer.Top:
                return this.top;
            case E_UI_Layer.System:
                return this.system;
        }
        return null;
    }

    
    public static void AddCustomEventListener(UIBehaviour control, EventTriggerType type , UnityAction<BaseEventData> callback)
    {
        //自定义事件监听控件
        EventTrigger trigger = control.GetComponent<EventTrigger>();
        if (trigger == null) {
            trigger = control.gameObject.AddComponent<EventTrigger>();
        }
        
        EventTrigger.Entry entry = new EventTrigger.Entry();
        //事件类型
        entry.eventID = type;
        //响应函数
        entry.callback.AddListener(callback);
        //加入控件中
        trigger.triggers.Add(entry);
    }

}

面板基类

作用:为了不用每次都去关联UI控件,这里直接实现找到所有UI控件脚本,并用字典存储。

字典:UI控件名为Key,链表为Value(存储该UI控件下所有UI控件脚本)

两个主要函数:FindChildrenControl,用于找到该面板下所有UI控件挂载的脚本。
GetControl,得到该面板指定UI控件对应的UI控件脚本。

public class BasePanel : MonoBehaviour
{
    // Start is called before the first frame update

    Dictionary<string, List<UIBehaviour>> controlDic = new Dictionary<string, List<UIBehaviour>>(); 
    protected virtual  void Awake()
    {
        FindChildrenControl<Button>();
        FindChildrenControl<Image>();
        FindChildrenControl<Text>();
        FindChildrenControl<Toggle>();
        FindChildrenControl<Slider>();
        FindChildrenControl<ScrollRect>();
        FindChildrenControl<InputField>();
    }

    public virtual void ShowMe()
    {

    }

    public virtual void HideMe() { }

    protected virtual void OnClick(string btnName)
    {

    }

    protected virtual void OnValueChange(string toggleName , bool value)
    {

    }

    protected virtual T GetControl<T>(string controlName) where T : UIBehaviour
    {
        if(controlDic.ContainsKey(controlName))
        {
            for(int i = 0; i < controlDic[controlName].Count; i++)
            {
                if (controlDic[controlName][i] is T)
                {
                    return controlDic[controlName][i] as T;
                }
            }
        }

        return null;
    }

    private void FindChildrenControl<T>() where T : UIBehaviour
    {
        T[] controls = gameObject.GetComponentsInChildren<T>();

        for(int i = 0; i < controls.Length; i++)
        {
            string controlName = controls[i].gameObject.name;

            if(controlDic.ContainsKey(controlName))
            {
                controlDic[controlName].Add(controls[i]);
            }
            else
            {
                controlDic.Add(controlName, new List<UIBehaviour>() { controls[i] });
            }
        }
    }
}

使用:在某一面板类中如下调用即可

private void Start()
{
    GetControl<Button>("btnSetting").onClick.AddListener(() =>
    {
        print("被点击");
    });
    UIManager.AddCustomEventListener(GetControl<Button>("btnSetting"), EventTriggerType.PointerEnter, (data) =>
    {
        print("鼠标进入" +  (data as PointerEventData).position);
    });
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值