Unity 2D 自定义toast 支持下滑
自定义了一个Toast弹窗
实现功能
1、支持简单的toast提示
2、支持连续弹出toast并且下滑
3、支持长消息和短消息提示
剩余工作
长短消息连续弹出 消息消失按照最后一次时间判断
防止多消息连续弹出Bug 弄了一个任务队列
效果
基本思路
简易的单例toast实现调用显示
利用协程实现定时消失
利用leantween实现多消息弹出时下滑旧消息 且计算下滑距离(方法比较痴呆 暂未考虑好其他办法 不用其他动画插件原因就是项目就用的Leantween 方便使用)
代码如下
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ToastManager : Singleton<ToastManager>
{
private class ToastTask {
public string text;
public bool isshort;
public ToastTask(string text, bool isshort)
{
this.text = text;
this.isshort = isshort;
}
}
private Queue<ToastTask> toastTasks = new Queue<ToastTask>();
public Transform Root;
public Text text;
public Image bg;
private Coroutine coroutine;
private CanvasGroup canvasGroup;
private int toastcount = 0;
float ShowTime = 3f;
float ShowTimeShort = 1f;
bool IsShort = false;
// Start is called before the first frame update
void Start()
{
canvasGroup = Root.GetComponent<CanvasGroup>();
canvasGroup.alpha = 0;
}
private void FixedUpdate()
{
if (toastTasks.Count>0 && Time.frameCount % 5 == 0)
{
ToastTask task = toastTasks.Dequeue();
ShowToast(task);
}
}
public void ShowToast(string text, bool isshort = false)
{
ToastTask task = new ToastTask(text, isshort);
toastTasks.Enqueue(task);
}
private void ShowToast(ToastTask task) {
this.IsShort = task.isshort;
//清空多余toast
ClearToast();
//已经有一个toast
if (canvasGroup.alpha > 0.9)
{
toastcount++;
if (coroutine != null)
{
StopCoroutine(coroutine);
}
//克隆 toast
GameObject gameObject = Instantiate(Root.GetChild(Root.childCount - 1).gameObject);
gameObject.transform.SetParent(Root);
gameObject.transform.localPosition = Vector3.zero;
gameObject.name = "bg" + toastcount;
ChangeView(gameObject, task.text);
gameObject.GetComponentInChildren<Text>().text = task.text;
//向下平移 toast
MoveDown();
coroutine = StartCoroutine(Dismiss());
return;
}
else
{
toastcount = 0;
Root.GetChild(0).localPosition = Vector3.zero;
}
//第一个toast
this.text.text = task.text;
ChangeView(task.text);
coroutine = StartCoroutine(Dismiss());
}
private void MoveDown()
{
for (int i = 0; i < Root.childCount-1; i++)
{
int j = Root.childCount - i-1;
Vector3 pos = Root.GetChild(i).transform.localPosition;
float dis = (j * 100);
//Debug.LogError("将第"+i+"个bg挪到"+ j+"位置");
LeanTween.moveLocal(Root.GetChild(i).gameObject, new Vector3(pos.x, -dis, 0), 0.3f);
}
}
private void ClearToast()
{
if (canvasGroup.alpha < 0.1)
{
for (int i = 1; i < Root.childCount; i++)
{
Destroy(Root.GetChild(i).gameObject);
}
}
}
/// <summary>
/// 根据文字多少 调整toast背景大小
/// </summary>
/// <param name="tip"></param>
private void ChangeView(string tip)
{
int len = GetTotalStrLength(tip);
bg.transform.GetComponent<RectTransform>().sizeDelta = new Vector2(len + 180, 100);
}
private void ChangeView(GameObject gameObject, string tip)
{
int len = GetTotalStrLength(tip);
gameObject.transform.GetComponent<RectTransform>().sizeDelta = new Vector2(len + 180, 100);
}
/// <summary>
/// 定时消失
/// </summary>
/// <returns></returns>
private IEnumerator Dismiss()
{
LeanTween.alphaCanvas(Root.GetComponent<CanvasGroup>(),1,0.1f);
yield return new WaitForSeconds(IsShort?ShowTimeShort:ShowTime);
LeanTween.alphaCanvas(Root.GetComponent<CanvasGroup>(), 0, 0.1f);
}
private int GetTotalStrLength(string tip)
{
int totalLength = 0;
Font font = text.font;
font.RequestCharactersInTexture(tip, text.fontSize, text.fontStyle);
CharacterInfo characterInfo = new CharacterInfo();
char[] arr = tip.ToCharArray();
foreach (char c in arr)
{
font.GetCharacterInfo(c, out characterInfo, text.fontSize);
totalLength += characterInfo.advance;
}
return totalLength;
}
}
附demo地址
https://download.csdn.net/download/weixin_42461528/17127837