Unity--树实现的红点系统

红点系统的简介

我们在平常生活中的软件中都能看到消息通知会在一些条目上会有红色的点点提示,我们在开发中也会遇到这样的情况,这就是我们平常说的红点系统。下面是我总结的红点系统的简单知识和今天的红点系统的示例:
红点示例

下面就是实现以上代码的示例:

树结构的常量类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RedPointConst
{
    //按照系统来划分树的各个节点,比如:上面展示的红点树结构,代码可以使用string来完成。
    //这个定义不仅仅是用来规划结构,也会为后面事件驱动的时候提供key。
    //主界面
    public const string main = "Main";
    //主界面邮件按钮
    public const string mail = "Main.Mail";
    //邮件系统界面
    public const string mailSystem = "Main.Mail.System";
    //队伍界面
    public const string mainTeam = "Main.Mail.Team";
    //工会界面
    public const string mainAlliance = "Main.Mail.Alliance";
    //双人队伍界面
    public const string mainTeamDouble = "Main.Mail.Team.Double";
    //四人队伍界面
    public const string mainTeamFour = "Main.Mail.Team.Four";
}

树结构的结点类
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RedPointNode
{
    //节点名称
    public string nodeName;
    //总的红点数量
    public int pointNum=0;
    //父节点
    public RedPointNode parent = null;
    //发生变化的回调函数
    public RedPointSystems.OnPointNumChange numChangeFunc;
    //子节点   (结点的const名称 结点数据)
    public Dictionary<string, RedPointNode> dicChilds = new Dictionary<string, RedPointNode>();

    /// <summary>
    /// 设置当前节点的红点数量
    /// </summary>
    /// <param name="rpNum"></param>
    public void SetRedPointNum(int rpNum)
    {
        //红点数量只能设置叶子节点
        if (dicChilds.Count > 0)
        {
            Debug.LogError("Only Can Set Leaf Node!");
            return;
        }
        pointNum = rpNum;
        NotifyPointNumChange();
        if (parent != null)
        {
            parent.ChangePredPointNum();
        }
    }
    /// <summary>
    /// 计算当前红点数量
    /// </summary>
    private void ChangePredPointNum()
    {
        int num = 0;
        foreach (var node in dicChilds.Values)
        {
            num += node.pointNum;
        }
        //红点有变化
        if (num != pointNum)
        {
            pointNum = num;
            NotifyPointNumChange();
        }
    }
    /// <summary>
    /// 通知红点数量变化
    /// </summary>
    private void NotifyPointNumChange()
    {
        // invoke(参数delegate)方法:在拥有此控件的基础窗口句柄的线程上执行指定的委托。
        //如果你的后台线程需要操作UI控件,并且需要等到该操作执行完毕才能继续执行,那么你就应该使用Invoke。
        numChangeFunc?.Invoke(this);
    }
}

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

public class RedPointSystems 
{
    //第一个是定义一个事件驱动的Delegate类型,第二个是要持有红点树的Root节点,
    //第三个是将需要关心的红点树加入到List中方便启动时候进行初始化
    //红点系统要做哪些事
    //红点变化通知
    public delegate void OnPointNumChange(RedPointNode node);
    RedPointNode mRootNode;//红点树Root节点
    //初始化红点树
    static List<string> IsPointTreeList = new List<string>
    {
        RedPointConst.main,
        RedPointConst.mail,
        RedPointConst.mailSystem,
        RedPointConst.mainTeam,
        RedPointConst.mainAlliance,
        RedPointConst.mainTeamDouble,
        RedPointConst.mainTeamFour,
        
    };

    //开始进行初始化
    public void InitRedPointTreeNode()
    {
        mRootNode = new RedPointNode();
        mRootNode.nodeName = RedPointConst.main;

        foreach (var s in IsPointTreeList)
        {
            var node = mRootNode;
            //把我们每一个节点的名字通过截取存成数组
            var treeNodeAy = s.Split('.');
            //判断数组的第[0]项是否是根结点,不是的话就会报错
            if (treeNodeAy[0] != mRootNode.nodeName)
            {
                Debug.Log("红点树根结点报错:"+treeNodeAy[0]);
                continue;
            }
            //数组存储每一个节点的名字[0]根结点[1]根的子节点  [2]是【1】的子节点以此类推
            if (treeNodeAy.Length > 1)
            {
                for (int i = 1; i < treeNodeAy.Length; i++)
                {
                    if (!node.dicChilds.ContainsKey(treeNodeAy[i]))
                    {
                        //添加节点
                        node.dicChilds.Add(treeNodeAy[i],new RedPointNode());
                    }
                    //节点名字  节点的父节点是是上一级节点
                    node.dicChilds[treeNodeAy[i]].nodeName = treeNodeAy[i];
                    node.dicChilds[treeNodeAy[i]].parent = node;
                    //初始化红点树的最后一次重新赋值
                    node = node.dicChilds[treeNodeAy[i]];
                }
            }
        }
    }

    //现在树结构有了,那么我们要对树结构设置事件驱动,其实就是给这棵树绑定一个事件回调:
    //事件回调    参数(节点名字,节点数量改变的回调方法)
    public void SetRedPointNodeCallBack(string strNode,RedPointSystems.OnPointNumChange callBack)
    {
        var nodelist = strNode.Split('.');
        if (nodelist.Length == 1)
        {
            if (nodelist[0] != RedPointConst.main)
            {
                Debug.Log("Get Wrong Root Node Current is"+nodelist[0]);
                return;
            }
        }

        var node = mRootNode;
        for (int i = 1; i < nodelist.Length; i++)
        {
            if (!node.dicChilds.ContainsKey(nodelist[i]))
            {
                Debug.Log("不包含这个孩子结点:" + nodelist[i]);
                return;
            }
            node = node.dicChilds[nodelist[i]];
            //最后一个节点了
            if (i == nodelist.Length - 1)
            {
                node.numChangeFunc = callBack;
                return;
            }
        }
    }

    //驱动层
    public void SetInvoke(string strNode,int rpNum)
    {
        //分析树节点
        var nodeList = strNode.Split('.');
        if (nodeList.Length == 1)
        {
            if (nodeList[0] != RedPointConst.main)
            {
                Debug.Log("根结点发生错误!现在的节点是"+nodeList[0]);
                return;
            }
        }

        var node = mRootNode;
        for (int i = 1; i < nodeList.Length; i++)
        {
            if (!node.dicChilds.ContainsKey(nodeList[i]))
            {
                Debug.Log("不包含这个孩子结点:" + nodeList[i]);
                return;
            }
            node = node.dicChilds[nodeList[i]];
            //最后一个节点
            if (i == nodeList.Length - 1)
            {
                //设置节点的红点数量
                node.SetRedPointNum(rpNum);
            }
        }
    }

}

具体实现的脚本

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

public class BootStart : MonoBehaviour
{
    //每一个界面的照片  红点数量文本
    public Image imageMail;
    public Image imageMailSystem;
    public Image imageMailTeam;
    public Image imageMailAlliance;
    public Image imageMailTeamDouble;
    public Image imageMailTeamFour;

    public Text textMail;
    public Text textMailSystem;
    public Text textMailTeam;
    public Text textMailAlliance;
    public Text textMailTeamDouble;
    public Text textMailTeamFour;

    // Start is called before the first frame update
    void Start()
    {
        RedPointSystems rps = new RedPointSystems();
        //树结构的初始化
        rps.InitRedPointTreeNode();

        //注册事件的回调
        rps.SetRedPointNodeCallBack(RedPointConst.mail,MailCallBack);
        rps.SetRedPointNodeCallBack(RedPointConst.mailSystem, MailSystemCallBack);
        rps.SetRedPointNodeCallBack(RedPointConst.mainTeam, MailTeamCallBack);
        rps.SetRedPointNodeCallBack(RedPointConst.mainAlliance, MailAllianceCallBack);
        rps.SetRedPointNodeCallBack(RedPointConst.mainTeamDouble, MailTeamDoubeCallBack);
        rps.SetRedPointNodeCallBack(RedPointConst.mainTeamFour, MailTeamFourCallBack);
        //节点名称,该节点的节点数量
        //组队结点下的双人四人组队子节点
        rps.SetInvoke(RedPointConst.mainTeamDouble, 1);
        rps.SetInvoke(RedPointConst.mainTeamFour, 2);
        //邮件系统下面的系统、工会系统红点数
        rps.SetInvoke(RedPointConst.mailSystem,3);
        rps.SetInvoke(RedPointConst.mainAlliance, 6);
        
    }

    private void MailTeamFourCallBack(RedPointNode node)
    {
        textMailTeamFour.text = node.pointNum.ToString();
        imageMailTeamFour.gameObject.SetActive(node.pointNum > 0);
        Debug.Log(node.nodeName + "rp Num changed num=" + node.pointNum);
    }

    private void MailTeamDoubeCallBack(RedPointNode node)
    {
        textMailTeamDouble.text = node.pointNum.ToString();
        imageMailTeamDouble.gameObject.SetActive(node.pointNum > 0);
        Debug.Log(node.nodeName + "rp Num changed num=" + node.pointNum);
    }

    private void MailAllianceCallBack(RedPointNode node)
    {
        textMailAlliance.text = node.pointNum.ToString();
        imageMailAlliance.gameObject.SetActive(node.pointNum > 0);
        Debug.Log(node.nodeName + "rp Num changed num=" + node.pointNum);
    }

    private void MailTeamCallBack(RedPointNode node)
    {
        textMailTeam.text = node.pointNum.ToString();
        imageMailTeam.gameObject.SetActive(node.pointNum > 0);
        Debug.Log(node.nodeName + "rp Num changed num=" + node.pointNum);
    }

    private void MailSystemCallBack(RedPointNode node)
    {
        textMailSystem.text = node.pointNum.ToString();
        imageMailSystem.gameObject.SetActive(node.pointNum > 0);
        Debug.Log(node.nodeName + "rp Num changed num=" + node.pointNum);
    }

    private void MailCallBack(RedPointNode node)
    {
        textMail.text = node.pointNum.ToString();
        imageMail.gameObject.SetActive(node.pointNum>0);
        Debug.Log(node.nodeName+"rp Num changed num="+node.pointNum);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

总结:这只是实现红点系统的一种方式,我这里只是提供了一种思路,代码写的不是很简洁为了通俗易懂,现在的红点需求基本上都可以通过这种方案实现,具体的实现效果在上面的X-Mind表现层里面的照片!

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值