这次做一个列表的练习,之前说可能要用到模板,最后发现是看情况使用的,那么就开始吧。

目标

定制一个滚动面板,用来展示物品的Icon和名字。
这次只演示功能,没有做美化,请大家见谅。

一、制作单个Node

这已经是轻车熟路了,创建三件套,我在这里命名为myNode,路径是Assets/Editor/myNode/…,然后稍微修改一下,然后:
在UXML中设置Image和Label,并用一个container将他们包围起来

<VisualElement class="node">
  <VisualElement name="box" class="container__row">
    <Image name="Icon" class="pic"/>
    <Label name="nameLabel" text="物品名称"/>
  </VisualElement>
</VisualElement>

在USS中做一些修改(可以自行美化)

/*----------------------container----------------------*/
.container
{
}
.container__row
{
	width:280px;
	border-radius: 12px;
	border-style: solid;
	border-width: 1px 1px 1px 1px;
	border-color: #000;
	flex-wrap:wrap;
	flex-direction:row;
}
/*----------------------Label----------------------*/
Label 
{
	align-self:center;
    font-size: 16;
    font-weight: bold;
}
/*----------------------Image----------------------*/
.pic
{
	align-self:flex-start;
	width:40px;
	height:40px;
	background-image:resource("unity");
	margin: 3px 30px 3px 50px;
}

那么目前的效果如下,这里图片和文字都是示例,具体之后会改的不用担心
Unity2019 UIElement 笔记(十)简单练习二

二、创建列表

依旧是创建三件套,我在这里命名为Test,路径是Assets/Editor/Test/…
首先是C#代码

using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
using System.Collections.Generic;

public class Test : EditorWindow
{
    [MenuItem("Window/UIElements/Test")]
    public static void ShowExample()
    {
        Test wnd = GetWindow<Test>();
        wnd.titleContent = new GUIContent("Test");
    }

    public void OnEnable()
    {
        VisualElement root = rootVisualElement;
        var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/Test/Test.uxml");
        var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Editor/Test/Test.uss");
        VisualElement labelFromUXML = visualTree.CloneTree();
        labelFromUXML.styleSheets.Add(styleSheet);
        root.Add(labelFromUXML);
    }
}

修改UXML,增加一个名为scv的容器,这里要给ScrollView取好名字,之后会通过这个名字为里面添加子元素。

<VisualElement name="menu" class="menu">
  <ScrollView name="scv" class="scv">
  </ScrollView>
</VisualElement>

那么依旧是USS修改,让里面的元素垂直分布,定义好大小

.menu 
{
	width:320px;
	border-radius: 6px;
	border-style: solid;
	border-color: #000;
	flex-wrap:wrap;
	flex-direction:row;
}
.scv
{
	width:310px;
}

那么窗口就创建好了,到这里都是轻车熟路了

三、添加子元素

这里就是问题的关键了,如何添加子元素?
目前来说,有两种方法来解决:
1、通过Template和Instance进行添加
2、在C#中添加
第一种方法我在Unity2019 UIElement 笔记(二)UXML元素介绍上中介绍过,很方便,但是不适合我们现在的情况,因为第一种情况适合为UI中加入一些模块化的,比较偏简单的重复性的功能。
而现在我们要加入大量、不同的子元素,我们不可能一个一个的手动进行修改,那么我们就需要从C#中为其添加子元素。
之前我们也提到过,事实上在UXML中,所有视觉元素的基类都是VisualElement,也就是说,我们只需要,将整个myNode作为一个VisualElement,然后重复的添加到一个可以拥有子元素的节点上就可以了。
那么接下来就很简单了:

找到父节点

就是通过之前的Query函数来找到自己想要的父节点

VisualElement scv = labelFromUXML.Query<ScrollView>("scv").First();

载入myNode

和之前一样的添加VisualElement的方法

visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/myNode/myNode.uxml");
styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Editor/myNode/myNode.uss");

将myNode加入父节点

这里我在resources中放入了三张图片
Unity2019 UIElement 笔记(十)简单练习二
然后在Test中定义一个链表,用来储存这三张图片的名字

private List<string> itemList = new List<string>() { "red", "green", "blue" };

当然这里我是偷懒了,实际情况肯定没有那么简单,大家可以考虑通过使用读取xml文件来分别读出道具的属性。
那么最后使用一个for循环将myNode添加到父节点,这里我为了演示滚动条的效果,取巧加多了点数量

for (int i = 0; i < itemList.Count * 30; i++)
        {
            VisualElement nodeFromUXML = visualTree.CloneTree();
            nodeFromUXML.styleSheets.Add(styleSheet);
            nodeFromUXML.Query<Label>("nameLabel").First().text = itemList[i % 3];
            nodeFromUXML.Query<Image>("Icon").First().style.backgroundImage = new StyleBackground((Texture2D)Resources.Load(itemList[i % 3]));
            scv.Add(nodeFromUXML);
        }

在这里有两点要注意:

  1. 依旧是使用Query来搜索想要的节点
  2. 目前更改图片我能想到的方法是更改它的style,就如同上面所示的,然后从Resources中读取资源
    我还没有想到其他办法,如果有更好的办法,请务必分享。

结果

那么就OK了,一个简单的道具列表就做好了!
Unity2019 UIElement 笔记(十)简单练习二
简单总结一下,这次的练习还是挺简单的,也没有什么花哨的地方,效果也还算不错。
唯一比较特别的点就在于如何添加节点,本质上也不是很难。
但是到目前为止的功能大部分只是展示,还未涉及到事件的响应,等介绍完事件系统,会进一步的完善这次的物品展示功能。

相关文章: