系统通知弹窗(CanvasGroup组件实现淡入淡出)

发表于2018-11-27
评论6 9.6k浏览

主要是在实现淡入淡出时用到了Canvas Group组件:

组件比较简单,有四个属性:

Alpha:透明度
Interactable:是否禁用输入交互
Block Raycasts:是否禁用射线检测
Ignore Parent Groups:是否忽略父级Canvas Group

该组件作用于挂载该组件的GameObject及其子物体。利用这一点,可以控制整个UI窗口的Alpha值,而不必纠结其下有多少子物体,也可以利用该组件设置整个窗口内所有组件的不可点击。

因为通知内容长度不定,窗口大小和文本框要自动缩放:
PopupMessageCenter作为父节点,挂载控制脚本"PopupMessageCenter"(代码附在文末),所有的弹窗GameObject都将挂到该父节点下。Vertical Layout Group组件会缩放子物体的宽度与父节点同宽,Content Size Fitter组件会根据子物体的数量及大小缩放父物体大小。

Popup Prefab是弹窗窗体,也是预设体,Vertical Layout Group组件可以根据子物体大小缩放窗体大小,Canvas Group组件实现淡入淡出,并禁用输入交互。

InfoText用来显示消息内容,Text组件的Vertical Overrflow属性,文字排版纵向溢出,Content Size Fitter组件会根据文字内容多少自动调整文本框大小。

代码部分,都加了注释说明,比较简单就不多说了:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
namespace SimpleFrame
{
    //弹窗消息类
    class MessageInfo
    {
        public string infoStr { get; private set; }
        public Color color { get; private set; }
        public MessageInfo(string messageStr, Color messageColor)
        {
            infoStr = messageStr;
            color = messageColor;
        }
    }
    public class PopupMessageCenter : MonoBehaviour
    {
        //淡入/淡出时间
        [SerializeField] float fadeTime = 0.5f;
        //持续显示时间
        [SerializeField] float showTime = 3f;
        //最多显示数量
        [SerializeField] int maxShowCount = 5;
        //消息弹窗预设
        Transform popupPrefab;
        //当前显示数量
        int curShowCount;
        //待显示消息列表
        Stack<MessageInfo> infoStack = new Stack<MessageInfo>();
        //所有可用弹窗列表
        Stack<Transform> popupStack = new Stack<Transform>();
        void Awake()
        {
            Init();
        }
        void Update()
        {
            //测试代码
            if(Input.GetKeyDown(KeyCode.Alpha1))
            {
                AddMessageInfo("哈哈哈哈哈哈哈哈哈哈哈", Color.red);
            }
            else if(Input.GetKeyDown(KeyCode.Alpha2))
            {
                AddMessageInfo("嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿", Color.grey);
            }
            else if (Input.GetKeyDown(KeyCode.Alpha3))
            {
                AddMessageInfo("嘻嘻嘻嘻嘻嘻嘻嘻", Color.green);
            }
        }
        public void Init()
        {
            //初始化消息弹窗设置
            popupPrefab = transform.Find("PopupPrefab");
            CanvasGroup prefabGroup = popupPrefab.GetComponent<CanvasGroup>();
            if (prefabGroup == null)
                prefabGroup = popupPrefab.gameObject.AddComponent<CanvasGroup>();
            prefabGroup.alpha = 0;
            prefabGroup.interactable = false;
            prefabGroup.blocksRaycasts = false;
            popupPrefab.gameObject.SetActive(false);
        }
        //添加消息
        public void AddMessageInfo(string infoStr, Color infoColor)
        {
            //当前显示数量是否达到上限
            if (curShowCount < maxShowCount)
            {
                //显示
                ShowMessageInfo(infoStr, infoColor);
            }
            else
            {
                //添加到待显示列表
                infoStack.Push(new MessageInfo(infoStr, infoColor));
            }
        }
        //展示消息
        void ShowMessageInfo(string infoStr, Color infoColor)
        {
            if (curShowCount >= maxShowCount)
                return;
            curShowCount++;
            Transform tmpInfoObj;
            if (popupStack.Count > 0)
                tmpInfoObj = popupStack.Pop();
            else
                tmpInfoObj = Instantiate(popupPrefab, transform);
            //设置子物体顺序, 即最新显示的弹窗在最上面
            tmpInfoObj.SetSiblingIndex(0);
            //设置显示内容
            Text tmpText = tmpInfoObj.GetComponentInChildren<Text>();
            tmpText.text = infoStr;
            tmpText.color = infoColor;
            StartCoroutine(ShowMessagePopup(tmpInfoObj.gameObject));
        }
        IEnumerator ShowMessagePopup(GameObject infoObj)
        {
            CanvasGroup tmpGroup = infoObj.GetComponent<CanvasGroup>();
            tmpGroup.alpha = 0;
            //开始显示
            infoObj.gameObject.SetActive(true);
            tmpGroup.DOFade(1, fadeTime);
            //持续一段时间
            yield return new WaitForSeconds(fadeTime + showTime);
            //开始隐藏
            tmpGroup.DOFade(0, fadeTime);
            yield return new WaitForSeconds(fadeTime);
            infoObj.gameObject.SetActive(false);
            popupStack.Push(infoObj.transform);
            curShowCount--;
            //如果待显示列表不为空, 继续显示
            if (infoStack.Count > 0)
            {
                MessageInfo tmpInfo = infoStack.Pop();
                if (tmpInfo != null)
                {
                    ShowMessageInfo(tmpInfo.infoStr, tmpInfo.color);
                }
            }
        }
    }
}

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: