Unity3D UGUI实现Toast

发表于2018-11-19
评论0 5.5k浏览
项目中有些信息需要以Toast的形式体现出来,考虑到有些人对这个了解的不够多,这才有下面给大家介绍的UGUI Toast的实现。

原理

先做一个Toast的prefeb,然后通过一个Manager将Toast生成出来,显示到Canvas。
然后出于性能考虑,由于反复Instantiate和Destroy对性能消耗巨大,所以内部使用了一个简单的Queue对生成出来的Toast进行了一个缓存。

使用方法

将prefeb中的ToastManager拖入到场景中

像这样

然后设置prefeb的参数:
第一个是可以用于显示的Canvas
第二个是Toast的对象池的大小
第三个是Toast的prefeb(可以在Res/Prefebs文件夹下找到)

代码调用方法:
简单的调用方法,默认的位置和颜色
    public void ShowTopToast(string str)
    {
        LTToastManager.Instance.ShowToast(str);
    }

可以自定义的调用方法,手动设置颜色,显示时间以及位置
    public void ShowBottomToast(string str)
    {
        LTToast tempToast = LTToastManager.Instance.GetToast();
        tempToast.SetColor(Color.green, Color.red);
        tempToast.SetDuring(LTToast.DURING_LONG);
        tempToast.SetText(str);
        tempToast.SetPositionAndSize(LTToast.Position.Bottom);
        tempToast.Show();
    }

实际效果

代码

Toast类
using UnityEngine;
using UnityEngine.UI;
// 该类与LTToastManager强调用耦合
// PS:本来是想写成参数传递进入的,但是想了想这两块代码本就是一个模块
// 能不能算在内聚里面 O(∩_∩)O~
public class LTToast : MonoBehaviour
{
    public enum Position
    {
        Bottom, Top, Custom
    }
    public Image background;
    public Text toastStr;
    public const float DURING_LONG = 1f;
    public const float DURING_SHOR = 0.5f;
    private const string ENTER_KEY = "enter";
    private const string EXIT_KEY = "exit";
    #region Top位置固定参数
    private static Vector2 TopAnchorMin = new Vector2(0, 1);
    private static Vector2 TopAnchorMax = new Vector2(1, 1);
    private static Vector2 TopPivot = new Vector2(0.5f, 1);
    private static Vector3 TopAnchoredPosition3D = new Vector3(0, 0, 0);
    private static Vector2 TopSizeDelta = new Vector3(0, 50);
    #endregion
    #region Bottom位置固定参数
    private static Vector2 BottomAnchorMin = new Vector2(0, 0);
    private static Vector2 BottomAnchorMax = new Vector2(1, 0);
    private static Vector2 BottomPivot = new Vector2(0.5f, 0);
    private static Vector3 BottomAnchoredPosition3D = new Vector3(0, 0, 0);
    private static Vector2 BottomSizeDelta = new Vector3(0, 50);
    #endregion
    #region 自定义位置参数
    private Vector2 customAnchorMin = new Vector2(0, 0);
    private Vector2 customAnchorMax = new Vector2(1, 0);
    private Vector2 customPivot = new Vector2(0.5f, 0);
    private Vector3 customAnchoredPosition3D = new Vector3(0, 0, 0);
    private Vector2 customSizeDelta = new Vector3(0, 50);
    #endregion
    private RectTransform rectTransform;
    private Animator mAnimator;
    private float duringTime = DURING_SHOR;
    private Position showPosition = Position.Top;
    private bool isExit = false;
    void Awake()
    {
        rectTransform = this.GetComponent<RectTransform>();
        mAnimator = this.GetComponent<Animator>();
    }
    public void SetColor(Color backColor, Color textColor)
    {
        background.color = backColor;
        toastStr.color = textColor;
    }
    public void SetDuring(float duringTime)
    {
        this.duringTime = duringTime;
    }
    public void SetText(string str)
    {
        toastStr.text = str;
    }
    public void SetPositionAndSize(Position showPosition)
    {
        this.showPosition = showPosition;
    }
    public void SetPositionAndSize(Vector2 min, Vector2 max, Vector2 pivot, Vector3 anchoredPosition, Vector2 size)
    {
        showPosition = Position.Custom;
        customAnchorMin = min;
        customAnchorMax = max;
        customPivot = pivot;
        customAnchoredPosition3D = anchoredPosition;
        customSizeDelta = size;
    }
    private void SetPositionAndSize()
    {
        if (showPosition == Position.Top)
        {
            rectTransform.anchorMin = TopAnchorMin;
            rectTransform.anchorMax = TopAnchorMax;
            rectTransform.pivot = TopPivot;
            rectTransform.anchoredPosition3D = TopAnchoredPosition3D;
            rectTransform.sizeDelta = TopSizeDelta;
        }
        else if (showPosition == Position.Bottom)
        {
            rectTransform.anchorMin = BottomAnchorMin;
            rectTransform.anchorMax = BottomAnchorMax;
            rectTransform.pivot = BottomPivot;
            rectTransform.anchoredPosition3D = BottomAnchoredPosition3D;
            rectTransform.sizeDelta = BottomSizeDelta;
        }
        else if (showPosition == Position.Custom)
        {
            rectTransform.anchorMin = customAnchorMin;
            rectTransform.anchorMax = customAnchorMax;
            rectTransform.pivot = customPivot;
            rectTransform.anchoredPosition3D = customAnchoredPosition3D;
            rectTransform.sizeDelta = customSizeDelta;
        }
        else
        {
            Debug.LogError("检测到未定义位置,采用默认位置");
            rectTransform.anchorMin = TopAnchorMin;
            rectTransform.anchorMax = TopAnchorMax;
            rectTransform.pivot = TopPivot;
            rectTransform.anchoredPosition3D = TopAnchoredPosition3D;
            rectTransform.sizeDelta = TopSizeDelta;
        }
    }
    public void Show()
    {
        isExit = false;
        // 强耦合
        transform.SetParent(LTToastManager.Instance._ShowCanvas.transform);
        // 设置位置及缩放的代码建议放在SetParent之后,防止蛋疼
        transform.localScale = Vector3.one;
        SetPositionAndSize();
        mAnimator.Play(ENTER_KEY);
    }
    public void Cancel()
    {
        if (isExit)
        {
            return;
        }
        mAnimator.Play(EXIT_KEY);
        isExit = true;
    }
    // UI帧调用,请勿更改
    void EnterDone()
    {
        Invoke("Cancel", duringTime);
    }
    // UI帧调用,请勿更改
    void ExitDone()
    {
        // 强耦合
        transform.SetParent(LTToastManager.Instance.transform);
        LTToastManager.Instance.ReturnToast(this);
    }
}

ToastManager类
using UnityEngine;
using System.Collections.Generic;
public class LTToastManager : MonoBehaviour
{
    private static LTToastManager mInstance;
    public static LTToastManager Instance
    {
        get
        {
            return mInstance;
        }
    }
    public Canvas _ShowCanvas;
    public int _ToastPoolSize = 5;
    public GameObject _PreToast;
    private int currentIndex = 0;
    private Queue<LTToast> toastPool;
    void Awake()
    {
        mInstance = this;
        toastPool = new Queue<LTToast>();
        Init();
    }
    private void Init()
    {
        if (null == _ShowCanvas)
        {
            throw new System.Exception("未绑定Canvas");
        }
        if (null == _PreToast)
        {
            throw new System.Exception("未绑定Toast");
        }
        // 清除已有的,保持Manager目录清洁(没什么卵用,纯粹洁癖)
        LTGame.LTUtils.ClearChildren(transform);
        // 让对象池里面拥有一个Toast对象,提高第一次调用的效率
        ReturnToast(GetToast());
    }
    public void ReturnToast(LTToast tempToast)
    {
        if (toastPool.Count < _ToastPoolSize)
        {
            toastPool.Enqueue(tempToast);
        }
        else
        {
            // 如果超出Toast池的最大大小则销毁
            Destroy(tempToast.gameObject);
        }
    }
    public LTToast GetToast()
    {
        if (toastPool.Count > 0)
        {
            return toastPool.Dequeue();
        }
        else
        {
            LTToast tempToast = Instantiate(_PreToast).GetComponent<LTToast>();
            // 将新生成的对象放置到Manager目录下。
            // PS:其实这段代码不应该放在这里,但是暂时木有找到更好的地方咯~~
            tempToast.transform.SetParent(transform);
            return tempToast;
        }
    }
    public LTToast ShowToast(string str)
    {
        return ShowToast(str, LTToast.DURING_SHOR);
    }
    public LTToast ShowToast(string str, float duringTime)
    {
        return ShowToast(str, Color.black, Color.white, duringTime);
    }
    public LTToast ShowToast(string str, Color backColor, Color textColor)
    {
        return ShowToast(str, backColor, textColor, LTToast.DURING_SHOR);
    }
    public LTToast ShowToast(string str, Color backColor, Color textColor, float duringTime)
    {
        LTToast result = GetToast();
        result.SetColor(backColor, textColor);
        result.SetText(str);
        result.SetDuring(duringTime);
        result.SetPositionAndSize(LTToast.Position.Top);
        result.Show();
        return result;
    }
}

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