实现UI多层级多选框

创建Scroll View

设置Content锚点参数添加组件

创建预制体Item添加toggle组件

新建Content添加组件设置锚点

准备工作完成后开始编写代码

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

public class XMLToScrollView : MonoBehaviour
{
    public RectTransform scrollContent;
    public GameObject nodePrefab;
    public GameObject leafPrefab;
    public GameObject partPrefab;

    private Dictionary<string, bool> selectedParts = new Dictionary<string, bool>();

    void Start()
    {
        LoadXMLData(Application.streamingAssetsPath+ "/Configs/dataConfig_pz.xml");
    }

     void LoadXMLData(string xmlPath)
    {
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(xmlPath);
        XmlNode root = xmlDoc.DocumentElement;

        foreach (XmlNode node in root.ChildNodes)
        {
            GameObject nodeObj = Instantiate(nodePrefab, scrollContent);
            Toggle nodeToggle = nodeObj.GetComponent<Toggle>();
            nodeObj.GetComponentInChildren<Text>().text =  node.Attributes["name"].Value;
            nodeToggle.onValueChanged.AddListener(delegate { OnNodeToggleChanged(nodeToggle, nodeObj.transform.Find("Content")); });
            float nodeHeight = 0;

              foreach (XmlNode leaf1 in node.ChildNodes)
            {
                GameObject leafObj1 = Instantiate(leafPrefab, nodeObj.transform.Find("Content"));
                Toggle leafToggle1 = leafObj1.GetComponent<Toggle>();
                leafObj1.GetComponentInChildren<Text>().text = leaf1.Attributes["name"].Value;
                leafToggle1.onValueChanged.AddListener(delegate { OnLeafToggleChanged(leafToggle1, leafObj1.transform.Find("Content")); });
                float leaf1Height = 0;

                foreach (XmlNode leaf2 in leaf1.ChildNodes)
                {
                    GameObject leafObj2 = Instantiate(leafPrefab, leafObj1.transform.Find("Content"));
                    Toggle leafToggle2 = leafObj2.GetComponent<Toggle>();
                    leafObj2.GetComponentInChildren<Text>().text = leaf2.Attributes["name"].Value;
                    leafToggle2.onValueChanged.AddListener(delegate { OnLeafToggleChanged(leafToggle2, leafObj2.transform.Find("Content")); });
                    float leaf2Height = 0;
                    XmlNodeList partList = leaf2.ChildNodes;
                    foreach (XmlNode part in partList[0].ChildNodes)
                    {
                        GameObject partObj = Instantiate(partPrefab, leafObj2.transform.Find("Content"));
                        Toggle partToggle = partObj.GetComponent<Toggle>();
                        partObj.GetComponentInChildren<Text>().text = part.Attributes["step"].Value;
                        string partId = part.Attributes["id"].Value;
                        partToggle.onValueChanged.AddListener(delegate { OnPartToggleChanged(node.Attributes["name"].Value + "&" + leaf1.Attributes["name"].Value + "&" + leaf2.Attributes["name"].Value + "&" + part.Attributes["id"].Value, partToggle.isOn); });
                         //selectedParts.Add(node.Attributes["name"].Value + "&"+ leaf1.Attributes["name"].Value+"&"+ leaf2.Attributes["name"].Value+ "&"+part.Attributes["id"].Value, partToggle);

                        leaf2Height += AdjustHeight(partObj);
                    }

                    leaf1Height += AdjustHeight(leafObj2, leaf2Height);
                }

                nodeHeight += AdjustHeight(leafObj1, leaf1Height);
            }

            AdjustHeight(nodeObj, nodeHeight);

            // 设置 Toggle 选择状态时,子级同步
            nodeToggle.onValueChanged.AddListener(isOn => SetChildrenToggleState(nodeObj.transform, isOn));
        }
    }
    void OnNodeToggleChanged(Toggle nodeToggle, Transform nodeTransform)
    {
        SetChildrenToggles(nodeTransform, nodeToggle.isOn);
    }

    void OnLeafToggleChanged(Toggle leafToggle, Transform leafTransform)
    {
        SetChildrenToggles(leafTransform, leafToggle.isOn);
    }
void OnPartToggleChanged(string partId, bool isOn)
    {
        if (selectedParts.ContainsKey(partId))
        {
            selectedParts[partId] = isOn;
        }
        else
        {
            selectedParts.Add(partId, isOn);
        }
    }
void SetChildrenToggles(Transform parent, bool isOn)
    {
        foreach (Transform child in parent)
        {
            Toggle childToggle = child.GetComponentInChildren<Toggle>();
            if (childToggle != null)
            {
                childToggle.isOn = isOn;
                SetChildrenToggles(child, isOn); // 递归设置子节点
            }
        }
    }

 float AdjustHeight(GameObject obj, float additionalHeight = 0f)
    {
        RectTransform rect = obj.GetComponent<RectTransform>();
        float originalHeight = rect.rect.height;
        float newHeight = originalHeight + additionalHeight;
        rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, newHeight);
        return newHeight;
    }

    void SetChildrenToggleState(Transform parent, bool isOn)
    {
        foreach (Transform child in parent)
        {
            Toggle toggle = child.GetComponent<Toggle>();
            if (toggle != null)
            {
                toggle.isOn = isOn;
                SetChildrenToggleState(child, isOn); // 递归设置子级状态
            }
        }
    }
     //获取当前选中ID
    public List<string> GetSelectedPartIds()
    {
        List<string> selectedPartIds = new List<string>();

        foreach (var partToggle in selectedParts)
        {
            if (partToggle.Value)
            {
                selectedPartIds.Add(partToggle.Key);
            }
        }

        return selectedPartIds;
    }
}

编写好脚本需求添加变量

测试调用GetSelectedPartIds()方法遍历可以查看选中数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值