Unity用UGUI实现简单的TreeView

创建TreeItem使用的Prefab

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

场景中创建一个TreeView

在这里插入图片描述
在这里插入图片描述

全部代码

public class TreeView : MonoBehaviour
{
    
    
    [SerializeField] private GameObject ItemPrefab;
    public Action<TreeItem> OnItemClick;
    public void LoadTree(IEnumerable<TreeItem> treeTtems)
    {
    
    
        LoadTree(treeTtems, transform);
    }
    private void LoadTree(IEnumerable<TreeItem> treeTtems, Transform _itemParentTran, TreeItem _itemParent = null)
    {
    
    
        foreach (TreeItem treeItem in treeTtems)
        {
    
    
            var itemTran = Instantiate(ItemPrefab, _itemParentTran).GetComponent<RectTransform>();
            var itemButton = itemTran.Find("Content").GetComponent<Button>();
            var headText = itemButton.transform.Find("Text").GetComponent<Text>();
            headText.text = treeItem.Name;
            if (treeItem.Height == 0) treeItem.Height = ItemPrefab.GetComponent<RectTransform>().sizeDelta.y;
            treeItem.transform = itemTran;
            treeItem.parent = _itemParent;
            itemButton.onClick.AddListener(() =>
            {
    
    
                treeItem.IsOpen = !treeItem.IsOpen;

                itemTran.DOSizeDelta(new Vector2(itemTran.sizeDelta.x, treeItem.GetRealHeight()), 0.2f);

                treeItem.parent.ResetHeight();

                OnItemClick?.Invoke(treeItem);
            });
            var childParent = itemTran.Find("Children");
            if (treeItem.Children != null && treeItem.Children.Count() > 0)
            {
    
    
                LoadTree(treeItem.Children, childParent, treeItem);
            }
            if (treeItem.IsOpen) itemTran.sizeDelta = new Vector2(itemTran.sizeDelta.x, treeItem.GetRealHeight());

            LayoutRebuilder.ForceRebuildLayoutImmediate(itemTran);
        }
    }
}
/// <summary>
/// TreeView的Item
/// </summary>
public class TreeItem
{
    
    
    /// <summary>
    /// TreeItem的<see cref="Transform"/>
    /// </summary>
    public Transform transform {
    
     get; set; }
    /// <summary>
    /// TreeItem的父级
    /// </summary>
    public TreeItem parent {
    
     get; set; }
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    /// <summary>
    /// 子级集合
    /// </summary>
    public IEnumerable<TreeItem> Children {
    
     get; set; }
    /// <summary>
    /// 是否展开/打开
    /// </summary>
    public bool IsOpen {
    
     get; set; }
    /// <summary>
    /// 高度,如果没有指定则获取Prefab的高度
    /// </summary>
    public float Height {
    
     get; set; }
}
public static class TreeItemBaseExtension
{
    
    
    /// <summary>
    /// 获取真实高度(包含子列表的高度)
    /// </summary>
    /// <param name="item"></param>
    /// <returns></returns>
    public static float GetRealHeight(this TreeItem item)
    {
    
    
        float tempHeight = 0f;
        getChildrenHeight(item, ref tempHeight);
        return tempHeight;
    }
    private static void getChildrenHeight(TreeItem treeItem, ref float height)
    {
    
    
        height += treeItem.Height;
        if (treeItem.IsOpen && treeItem.Children != null)
        {
    
    
            foreach (var item in treeItem.Children)
            {
    
    
                getChildrenHeight(item, ref height);
            }
        }
    }
    /// <summary>
    /// 刷新父级高度
    /// </summary>
    /// <param name="treeItem"></param>
    public static void ResetHeight(this TreeItem treeItem)
    {
    
    
        if (treeItem != null)
        {
    
    
            var rect = treeItem.transform.GetComponent<RectTransform>();

            rect.DOSizeDelta(new Vector2(rect.sizeDelta.x, treeItem.GetRealHeight()), 0.2f);

            treeItem.parent.ResetHeight();
        }
    }
    /// <summary>
    /// 是否存在子列表
    /// </summary>
    /// <param name="treeItem"></param>
    /// <returns></returns>
    public static bool HasChild(this TreeItem treeItem)
    {
    
    
        return treeItem.Children != null;
    }
}

调用

        treeView.LoadTree(list);
        treeView.OnItemClick += item =>
        {
    
    
            if (!item.HasChild())
                Debug.Log(item.Name);
        };

猜你喜欢

转载自blog.csdn.net/u010197227/article/details/126589191