Unity3D利用VerticalLayoutGroup组件制作(折叠菜单、树状菜单)

先上效果图Unity3D利用VerticalLayoutGroup组件制作(折叠菜单、树状菜单)_第1张图片
本文利用VerticalLayoutGroup组件动态生成目录,目录数据由文件目录转换而成。无需其他设置。只需将TreeMenuCheckBox脚本挂载到某个对象上 然后指定属性面板的值既可。
Unity3D利用VerticalLayoutGroup组件制作(折叠菜单、树状菜单)_第2张图片
直接上代码 一共两个脚本 TreeMenuCheckBox负责创建目录 UIMenuClick负责点击事件的监听

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class UIMenuClick : MonoBehaviour ,IPointerUpHandler,IPointerDownHandler,IDragHandler,IBeginDragHandler,IEndDragHandler{
     
    public GameObject Group = null;
    public GameObject Identifying = null;
    public System.Action<RectTransform> Refresh;
    private bool IsDrag = false;
    public void OnBeginDrag(PointerEventData eventData)
    {
     
        IsDrag = true;
        GetParntScrollRect().OnBeginDrag(eventData);
    }
    public void OnDrag(PointerEventData eventData)
    {
     
        GetParntScrollRect().OnDrag(eventData);
    }
    public void OnEndDrag(PointerEventData eventData)
    {
     
        IsDrag = false;
        GetParntScrollRect().OnEndDrag(eventData);
    }
    public void OnPointerDown(PointerEventData eventData)
    {
     
    }
    public void OnPointerUp(PointerEventData eventData)
    {
     
        if (IsDrag)
            return;
        if (Group!=null)
        {
     
            Group.SetActive(!Group.activeSelf);
            RefreshIdentifying();
            Refresh?.Invoke(Group.GetComponent<RectTransform>());
        }
    }
    public static UnityEngine.UI.ScrollRect scrollRect;
    public UnityEngine.UI.ScrollRect GetParntScrollRect()
    {
     
        if (scrollRect==null)
            scrollRect = GameObject.FindObjectOfType<TreeMenuCheckBox>().GetComponent<UnityEngine.UI.ScrollRect>();
        return scrollRect;
    }
    /// 
    /// 刷新标识箭头
    /// 
    public void RefreshIdentifying()
    {
     
        if (Identifying!=null)
            Identifying.transform.localEulerAngles = new Vector3(0, 0, Group ? Group.activeSelf ? -90 : 0 : 0);
    }
}
public class TreeMenuCheckBox : MonoBehaviour {
     
    [Header("字体")]
    public Font font;
    [Header("标识图")]
    public Sprite Ide;
    public Catalog data = new Catalog();
    [Header("窗口根节点")]
    public Transform Content;
    [Header("默认展开?")]
    public bool IsUnfold = false;
    void Start () {
     
       if (font==null)
        {
     
            Debug.Log("[请设置Font]");
            return;
        }
        #region  通过文件夹获取树状结构数据  也可以通过其他方式给 Catalog 赋值
        DirectoryInfo dir = new DirectoryInfo(Application.streamingAssetsPath+"/data");
        DirectoryInfo[] dirs = dir.GetDirectories();
        for (int i = 0; i < dirs.Length; i++)
        {
     
            GetMenus(dirs[i],data.Data);
        }
        #endregion
        Create();
        Refresh(Content.GetComponent<RectTransform>());
    }
     public void GetMenus(DirectoryInfo info, List<Catalog.CatalogData> data)
    {
     
        data.Add(new Catalog.CatalogData(info.Name));
        DirectoryInfo[] dirs = info.GetDirectories();
        for (int i = 0; i < dirs.Length; i++)
        {
     
            GetMenus(dirs[i], data[data.Count-1].Data);
        }
    }
     /// 
    /// 创建树形目录
    /// 
    public void Create()
    {
     
        CreateNode(Content,data.Data);
        Debug.Log("创建目录完毕");
    }
     /// 
    /// 创建节点
    /// 
    /// 
    /// 
    public void CreateNode(Transform parnt, List<Catalog.CatalogData> data)
    {
     
        for (int i = 0; i < data.Count; i++)
        {
     
            #region 创建菜单
            GameObject menu = new GameObject(data[i].MenuName);
            Image image= menu.AddComponent<Image>();
            image.color = Color.gray;
            menu.transform.SetParent(parnt);
            menu.transform.localScale = Vector3.one;
            menu.GetComponent<RectTransform>().sizeDelta = new Vector2(400,50);
             #endregion
             #region  创建菜单下的文字
            GameObject label = new GameObject(data[i].MenuName);
            label.transform.SetParent(menu.transform);
            label.transform.localScale = Vector3.one;
            Text text = label.AddComponent<Text>();
            text.font = font;
            text.text = data[i].MenuName;
            text.fontSize = 26;
            text.fontStyle = FontStyle.Normal;
            text.alignment = TextAnchor.MiddleCenter;
            RectTransform rect = label.GetComponent<RectTransform>();
            rect.sizeDelta = new Vector2(400, 50);   
            #endregion
            #region  添加菜单的监听事件
            UIMenuClick menuClick = menu.AddComponent<UIMenuClick>();
            menuClick.Group = null;
            menuClick.Refresh = Refresh;
            GameObject identifying = new GameObject("identifying");
            Image ima = identifying.AddComponent<Image>();
            ima.sprite= Ide;
            ima.SetNativeSize();
            identifying.transform.SetParent(menu.transform);
            identifying.transform.localScale = Vector3.one;
            rect = identifying.GetComponent<RectTransform>();
            rect.pivot = new Vector2(0.5f,0.5f);
            rect.localPosition = new Vector3(-(menu.GetComponent<RectTransform>().sizeDelta.x/2f)-10f- rect.sizeDelta.x/2f, 0);
            identifying.SetActive(false);
            menuClick.Identifying = identifying;
            #endregion
		 #region  创建当前菜单下的节点
	    if (data[i].Data.Count>0)
            {
     
                GameObject group = new GameObject(data[i].MenuName+ "_Group");
                menuClick.Group = group;
                group.transform.SetParent(parnt);
                group.transform.localScale = Vector3.one;
                group.AddComponent<RectTransform>().sizeDelta = new Vector2(400, 0);
                VerticalLayoutGroup layoutGroup = group.AddComponent<VerticalLayoutGroup>();
                layoutGroup.padding.left = 50;
                //group.padding.top = (int)a.GetComponent().sizeDelta.y;
                layoutGroup.spacing = 10f;
                layoutGroup.childControlHeight = false;
                layoutGroup.childControlWidth = false;
                group.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
                CreateNode(group.transform, data[i].Data);
                group.SetActive(IsUnfold);
                identifying.SetActive(true);
                menuClick.RefreshIdentifying();
                LayoutRebuilder.ForceRebuildLayoutImmediate(group.GetComponent<RectTransform>());
            }
              #endregion
        }
    }
     /// 
    /// 刷新UI布局
    /// 
    /// 
     public void Refresh(RectTransform rect)
     {
     
		 LayoutRebuilder.ForceRebuildLayoutImmediate(rect);
		 if (rect.parent!=null)
           {
     
           	 if (rect.parent.GetComponent<RectTransform>()!=null)
           	 {
     
               	 Refresh(rect.parent.GetComponent<RectTransform>());
           	 }
           }
     }
}

Content 根节点须手动添加VerticalLayoutGroup 组件和ContentSizeFitter组件
本人的ScrollRect宽度为450.
Unity3D利用VerticalLayoutGroup组件制作(折叠菜单、树状菜单)_第3张图片
目录数据放在StreamingAssets目录下 大家也可以根据自己的需求做一些改变
Unity3D利用VerticalLayoutGroup组件制作(折叠菜单、树状菜单)_第4张图片

补充:少了一点代码

public class Catalog
{
     
 	 public List<CatalogData> Data = new List<CatalogData>();  
	 public class CatalogData
 	 {
     
  		public string MenuName="";
      		  public List<CatalogData> Data = new List<CatalogData>();
       		 public CatalogData(string name)
       		 {
     
        		    MenuName = name;
       		 }
	}

}

Unity3D利用VerticalLayoutGroup组件制作(折叠菜单、树状菜单) 二

你可能感兴趣的:(Unity3D利用VerticalLayoutGroup组件制作(折叠菜单、树状菜单))