UIElements开发人员指南4 The UXML format(UXML格式)

UXML格式

UXML文件是定义用户界面的逻辑结构的文本文件。UXML文件中使用的格式受HTML(超文本标记语言),XAML(可扩展应用程序标记语言)和XML(可扩展标记语言)的启发。如果您熟悉这些公认的格式,您应该注意到UXML中有很多相似之处。但是,UXML格式包含很小的差异,以提供与Unity一起有效使用的方法。

本节介绍Unity支持的UXML格式,并提供有关编写,加载和定义UXML模板的详细信息。它还包括有关定义新元素以及如何使用UQuery的信息。

UXML可以让技术较低的用户更容易在Unity中构建用户界面。在UXML中,您可以:

  • 用XML定义用户界面(UI)的结构。
  • 用USS样式表来定义UI布局。

这使得技术开发人员只需执行技术任务,例如导入资产,定义逻辑和处理数据。

定义新元素(扩展UIElement

UIElement是可扩展的。您可以定义自己的用户界面组件和元素。

在使用UXML文件定义新元素之前,需要从VisualElement或其子类派生一个新类,然后在此新类中实现适当的功能。您的新类必须实现默认构造函数。

例如,以下代码是派生的新StatusBar类并实现其默认构造函数:

class StatusBar : VisualElement
{
    public StatusBar()
    {
        m_Status = String.Empty;
    }

    string m_Status;
    public string status { get; set; }
}

为了让UIElements在读取UXML文件时实例化一个新类,您必须为您的类定义一个工厂。除非您的工厂需要做一些特殊的事情,否则您可以从UxmlFactoy<T>派生工厂。建议您将工厂类放在相应的组件类中。

例如,以下代码演示了如何为StatusBar定义工厂,它通过派生UxmlFactory<T>类来定义工厂,工厂名为UxmlFactory

class StatusBar : VisualElement
{
    public new class UxmlFactory : UxmlFactory<StatusBar> {}

    // ...
}

通过定义此工厂,您可以<StatusBar>在UXML文件中使用该元素。

定义元素的属性

您可以为新类定义UXML特征,并将其工厂设置为使用这些特征。

例如,以下代码演示了如何定义UXML traits类以将status属性初始化为类的属性StatusBar。status属性是从XML数据初始化的。

class StatusBar : VisualElement
{
    public new class UxmlFactory : UxmlFactory<StatusBar, UxmlTraits> {}

    public new class UxmlTraits : VisualElement.UxmlTraits
    {
        UxmlStringAttributeDescription m_Status = new UxmlStringAttributeDescription { name = "status" };
        
        public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
        {
            get { yield break; }
        }

        public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
        {
            base.Init(ve, bag, cc);
            ((StatusBar)ve).status = m_Status.GetValueFromBag(bag, cc);
        }
    }

    // ...
}

UxmlTraits有两个目的:

  • 工厂使用它来初始化新创建的对象。

  • 它通过schema的生成过程进行分析,以获取有关元素的信息。此信息将被转换为XML schema 指令。

上面的示例代码执行了以下操作:

  • 声明m_Status的变量定义了一个名为status的XML属性。
  • uxmlChildElementsDescription返回空IEnumerable表明StatusBar元素没有子元素。
  • Init()方法从XML解析器的属性包中读取status属性,并将StatusBar.status属性设置为此值。
  • 通过将UxmlTraits类放在StatusBar类中允许该Init()方法访问StatusBar的私有成员。
  • UxmlTraits类继承自基类UxmlTraits,因此它可以共享基类的属性。
  • Init()调用base.Init()初始化基类属性。

上面的代码示例使用UxmlStringAttributeDescription类声明了一个字符串属性。UIElements支持以下类型的属性,每个属性都将C#类型链接到XML类型:

属性属性值
UxmlStringAttributeDescription一个字符串
UxmlFloatAttributeDescriptionC#float类型范围内的单精度浮点值。
UxmlDoubleAttributeDescriptionC#double类型范围内的双精度浮点值。
UxmlIntAttributeDescriptionC#int类型范围内的整数值。
UxmlLongAttributeDescriptionC#long类型范围内的长整数值。
UxmlBoolAttributeDescriptiontrue 要么 false
UxmlColorAttributeDescription表示颜色的字符串(#FFFFFF
UxmlEnumAttributeDescription<T>表示该Enum类型的值之一的字符串T

在上面的代码示例中,uxmlChildElementsDescription返回一个空IEnumerable,表示该StatusBar元素不接受子元素。

要让元素接受某种类型的子元素,必须重写该uxmlChildElementsDescription属性。例如,为了让StatusBar接受任何类型的子元素,uxmlChildElementsDescription需要按如下方式指定属性:

public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
{
    get
    {
        yield return new UxmlChildElementDescription(typeof(VisualElement));
    }
}

定义名称空间前缀

在C#中定义新元素后,即可开始在UXML文件中使用该元素。如果在新命名空间中定义了新元素,则应为命名空间定义前缀。命名空间前缀被声明为根<UXML>元素的属性,并在元素作用域时替换为完整的命名空间名称。

要定义命名空间前缀,需要为要定义的每个命名空间前缀向程序集添加一个UxmlNamespacePrefix属性。

[assembly: UxmlNamespacePrefix("My.First.Namespace", "first")]
[assembly: UxmlNamespacePrefix("My.Second.Namespace", "second")]

这可以在程序集的根级别(任何命名空间之外)的任何C#文件中完成。

schema 生成系统将执行以下操作:

  • 检查这些属性并使用它们生成schema 。
  • 在新创建的UXML文件中,添加命名空间前缀定义作为<UXML>元素的属性
  • 为命名空间包含schema文件位置,存放在它的xsi:schemaLocation属性中。

当你需要更新项目中的UXML的schema时,选择菜单AssetsUpdate UIElements Schema以确保文本编辑器识别新元素。

通过在 Project/Assets/Editor文件夹中选择 Create > UIElements Editor Window ,可以在新创建的UXML中生成已定义的命名空间前缀。

高级用法

自定义UXML名称

您可以通过覆盖其IUxmlFactory.uxmlNameIUXmlFactory.uxmlQualifiedName属性来定制UXML名称。确保uxmlName在命名空间中是唯一的,而uxmlQualifiedName在项目中是唯一的。

如果两个名称都不唯一,则在尝试加载程序集时会引发异常。

以下代码示例演示如何覆盖和自定义UXML名称:

public class FactoryWithCustomName : UxmlFactory<..., ...>
{
    public override string uxmlName
    {
        get { return "UniqueName"; }
    }

    public override string uxmlQualifiedName
    {
        get { return uxmlNamespace + "." + uxmlName; }
    }
}

为元素选择工厂

默认情况下,IUxmlFactory实例化一个元素并使用元素的名称来选择元素。

您可以通过覆盖IUXmlFactory.AcceptsAttributeBag来在选择过程考虑元素的属性值。然后,工厂将检查元素属性,以确定它是否可以为UXML元素实例化对象。

例如,如果您的VisualElement类是泛型类,那么这会很有用。在这种情况下,类的专有工厂可以检查XML的type属性的值。根据具体值来决定接受或拒绝实例化。请参阅PropertyControl<T>的实现示例。

在多个工厂都可以实例化同一类元素的情况下,将会选择第一个注册的工厂。

覆盖基类属性的默认值

您可以通过在派生UxmlTraits类中设置defaultValue来更改基类中声明的属性默认值。

例如,以下代码显示了如何更改默认值m_TabIndex

class MyElementTraits : VisualElement.UxmlTraits
    {
        public MyElementTraits()
        {
            m_TabIndex.defaultValue = 0;
        }
    }

接受任何属性

默认情况下,生成的XML schema中声明元素可以具有任何属性。

除了在UxmlTraits类中声明的属性之外,其它属性都不受限制。这与XML验证器形成对比,后者检查声明的属性的值是否与其声明匹配。

附加属性包含在IUxmlAttributes包中,被传递给IUxmlFactory.AcceptsAttributBag()IUxmlFactory.Init()函数。是否使用这些附加属性取决于工厂实现。默认行为是放弃附加属性。

这意味着这些附加属性未附加到实例化的VisualElement ,并且这些附加属性无法通过UQuery来查询获得。

定义新元素时,可以通过在UxmlTraits构造函数中将UxmlTraits.canHaveAnyAttribute属性设置为false,将接受的属性限制为显式声明过的属性。

使用Schema定义

Schema 定义文件指定每个UXML元素可以包含的属性和子元素。应使用Schema 定义文件作为你正确编写UXML文档和验证UXML文档的指南。

在UXML 模板文件中,<UXML>根元素的xsi:noNamespaceSchemaLocationxsi:schemaLocation属性指定的Schema 定义文件的位置。

选择Assets > Create > UIElements Editor Window,将会自动更新Schema定义文件,它会使用项目的VisualElement子类中的最新信息。要强制更新UXML模式文件,请选择“ Assets > Update UIElements Schema

注意:某些文本编辑器无法识别该xsi:noNamespaceSchemaLocation属性。如果文本编辑器找不到架构定义文件,则还应指定该xsi:schemaLocation属性。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值