UGUI系列-实现层级菜单(Unity3D)

简介: 层级菜单在Unity中用到的并不多,主要是做分类的时候用的比较多,今天就给大家分享几个层级代码,扩充一下,写成插件也是不错的。

一、前言

层级菜单在Unity中用到的并不多,主要是做分类的时候用的比较多,今天就给大家分享几个层级代码,扩充一下,写成插件也是不错的。

首先看一下效果吧:


1.

网络异常,图片无法展示
|


2.

网络异常,图片无法展示
|


3.

网络异常,图片无法展示
|

网络异常,图片无法展示
|


4.

网络异常,图片无法展示
|


5.

网络异常,图片无法展示
|


二、资源下载

源文件:源文件下载

Github下载地址:LayerMenu.unitypackage


三、正文


第一种实现效果

网络异常,图片无法展示
|

实现原理:这个是用系统自带的UGUI  Scroll View组件,脚本控制创建父物体,父物体身上挂载有初始化子物体的脚本 优缺点: 优点是实现简单,不需要多与的插件,代码量也不大,控制比较方便 缺点是只能实现两个层级的显示 实现过程:


1、新建一个Scrpll View

网络异常,图片无法展示
|


2、制作预制体 界面就这么设计就行:

网络异常,图片无法展示
|

名字改一下 Content:父节点容器 ParentMenu:父节点 TextParent:父节点文本 ChildMenu:子节点容器 item:子节点 TextChild:子节点文本

网络异常,图片无法展示
|

然后将父节点改名字叫parentMenu,做成预制体:

网络异常,图片无法展示
|

预制体放到Resources文件夹中:

网络异常,图片无法展示
|

将子物体也制作成预制体:

网络异常,图片无法展示
|


3、编写脚本ParentMenu.cs 这个脚本主要是作用是创建子物体:

using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class ParentMenu : MonoBehaviour
{
    private GameObject childMenu;//子菜单的parent
    private RectTransform[] childs;//所有子菜单的rect
    private RectTransform itemRect;//子菜单的prefab
    private Vector3 offset;//单个子菜单的高度
    private int count;//子菜单的个数
    public bool isOpening { get; private set; }//父菜单是否展开
    public bool isCanClick { get; set; }//父菜单是否可以点击
    public void Init(RectTransform rect, int count)
    {
        //找到子节点
        childMenu = transform.Find("childMenu").gameObject;
        itemRect = rect;
        this.count = count;
        childs = new RectTransform[this.count];
        offset = new Vector3(0, itemRect.rect.height);
        for (int i = 0; i < this.count; i++)
        {
            childs[i] = Instantiate(itemRect, childMenu.transform);
        }
        childMenu.gameObject.SetActive(false);
        isOpening = false;
        isCanClick = true;
        GetComponent<Button>().onClick.AddListener(OnButtonClick);
    }
    void OnButtonClick()
    {
        if (!isCanClick) return;
        if (!isOpening)
            StartCoroutine(ShowChildMenu());
        else
            StartCoroutine(HideChildMenu());
    }
    IEnumerator ShowChildMenu()
    {
        childMenu.gameObject.SetActive(true);
        for (int i = 0; i < count; i++)
        {
            childs[i].localPosition -= i * offset;
            yield return new WaitForSeconds(0.1f);
        }
        isCanClick = true;
        isOpening = true;
    }
    IEnumerator HideChildMenu()
    {
        for (int i = count - 1; i >= 0; i--)
        {
            childs[i].localPosition += i * offset;
            yield return new WaitForSeconds(0.1f);
        }
        childMenu.gameObject.SetActive(false);
        isCanClick = true;
        isOpening = false;
    }
}
复制代码


4、编写脚本FoldableMenu.cs 这个脚本主要是为了创建父物体,以及控制折叠菜单

using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class FoldableMenu : MonoBehaviour
{
    private RectTransform content;//父物体的parent
    private TextAsset textAsset;//所有菜单信息
    private RectTransform parentRect;//父菜单的prefab
    private RectTransform[] parentArr;//所有父菜单的数组
    private RectTransform childRect;//子菜单的prefab
    private Vector3 parentOffset;//单个父菜单的高度
    private Vector3 childOffset;//单个父菜单的高度
    private int[] cntArr;//所有父菜单拥有的子菜单个数
    void Awake()
    {
        Init();
    }
    void Init()
    {
        //获取到父节点
        content = transform.Find("Viewport/Content").GetComponent<RectTransform>();
        //获取到menuinfo里面的信息  3 3 4 4 5 5
        textAsset = Resources.Load<TextAsset>("menuInfo");
        //获取到父物体 设置父物体的高度
        parentRect = Resources.Load<RectTransform>("parentMenu");
        parentOffset = new Vector3(0, parentRect.rect.height);
        //获取到子物体 设置子物体的高度
        childRect = Resources.Load<RectTransform>("item");
        childOffset = new Vector3(0, childRect.rect.height);
        //分割字符串 info = 3 3 4 4 5 5
        var info = textAsset.text.Split(',');//获取子菜单个数信息
        //数组的长度
        cntArr = new int[info.Length];
        //父菜单的数组
        parentArr = new RectTransform[info.Length];
        //初始化content高度 宽度不变 高度是所有父物体的总长
        content.sizeDelta = new Vector2(content.rect.width, parentArr.Length * parentRect.rect.height);
        //i = 6
        for (int i = 0; i < cntArr.Length; i++)
        {
            //创建服务器
            parentArr[i] = Instantiate(parentRect, content.transform);
            //坐标为 上一个父物体的宽度
            parentArr[i].localPosition -= i * parentOffset;
            //赋值
            cntArr[i] = int.Parse(info[i]);
            //父物体上面加载子物体 子物体数量为3 3 4 4 5 5
            parentArr[i].GetComponent<ParentMenu>().Init(childRect, cntArr[i]);
            int j = i;
            //父物体上面的button绑定事件
            parentArr[i].GetComponent<Button>().onClick.AddListener(() => { OnButtonClick(j); });
        }
    }
    void OnButtonClick(int i)
    {
        //如果iscanclick为false则return  因为已经点击过了 不能再点击了 除非升起来的时候将isCanClick改为true
        if (!parentArr[i].GetComponent<ParentMenu>().isCanClick)
            return;
        parentArr[i].GetComponent<ParentMenu>().isCanClick = false;
        //isopening 为true 执行 menuup 为flase执行menuDown
        if (!parentArr[i].GetComponent<ParentMenu>().isOpening)
            StartCoroutine(MenuDown(i));
        else
            StartCoroutine(MenuUp(i));
    }
    IEnumerator MenuDown(int index)
    {       
        for (int i = 0; i < cntArr[index]; i++)
        {
            //更新content高度
            content.sizeDelta = new Vector2(content.rect.width,
                content.rect.height + childOffset.y);
            for (int j = index + 1; j < parentArr.Length; j++)
            {
                parentArr[j].localPosition -= childOffset;
            }
            yield return new WaitForSeconds(0.1f);
        }     
    }
    IEnumerator MenuUp(int index)
    {
        for (int i = 0; i < cntArr[index]; i++)
        {
            //更新content高度
            content.sizeDelta = new Vector2(content.rect.width,
                content.rect.height - childOffset.y);
            for (int j = index + 1; j < parentArr.Length; j++)
            {
                parentArr[j].localPosition += childOffset;
            }
            yield return new WaitForSeconds(0.1f);
        }
    }
}
复制代码

将这个脚本挂载到Scroll View上面:

网络异常,图片无法展示
|
运行,搞定!


第二种实现效果

网络异常,图片无法展示
|

实现原理:这个也是用UGUI做的,不一样的是不需要容器组件,主要是寻找父节点,然后保存父节点的信息,下一个节点以父节点为目标进行偏移,或者以父节点为目标做子节点

优缺点:

优点:是代码清晰,可扩展性强,不需要设计UGUI

缺点:结构比较简单,没有实现多层级的功能

实现过程:


1、创建预制体

网络异常,图片无法展示
|

结构比较简单,两个Image,箭头的图片带Button组件(可以下拉和合并) 然后将预制体放到Resources文件夹中:

网络异常,图片无法展示
|


2、编写PublicData.cs脚本 一个数据类

using UnityEngine;
public class PublicData
{
    public static Transform parent;
    public static Vector2 currentPosition;
}
复制代码


3、编写脚本Options_Triangle.cs 初始化子节点的函数

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Options_Triangle : MonoBehaviour
{
    public Button triangle;
    public Image content;
    public List<Transform> children = new List<Transform>();
    void Start()
    {
        triangle.onClick.AddListener(() =>
        {
            if (triangle.transform.eulerAngles.z == 270)
            {
                triangle.transform.eulerAngles = Vector3.zero;
                for (int i = 0; i < children.Count; i++)
                {
                    children[i].gameObject.SetActive(false);
                }
            }
            else
            {
                triangle.transform.eulerAngles = new Vector3(0, 0, -90);
                for (int i = 0; i < children.Count; i++)
                {
                    children[i].gameObject.SetActive(true);
                }
            }
        });
    }
}
复制代码

4、编写ClickEvent.cs 这是一个层级菜单的编辑功能的脚本

using UnityEngine;
using UnityEngine.UI;
public class ClickEvent : MonoBehaviour
{
    public Button add_options_t;
    public Button add_options;
    public Transform canvasParent;
    void Start()
    {
        add_options_t.onClick.AddListener(() =>
        {
            if (PublicData.parent == null)
            {
                PublicData.parent = Instantiate(Resources.Load<Transform>("Options_triangle"));
                PublicData.parent.transform.SetParent(canvasParent, false);
                PublicData.currentPosition = new Vector2(PublicData.parent.position.x, PublicData.parent.position.y);
            }
            else
            {
                Transform option = Instantiate(Resources.Load<Transform>("Options_triangle"));
                option.transform.SetParent(PublicData.parent, false);
                option.transform.position = new Vector3(PublicData.currentPosition.x + 30, PublicData.currentPosition.y - 32, 0);
                PublicData.parent.GetComponent<Options_Triangle>().triangle.transform.eulerAngles = new Vector3(0, 0, -90);
                PublicData.parent.GetComponent<Options_Triangle>().children.Add(option);
                PublicData.parent = option;
                PublicData.currentPosition = new Vector2(PublicData.parent.position.x, PublicData.parent.position.y);
            }
        });
        add_options.onClick.AddListener(() =>
        {
            if (PublicData.parent == null)
            {
                return;
            }
            PublicData.parent.GetComponent<Options_Triangle>().triangle.transform.eulerAngles = new Vector3(0, 0, -90);
            Transform content = Instantiate(Resources.Load<Transform>("Options"));
            content.transform.SetParent(PublicData.parent, false);
            content.transform.position = new Vector3(PublicData.currentPosition.x + 16, PublicData.currentPosition.y - 32, 0);
            PublicData.parent.GetComponent<Options_Triangle>().children.Add(content);
            PublicData.currentPosition = new Vector2(content.position.x - 16, content.position.y);
        });
    }
}
复制代码

OK。将ClickEvent脚本挂载在场景中的任一物体身上就可以了


第三种实现效果

网络异常,图片无法展示
|

实现原理:这个也是用UGUI做的,比较有特点的地方是没有使用一行代码,使用VerticalLayoutGroup和ContentSizeFitter组件的自动排序功能和Button的OnClick组件控制子物体的显示与隐藏来实现层级菜单的功能。

优缺点:

优点是不需要代码控制,简单易用

缺点是需要提前堆砌UI,工作量比较大,然后改动的时候耗费精力大

实现过程:


1、新建Scroll View

网络异常,图片无法展示
|


2、父节点

网络异常,图片无法展示
|
网络异常,图片无法展示
|

父节点有一个Button和一个隐藏的Image

Button

网络异常,图片无法展示
|

有两个功能

网络异常,图片无法展示
|

第一个就是显示跟自己位置坐标一样的子物体BtnSelecteStyle,因为BtnSelecteStyle是Button的子物体,所以BtnSelecteStyle就会挡住Button,为啥要挡住呢,因为还需要BtnSelecteStyle的OnClick将子节点收起来 BtnSelecteStyle的OnClick挂载的功能:

网络异常,图片无法展示
|

第二个就是显示子节点的容器也就是ImgBtnParentLayout

这个ImgBtnParentLayout就是子节点的容器

网络异常,图片无法展示
|

下面是几个子节点

网络异常,图片无法展示
|

OK。可以了


第四种实现效果

网络异常,图片无法展示
|

实现原理:这个是用代码动态生成的,其中一个脚本主要用来创建父物体和子物体,以及父级关系,另一个脚本是设置位置,箭头变化,按钮功能的初始化

优缺点:

优点是代码清晰,结构明了,可以实现层级多级显示、多级目录的设置、树级菜单等

缺点是没有判断最后一个节点的代码,最后一个节点无法设置图片,最后一个节点的功能没有添加

实现过程:


1、首先也是制作预制体

网络异常,图片无法展示
|
网络异常,图片无法展示
|
网络异常,图片无法展示
|
网络异常,图片无法展示
|
网络异常,图片无法展示
|
网络异常,图片无法展示
|
网络异常,图片无法展示
|

ArrowButton和ArrowButton2都是为了控制子节点的关闭和显示,不同的是ArrowButton是左边的小按钮,还有一个图片显示的功能,ArrowButton2是整体的按钮,不显示,但是点击整体都可以实现显示和隐藏子节点的功能

资源:

网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|

图片是白的,仔细看一下还是能看到的 - -,然后保存下载,放到项目中去


2、编写脚本ItemPanelBase.cs 这个脚本是设置节点的位置,以及箭头切换的脚本

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public enum NameSort
{
    Default,
    Active,
    Passive
}
public class ItemPanelBase : MonoBehaviour
{
    private List<ItemPanelBase> childList;//子物体集合
    [HideInInspector]
    public Button downArrow;//下箭头按钮
    public Button downArrow2;//下箭头按钮
    public Sprite down, right, dot;
    public bool isOpen { get; set; }//子物体开启状态
    private Vector2 startSize;//起始大小
    NameSort m_NameSore = NameSort.Default;
    string m_Name;
    private void Awake()
    {
        childList = new List<ItemPanelBase>();
        downArrow = this.transform.Find("ContentPanel/ArrowButton").GetComponent<Button>();
        downArrow.onClick.AddListener(() =>
        {
            if (isOpen)
            {
                CloseChild();
                isOpen = false;
            }
            else
            {
                OpenChild();
                isOpen = true;
            }
        });
        downArrow2 = this.transform.Find("ContentPanel/ArrowButton2").GetComponent<Button>();
        downArrow2.onClick.AddListener(() =>
        {
            if (isOpen)
            {
                CloseChild();
                isOpen = false;
            }
            else
            {
                OpenChild();
                isOpen = true;
            }
        });
        startSize = this.GetComponent<RectTransform>().sizeDelta;
        isOpen = false;
    }
    //添加子物体到集合
    private void AddChild(ItemPanelBase parentItemPanelBase)
    {
        childList.Add(parentItemPanelBase);
        if (childList.Count >= 1)
        {
            downArrow.GetComponent<Image>().sprite = right;
        }
    }
    //设置当前对象的名字值
    public void SetName(string _name,NameSort m_sort)
    {
        m_Name = _name;
        m_NameSore = m_sort;
    }
    /// <summary>
    /// 设置父物体,父物体不为一级菜单
    /// </summary>
    /// <param name="parentItemPanelBase"></param>
    public void SetItemParent(ItemPanelBase parentItemPanelBase)
    {
        this.transform.parent = parentItemPanelBase.transform;
        parentItemPanelBase.AddChild(this);
        this.GetComponent<VerticalLayoutGroup>().padding = new RectOffset((int)parentItemPanelBase.downArrow.GetComponent<RectTransform>().sizeDelta.x, 0, 0, 0);
        if (parentItemPanelBase.isOpen)
        {
            this.GetComponent<ItemPanelBase>().AddParentSize((int)this.gameObject.GetComponent<RectTransform>().sizeDelta.y);
        }
        else
        {
            this.transform.gameObject.SetActive(false);
        }
    }
    /// <summary>
    /// 设置父物体,父物体为一级菜单
    /// </summary>
    /// <param name="tran"></param>
    public void SetBaseParent(Transform tran)
    {
        this.transform.parent = tran;
    }
    /// <summary>
    /// 填充Item数据
    /// </summary>
    /// <param name="_name">名字</param>
    public void InitPanelContent(string _name)
    {
        transform.Find("ContentPanel/Text").GetComponent<Text>().text = _name;
    }
    /// <summary>
    /// 增加一个子物体后更新Panel大小
    /// </summary>
    /// <param name="change"></param>
    public void UpdateRectTranSize(int change)
    {
        this.gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(startSize.x, this.gameObject.GetComponent<RectTransform>().sizeDelta.y + change);
    }
    /// <summary>
    /// 增加父物体高度
    /// </summary>
    /// <param name="parentItem"></param>
    /// <param name="change"></param>
    public void AddParentSize(int change)
    {
        if (this.transform.parent.GetComponent<ItemPanelBase>() != null)
        {
            this.transform.parent.GetComponent<ItemPanelBase>().UpdateRectTranSize(change);
            this.transform.parent.GetComponent<ItemPanelBase>().AddParentSize(change);
        }
    }
    /// <summary>
    /// 关闭子物体列表
    /// </summary>
    public void CloseChild()
    {
        if (childList.Count == 0) return;
        foreach (ItemPanelBase child in childList)
        {
            child.gameObject.SetActive(false);
            child.GetComponent<ItemPanelBase>().AddParentSize(-(int)child.gameObject.GetComponent<RectTransform>().sizeDelta.y);
        }
        downArrow.GetComponent<Image>().sprite = right;
    }
    /// <summary>
    /// 打开子物体列表
    /// </summary>
    public void OpenChild()
    {
        if (childList.Count == 0)
        {
            if (m_Name == "125K读卡器" && m_NameSore == NameSort.Active)
            {
                Debug.Log("125k设备");
            }
            return;
        }
        foreach (ItemPanelBase child in childList)
        {
            child.gameObject.SetActive(true);
            child.GetComponent<ItemPanelBase>().AddParentSize((int)child.gameObject.GetComponent<RectTransform>().sizeDelta.y);
        }
        downArrow.GetComponent<Image>().sprite = down;
    }
}
复制代码


3、编写脚本PullDownList.cs 这个就是创建层级菜单的脚本: 比较繁琐

using System.Collections.Generic;
using UnityEngine;
public class PullDownList : MonoBehaviour
{
    private List<GameObject> itemPanelList;
    public GameObject itemPanel;
    private void Awake()
    {
        itemPanelList = new List<GameObject>();
    }
    void Start()
    {
        for (int i = 0; i < 27; i++)
        {
            //一级菜单
            if(i == 0)
            {
                GameObject newItemPanel = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel);
                newItemPanel.GetComponent<ItemPanelBase>().SetBaseParent(this.transform);
                newItemPanel.GetComponent<ItemPanelBase>().InitPanelContent("层级一");
            }
            //二级菜单
            if (i == 1)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[0].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级二");
            }
            else if (i == 2)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[0].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级二");
            }
            //三级菜单
            else if (i == 3)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[1].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");
            }
            else if (i == 4)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[1].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");
            }
            else if (i == 5)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[1].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");
            }
            else if (i == 6)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[1].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");
            }
            else if (i == 7)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[2].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");
            }
            else if (i == 8)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[2].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");
            }
            else if (i == 9)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[2].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");
            }
            else if (i == 10)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[2].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级三");
            }
            //四级菜单
            else if (i == 11)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[3].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);
            }
            else if (i == 12)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[3].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);
            }
            else if (i == 13)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[4].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);
            }
            else if (i == 14)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[4].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);
            }
            else if (i == 15)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[5].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);
            }
            else if (i == 16)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[5].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);
            }
            else if (i == 17)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[6].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);
            }
            else if (i == 18)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[6].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Active);
            }
            else if (i == 19)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[7].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);
            }
            else if (i == 20)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[7].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);
            }
            else if (i == 21)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[8].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);
            }
            else if (i == 22)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[8].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);
            }
            else if (i == 23)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[9].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);
            }
            else if (i == 24)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[9].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);
            }
            else if (i == 25)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[10].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);
            }
            else if (i == 26)
            {
                GameObject newItemPanel2 = Instantiate(itemPanel);
                itemPanelList.Add(newItemPanel2);
                newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[10].GetComponent<ItemPanelBase>());
                newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent("层级四");
                newItemPanel2.GetComponent<ItemPanelBase>().SetName("层级四", NameSort.Passive);
            }
        }
    }
}
复制代码

将脚本挂载在Panel上面

网络异常,图片无法展示
|

OK,大功告成


第五种实现效果

网络异常,图片无法展示
|

实现原理:这个是用UI硬堆砌起来的层级菜单,然后通过代码控制对象的隐藏和显示,即可实现层级菜单的折叠与下拉功能,主要用到GridLayoutGroup组件来排序与更新

优缺点:

优点是操作简单,代码也简单,不需要太多的理解,然后可以显示多级菜单,多级内容,以及最后一个节点的功能与图片的设置功能

缺点是需要提前堆砌UI,可扩容性差,前期工作量大,然后后期修改工作量大,最重要的是我觉得这种实现方式蛮low的

实现过程:


1、显示制作UI Panel上面挂载GridLayoutGroup组件

网络异常,图片无法展示
|

制作UI

网络异常,图片无法展示
|
网络异常,图片无法展示
|

UI的话就很简单,一个Button下面两个子物体一个text一个Image,text是显示内容,image是显示箭头

这时候就有人问了,那子物体怎么办,子物体也是同样的结构

网络异常,图片无法展示
|

就是把image往后拉了一下

三级菜单也一样:

网络异常,图片无法展示
|

再加一个一级菜单:

网络异常,图片无法展示
|

是不是so easy....哈哈哈 真的好low

脚本功能就很简单 一级菜单控制它往下的所有子节点的隐藏于显示

网络异常,图片无法展示
|

二级菜单控制它往下的所有子节点的隐藏于显示

网络异常,图片无法展示
|

以此类推。。。。


2、编辑代码PullDown.cs

using UnityEngine;
using UnityEngine.UI;
public class PullDown : MonoBehaviour
{
    public Button m_Btn1;//一级菜单按钮
    public Button m_Btn2;//二级菜单按钮
    public Button m_Btn3;//三级菜单按钮
    bool m_is1;//全局参数 控制开关
    bool m_is2;//全局参数 控制开关
    void Start()
    {
        m_is1 = true;
        m_is2 = true;
        m_Btn1.onClick.AddListener(Btn1_Event);
        m_Btn2.onClick.AddListener(Btn2_Event);
    }
    public void Btn1_Event()
    {
        if (m_is1)
        {
            m_Btn2.gameObject.SetActive(false);
            m_Btn3.gameObject.SetActive(false);
            m_is1 = false;
        }
        else
        {
            m_Btn2.gameObject.SetActive(true);
            m_Btn3.gameObject.SetActive(true);
            m_is1 = true;
        }
    }
    public void Btn2_Event()
    {
        if (m_is2)
        {
            m_Btn3.gameObject.SetActive(false);
            m_is2 = false;
        }
        else
        {
            m_Btn3.gameObject.SetActive(true);
            m_is1 = true;
        }
    }
}
复制代码

OK了,快去试试吧



相关文章
|
3月前
|
开发框架 前端开发 搜索推荐
在WInform开发中实现工具栏/菜单的动态呈现
在WInform开发中实现工具栏/菜单的动态呈现
|
6月前
|
iOS开发
Xcode强大的多视图立体分层显示View UI Herarchy
Xcode强大的多视图立体分层显示View UI Herarchy
58 0
|
图形学
|
前端开发 C++
qt 如何设计好布局和漂亮的界面。
qt 如何设计好布局和漂亮的界面。
1104 1
qt 如何设计好布局和漂亮的界面。
|
前端开发 vr&ar 图形学
UGUI系列-UI菜单列表,滑动展示UI(Unity3D)
物体或者UI的在平面上的旋转展示的代码实现,这个功能也是用的比较多的模块,可以将这个代码做成模板,在以后的项目中都会用到。
UGUI系列-列表添加物理效果(Unity3D)
最近要做一个滑动列表界面,美术的效果图为用绳子连接的短板,上面附带信息,看图的感觉似乎添加点物理效果(让绳子不规则的带动短板晃动)会显得更加真实,于是为这个界面加了些物理效果,感觉还不错,特此记录下。
Qt-网易云音乐界面实现-1 窗口隐藏拖拽移动,自定义标题栏
最近也换了公司,也换了新的工作,工资也象征性的涨了一点点,但是最近心里还是慌慌,不知道为什么,没有那种踏实感,感觉自己随时可以被抛弃的感觉。感觉自己在荒废时间,也感觉自己在浪费生命。
301 0
Qt-网易云音乐界面实现-1 窗口隐藏拖拽移动,自定义标题栏
|
前端开发 C# 图形学
【Unity使用UGUI实现王者荣耀UI界面(一)】加载页面(进度条)
【Unity使用UGUI实现王者荣耀UI界面(一)】加载页面(进度条)
738 0
【Unity使用UGUI实现王者荣耀UI界面(一)】加载页面(进度条)
|
图形学
Unity 基础 之 自定义编辑器布局
Unity 是一个强大的开发引擎,一起来认识一下编辑器布局吧。看看如何才能调整出你想要的布局吧,调整后果然舒适哦~
454 0
|
调度 Windows C#
理解 UWP 视图的概念,让 UWP 应用显示多个窗口(多视图)
原文 理解 UWP 视图的概念,让 UWP 应用显示多个窗口(多视图) UWP 应用多是一个窗口完成所有业务的,事实上我也推荐使用这种单一窗口的方式。不过,总有一些特别的情况下我们需要用到不止一个窗口,那么 UWP 中如何使用多窗口呢? 本文内容 为什么 UWP 需要多窗口? UWP 视图的概念 UWP 多窗口 管理多个 UWP 视图 参考资料 为什么 UWP 需要多窗口? 多窗口在传统 Win32 的开发当中是司空见惯的事儿了,不过我个人非常不喜欢,因为 Windows 系统上的多窗口太多坑。
1642 0