unity 三级下拉菜单(树形下拉菜单UGUI)
- 最新项目需求要求做一个下拉菜单列表(树形下拉菜单)。但UGUI并没有原生的插件,只能自己实现。
思路每个级的ItemPanel(一个单级菜单条)样式是一样的,于是需要一个panel来装所有的itemPanel,在整个菜单 顶部panel上添加vertically layout group组件,使下面的子菜单从上到下依次排列。文章最后会附上 demo下载地址 - 效果图
- 具体实现新建Canvas->Panel,
粘出部分代码,详细可以下载demo
控制端
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 < 10; i++)
{
GameObject newItemPanel = Instantiate(itemPanel);
itemPanelList.Add(newItemPanel);
newItemPanel.GetComponent<ItemPanelBase>().SetBaseParent(this.transform);
newItemPanel.GetComponent<ItemPanelBase>().InitPanelContent(new ItemBean("一级菜单" + i, i));
}
for (int i = 0; i < 5; i++)
{
GameObject newItemPanel2 = Instantiate(itemPanel);
itemPanelList.Add(newItemPanel2);
newItemPanel2.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[i].GetComponent<ItemPanelBase>());
newItemPanel2.GetComponent<ItemPanelBase>().InitPanelContent(new ItemBean("二级菜单" + i, i));
}
for (int i = 0; i < 2; i++)
{
GameObject newItemPanel3 = Instantiate(itemPanel);
itemPanelList.Add(newItemPanel3);
newItemPanel3.GetComponent<ItemPanelBase>().SetItemParent(itemPanelList[11].GetComponent<ItemPanelBase>());
newItemPanel3.GetComponent<ItemPanelBase>().InitPanelContent(new ItemBean("三级菜单" + i, i));
}
}
}
itempanel端
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ItemPanelBase : MonoBehaviour
{
private List<ItemPanelBase> childList;
[HideInInspector]
public Button downArrow;
public Sprite down, right,dot;
public bool isOpen { get; set; }
private Vector2 startSize;
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;
}
});
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 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);
}
}
public void SetBaseParent(Transform tran)
{
this.transform.parent = tran;
}
public void UpdateRectTranSize(int change)
{
this.gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(startSize.x, this.gameObject.GetComponent<RectTransform>().sizeDelta.y + change);
}
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);
}
}
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;
}
public void OpenChild()
{
if (childList.Count == 0) 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;
}
public virtual void InitPanelContent(ItemBeanbase itemBeanbase) { }
}
- 最后附上项目地址 demo下载地址
|