这次做一个列表的练习,之前说可能要用到模板,最后发现是看情况使用的,那么就开始吧。
目标
定制一个滚动面板,用来展示物品的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;
}
那么目前的效果如下,这里图片和文字都是示例,具体之后会改的不用担心
二、创建列表
依旧是创建三件套,我在这里命名为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中放入了三张图片
然后在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);
}
在这里有两点要注意:
- 依旧是使用Query来搜索想要的节点
- 目前更改图片我能想到的方法是更改它的style,就如同上面所示的,然后从Resources中读取资源
我还没有想到其他办法,如果有更好的办法,请务必分享。
结果
那么就OK了,一个简单的道具列表就做好了!
简单总结一下,这次的练习还是挺简单的,也没有什么花哨的地方,效果也还算不错。
唯一比较特别的点就在于如何添加节点,本质上也不是很难。
但是到目前为止的功能大部分只是展示,还未涉及到事件的响应,等介绍完事件系统,会进一步的完善这次的物品展示功能。