Version: 6000.3
语言: 中文
结构 UI 示例
创建复杂的列表视图

创建列表视图和树视图

列表视图和树视图是 UI 设计中的常见功能。你可以使用 UI 工具包在自定义编辑器窗口或运行时中创建列表视图和树视图。此示例演示如何在自定义编辑器窗口中创建列表视图和树视图。您可以使用 UXML 配置列表和树的结构,然后在 C# 脚本中动态填充它们。

示例概述

此示例创建了四个编辑器窗口,其中显示以下内容:

  • 单列行星列表
  • 具有两列的行星列表
  • 行星的树状视图
  • 具有两列的行星的树形视图

您可以在此 GitHub 存储库中找到此示例创建的已完成文件。

先决条件

本指南适用于熟悉 Unity 编辑器、UI 工具包和 C# 脚本的开发人员。在开始之前,请熟悉以下内容:

在 C 中创建数据#

在由两组行星组成的 C# 脚本中创建数据,该脚本和根节点动画层次结构中的转换,允许 Unity 在通用模型的动画剪辑之间建立一致性。它还使 Unity 能够在尚未“就地”创作的动画之间正确混合(即,整个模型在动画时移动其世界位置的位置)。更多信息
请参阅术语表
用于树视图。

  1. 使用任何模板在 Unity 中创建项目。

  2. 在您的项目窗口一个窗口,显示您的内容Assets文件夹(项目选项卡)更多信息
    术语表中查看
    ,创建一个名为Editor.

  3. Editor文件夹中,创建一个名为PlanetsWindow.cs.

  4. 替换PlanetsWindow.cs替换为以下内容:

    using System.Collections.Generic;
    using UnityEngine;
    using UnityEditor;
    using UnityEngine.UIElements;
    
    // Base class for all windows that display planet information.
    public class PlanetsWindow : EditorWindow
    {
        [SerializeField]
        protected VisualTreeAsset uxmlAsset;
    
        // Nested interface that can be either a single planet or a group of planets.
        protected interface IPlanetOrGroup
        {
            public string name
            {
                get;
            }
    
            public bool populated
            {
                get;
            }
        }
    
        // Nested class that represents a planet.
        protected class Planet : IPlanetOrGroup
        {
            public string name
            {
                get;
            }
    
            public bool populated
            {
                get;
            }
    
            public Planet(string name, bool populated = false)
            {
                this.name = name;
                this.populated = populated;
            }
        }
    
        // Nested class that represents a group of planets.
        protected class PlanetGroup : IPlanetOrGroup
        {
            public string name
            {
                get;
            }
    
            public bool populated
            {
                get
                {
                    var anyPlanetPopulated = false;
                    foreach (Planet planet in planets)
                    {
                        anyPlanetPopulated = anyPlanetPopulated || planet.populated;
                    }
                    return anyPlanetPopulated;
                }
            }
    
            public readonly IReadOnlyList<Planet> planets;
    
            public PlanetGroup(string name, IReadOnlyList<Planet> planets)
            {
                this.name = name;
                this.planets = planets;
            }
        }
    
        // Data about planets in our solar system.
        protected static readonly List<PlanetGroup> planetGroups = new List<PlanetGroup>
        {
            new PlanetGroup("Inner Planets", new List<Planet>
            {
                new Planet("Mercury"),
                new Planet("Venus"),
                new Planet("Earth", true),
                new Planet("Mars")
            }),
            new PlanetGroup("Outer Planets", new List<Planet>
            {
                new Planet("Jupiter"),
                new Planet("Saturn"),
                new Planet("Uranus"),
                new Planet("Neptune")
            })
        };
    
        // Expresses planet data as a list of the planets themselves. Needed for ListView and MultiColumnListView.
        protected static List<Planet> planets
        {
            get
            {
                var retVal = new List<Planet>(8);
                foreach (var group in planetGroups)
                {
                    retVal.AddRange(group.planets);
                }
                return retVal;
            }
        }
    
        // Expresses planet data as a list of TreeViewItemData objects. Needed for TreeView and MultiColumnTreeView.
        protected static IList<TreeViewItemData<IPlanetOrGroup>> treeRoots
        {
            get
            {
                int id = 0;
                var roots = new List<TreeViewItemData<IPlanetOrGroup>>(planetGroups.Count);
                foreach (var group in planetGroups)
                {
                    var planetsInGroup = new List<TreeViewItemData<IPlanetOrGroup>>(group.planets.Count);
                    foreach (var planet in group.planets)
                    {
                        planetsInGroup.Add(new TreeViewItemData<IPlanetOrGroup>(id++, planet));
                    }
    
                    roots.Add(new TreeViewItemData<IPlanetOrGroup>(id++, group, planetsInGroup));
                }
                return roots;
            }
        }
    }
    

创建列表视图

若要创建列表视图,请先使用 UI 生成器创建 ListView UI 控件。然后,使用 ListView 创建自定义编辑器窗口,并在 C# 脚本中定义获取列表数据的位置。最后,将 UXML 文件引用到 C# 脚本。

  1. 右键单击Editor文件夹。

  2. 选择 创建>UI 工具包 > 编辑器窗口

  3. 在“C#”框中,输入PlanetsListView并清除 USS 复选框。这将创建两个文件:PlanetsListView.uxmlPlanetsListView.cs.

  4. 双击PlanetsListView.uxml在 UI Builder 中打开它。

  5. 在“层次结构”窗口中,删除“标签”控件并添加“ListView”控件。

  6. 在“层次结构”窗口中选择 ListView 控件。

  7. 检查器一个 Unity 窗口,显示有关当前选定游戏对象、资产或项目设置的信息,允许您检查和编辑值。更多信息
    请参阅术语表
    窗口中,将“固定项目高度”设置为 20。

  8. 保存您的更改。你PlanetsListView.uxml应如下所示:

    <ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
        <ui:ListView fixed-item-height="20" />
    </ui:UXML>
    
  9. 替换PlanetsListView.cs替换为以下内容:

    using UnityEditor;
    using UnityEngine.UIElements;
    
    public class PlanetsListView : PlanetsWindow
    {
        [MenuItem("Planets/Standard List")]
        static void Summon()
        {
            GetWindow<PlanetsListView>("Standard Planet List");
        }
    
        void CreateGUI()
        {
            // The protected variable 'uxmlAsset' is a VisualTreeAsset defined in the parent 
            // class PlanetsWindow.
            uxmlAsset.CloneTree(rootVisualElement);
            var listView = rootVisualElement.Q<ListView>();
    
            // Set ListView.itemsSource to populate the data in the list.
            listView.itemsSource = planets;
    
            // Set ListView.makeItem to initialize each entry in the list.
            listView.makeItem = () => new Label();
    
            // Set ListView.bindItem to bind an initialized entry to a data item.
            listView.bindItem = (VisualElement element, int index) =>
                (element as Label).text = planets[index].name;
        }
    }
    
  10. 在 Unity 中,选择PlanetsListView.cs,然后拖动PlanetsListView.uxml检查器中的 Uxml 字段中。

  11. 从菜单中,选择 行星>标准列表 以查看行星列表。

Unity 编辑器窗口中的行星列表。
Unity 编辑器窗口中的行星列表。

创建包含多列的列表视图

要创建具有多列的列表视图,请首先创建一个MultiColumnListView UI控件,并在UXML文件中定义列数和列标题。然后,使用 MultiColumnListView 创建自定义编辑器窗口,并定义在 C# 脚本中获取每列中列表数据的位置。最后,将 UXML 文件引用到 C# 脚本。

  1. 右键单击Editor文件夹。

  2. 选择 创建>UI 工具包>UI 文档(Create UI Toolkit) 以创建一个UXML文件,并将其命名为PlanetsMultiColumnListView.uxml.

  3. 打开PlanetsMultiColumnListView.uxml在文本编辑器中。

  4. 替换PlanetsMultiColumnListView.uxml替换为以下内容:

    <ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
        <ui:MultiColumnListView fixed-item-height="20">
            <!-- Columns and Column aren't Visual Elements or controls. They are considered attributes of MultiColumnListView. -->
            <ui:Columns>
                <ui:Column name="name" title="Name" width="80" />
                <ui:Column name="populated" title="Populated?" width="80" />
            </ui:Columns>
        </ui:MultiColumnListView>
    </ui:UXML>
    
  5. Editor文件夹中,创建一个名为PlanetsMultiColumnListView.cs.

  6. 替换PlanetsMultiColumnListView.cs替换为以下内容:

    using UnityEditor;
    using UnityEngine.UIElements;
    
    public class PlanetsMultiColumnListView : PlanetsWindow
    {
        [MenuItem("Planets/Multicolumn List")]
        static void Summon()
        {
            GetWindow<PlanetsMultiColumnListView>("Multicolumn Planet List");
        }
    
        void CreateGUI()
        {
            // The protected variable 'uxmlAsset' is a VisualTreeAsset defined in the parent 
            // class PlanetsWindow.
            uxmlAsset.CloneTree(rootVisualElement);
            var listView = rootVisualElement.Q<MultiColumnListView>();
    
            // Set MultiColumnListView.itemsSource to populate the data in the list.
            listView.itemsSource = planets;
    
            // For each column, set Column.makeCell to initialize each cell in the column.
            // You can index the columns array with names or numerical indices.
            listView.columns["name"].makeCell = () => new Label();
            listView.columns["populated"].makeCell = () => new Toggle();
    
            // For each column, set Column.bindCell to bind an initialized cell to a data item.
            listView.columns["name"].bindCell = (VisualElement element, int index) =>
                (element as Label).text = planets[index].name;
            listView.columns["populated"].bindCell = (VisualElement element, int index) =>
                (element as Toggle).value = planets[index].populated;
        }
    }
    
  7. 在 Unity 中,选择PlanetsMultiColumnListView.cs在“项目”窗口中。

  8. PlanetsMultiColumnListView.uxml检查器中的 Uxml 字段中。

  9. 从菜单中,选择行星>多列列表以查看两列列表。一列有行星列表。另一列有指示行星是否有人居住的开关。

Unity 编辑器窗口中的一个列表,其中包含两列,一列用于行星,另一列带有指示行星是否已填充的复选框。
Unity 编辑器窗口中的一个列表,其中包含两列,一列用于行星,另一列带有指示行星是否已填充的复选框。

创建树视图

要在自定义编辑器中创建树视图,请先在 UXML 文件中创建 TreeView UI 控件。然后,使用 TreeView 创建一个自定义编辑器窗口,并通过 C# 脚本定义从何处获取树节点的数据。最后,将 UXML 文件引用到 C# 脚本。

  1. Editor文件夹中,创建一个名为PlanetsTreeView.uxml.

  2. 替换PlanetsTreeView.uxml替换为以下内容:

    <ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
        <ui:TreeView fixed-item-height="20" />
    </ui:UXML>
    
  3. Editor文件夹中,创建一个名为PlanetsTreeView.cs.

  4. 替换PlanetsTreeView.cs替换为以下内容:

    using UnityEditor;
    using UnityEngine.UIElements;
    
    public class PlanetsTreeView : PlanetsWindow
    {
        [MenuItem("Planets/Standard Tree")]
        static void Summon()
        {
            GetWindow<PlanetsTreeView>("Standard Planet Tree");
        }
    
        void CreateGUI()
        {
            // The protected variable 'uxmlAsset' is a VisualTreeAsset defined in the parent 
            // class PlanetsWindow.
            uxmlAsset.CloneTree(rootVisualElement);
            var treeView = rootVisualElement.Q<TreeView>();
    
            // Call TreeView.SetRootItems() to populate the data in the tree.
            treeView.SetRootItems(treeRoots);
    
            // Set TreeView.makeItem to initialize each node in the tree.
            treeView.makeItem = () => new Label();
    
            // Set TreeView.bindItem to bind an initialized node to a data item.
            treeView.bindItem = (VisualElement element, int index) =>
                (element as Label).text = treeView.GetItemDataForIndex<IPlanetOrGroup>(index).name;
        }
    }
    
  5. 在 Unity 中,选择PlanetsTreeView.cs在“项目”窗口中。

  6. PlanetsTreeView.uxml检查器中的 Uxml 字段中。

  7. 从菜单中,选择 行星(Planets) > 标准树(Standard Tree) 以查看按节点分组的两个行星列表。每个节点旁边都有一个箭头。如果选择箭头,窗口将显示组中的行星。

Unity 编辑器窗口中的列表,分为两个折叠部分:“内行星”和“外行星”。
Unity 编辑器窗口中的列表,分为两个折叠部分:“内行星”和“外行星”。

创建具有多列的树视图

要在自定义编辑器中创建具有多列的树视图,请先创建一个MultiColumnTreeView UI控件,并在UXL文件中定义列。然后,使用 MultiColumnTreeView 创建自定义编辑器窗口,并定义在 C# 脚本中获取每列数据的位置。最后,将 UXML 文件引用到 C# 脚本。

  1. Editor文件夹中,创建一个名为PlanetsMultiColumnTreeView.uxml.

  2. 替换PlanetsMultiColumnTreeView.uxml替换为以下内容:

    <ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
        <ui:MultiColumnTreeView fixed-item-height="20">
            <!-- Columns and Column aren't Visual Elements or controls; they are considered attributes of MultiColumnListView. -->
            <ui:Columns>
                <ui:Column name="name" title="Name" width="120" />
                <ui:Column name="populated" title="Populated?" width="80" />
            </ui:Columns>
        </ui:MultiColumnTreeView>
    </ui:UXML>
    
  3. Editor文件夹中,创建一个名为PlanetsMultiColumnTreeView.cs.

  4. 替换PlanetsMultiColumnTreeView.cs替换为以下内容:

    using UnityEditor;
    using UnityEngine.UIElements;
        
    public class PlanetsMultiColumnTreeView : PlanetsWindow
    {
        [MenuItem("Planets/Multicolumn Tree")]
        static void Summon()
        {
            GetWindow<PlanetsMultiColumnTreeView>("Multicolumn Planet Tree");
        }
        
        void CreateGUI()
        {
            // The protected variable 'uxmlAsset' is a VisualTreeAsset defined in the parent 
            // class PlanetsWindow.
            uxmlAsset.CloneTree(rootVisualElement);
            var treeView = rootVisualElement.Q<MultiColumnTreeView>();
        
            // Call MultiColumnTreeView.SetRootItems() to populate the data in the tree.
            treeView.SetRootItems(treeRoots);
        
            // For each column, set Column.makeCell to initialize each node in the tree.
            // You can index the columns array with names or numerical indices.
            treeView.columns["name"].makeCell = () => new Label();
            treeView.columns["populated"].makeCell = () => new Toggle();
        
            // For each column, set Column.bindCell to bind an initialized node to a data item.
            treeView.columns["name"].bindCell = (VisualElement element, int index) =>
                (element as Label).text = treeView.GetItemDataForIndex<IPlanetOrGroup>(index).name;
            treeView.columns["populated"].bindCell = (VisualElement element, int index) =>
                (element as Toggle).value = treeView.GetItemDataForIndex<IPlanetOrGroup>(index).populated;
        }
    }
    
  5. 在 Unity 中,选择PlanetsMultiColumnTreeView.cs在“项目”窗口中。

  6. PlanetsMultiColumnTreeView.uxml检查器中的 Uxml 字段中。

  7. 选择“行星”>“多列树”以查看包含两列的列表。第一列有两个按节点分组的行星列表。每个节点旁边都有一个箭头。如果选择箭头,窗口会显示该组中的行星和切换的列表。

Unity 编辑器窗口中的一个列表,其中包含两列,一列用于行星,另一列带有指示行星是否已填充的复选框。此外,数据被组织成两个水平折叠部分,称为内行星和外行星。
Unity 编辑器窗口中的一个列表,其中包含两列,一列用于行星,另一列带有指示行星是否已填充的复选框。此外,数据被组织成两个水平折叠部分,称为内行星和外行星。

其他资源

结构 UI 示例
创建复杂的列表视图