Version: Unity 6.0 (6000.0)
语言 : 中文
设置 UI 结构示例
创建复杂的列表视图

创建列表和树视图

列表视图和树视图是__ UI__(即用户界面,User Interface)让用户能够与您的应用程序进行交互。Unity 目前支持三种 UI 系统。更多信息
See in Glossary
设计中常见的功能。您可以使用 UI 工具包在自定义编辑器窗口或运行时中创建列表和树视图。此示例演示如何在自定义编辑器窗口中创建列表和树视图。您可以使用 UXML 配置列表和树的结构,然后在 C# 脚本中动态填充。

示例概述

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

  • 具有单列的行星列表
  • 包含两列的行星列表
  • 行星树视图
  • 具有两列的行星树视图

可以在此 GitHub 代码仓库中找到此示例创建的完整文件。

先决条件

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

用 C# 创建数据

在由两组行星和树视图根节点组成的 C# 脚本中创建数据。

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

  2. 在项目窗口中,创建一个名为 Editor 的文件夹。

  3. Editor 文件夹中,创建一个名为 PlanetsWindow.cs 的 C# 脚本。

  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 Builder 创建 ListView UI 控件。然后,使用 ListView 创建一个自定义编辑器窗口,并在 C# 脚本中定义获取列表数据的位置。最后,将 UXML 文件引用到 C# 脚本。

  1. 右键单击 Editor 文件夹。

  2. 选择创建 (Create) > UI 工具包 (UI Toolkit) > 编辑器窗口 (Editor Window)

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

  4. 双击 PlanetsListView.uxml 可在 UI Builder 中将其打开。

  5. 在层级视图 (Hierarchy) 窗口中,删除标签 (Label) 控件并添加 ListView 控件。

  6. 在层级视图 (Hierarchy) 窗口中选择 ListView 控件。

  7. 在检视面板 (Inspector) 窗口中,将固定项高 (Fixed Item Height) 设置为 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 中,在项目 (Project) 窗口中选择 PlanetsListView.cs,然后将 PlanetsListView.uxml 拖入检视面板 (Inspector) 中的 Uxml 字段。

  11. 从菜单中选择行星 (Planets) > 标准列表 (Standard List) 以查看行星列表。

创建具有多列的列表视图

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

  1. 右键单击 Editor 文件夹。

  2. 选择创建 (Create) > UI 工具包 (UI Toolkit) > UI 文档 (UI Document) 以创建 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 的 C# 文件。

  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 的项目 (Project) 窗口中选择 PlanetsMultiColumnListView.cs

  8. PlanetsMultiColumnListView.uxml 拖入检视面板 (Inspector) 中的 Uxml 字段。

  9. 从菜单中选择行星 (Planets) > 多列列表 (Multicolumn List) 以查看两列列表。一列包含行星列表。另一列具有指示是否填充行星的开关。

创建树视图

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

  1. Editor 文件夹中,创建一个名为 PlanetsTreeView.uxml 的 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 的 C# 文件。

  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 的项目 (Project) 窗口中选择 PlanetsTreeView.cs

  6. PlanetsTreeView.uxml 拖入检视面板 (Inspector) 中的 Uxml 字段。

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

创建具有多列的树视图

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

  1. Editor 文件夹中,创建一个名为 PlanetsMultiColumnTreeView.uxml 的 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 的 C# 文件。

  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 的项目 (Project) 窗口中选择 PlanetsMultiColumnTreeView.cs

  6. PlanetsMultiColumnTreeView.uxml 拖入检视面板 (Inspector) 中的 Uxml 字段。

  7. 选择行星 (Planets) > 多列树 (Multicolumn Tree) 可以查看具有两列的列表。第一列包含两个按节点分组的行星列表。每个节点旁边都有一个箭头。如果选择箭头,该窗口将显示该组中的行星和开关列表。

其他资源

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