暴露自訂control給UXML

  1. 自訂control需要繼承VisualElement並且這個自訂control需要有一個預設constructor
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class StatusBar : VisualElement
    {
    // 需要有一個預設constructor
    public StatusBar()
    {
    m_Status = String.Empty;
    }

    string m_Status;
    public string status { get; set; }
    }
  2. 為了讓你自訂的control可以在UXML中使用,你需要定義一個factory class,如果沒有特殊的需求,可以直接繼承UxmlFactory<T>
    1
    2
    3
    4
    5
    6
    7
    class StatusBar : VisualElement
    {
    // 建議直接將factory class放在自訂的control中
    public new class UxmlFactory : UxmlFactory<StatusBar> {}

    // ...
    }
  3. UxmlTraits:定義在UXML中可以使用的特徵(UXML traits),
    • UxmlTraits的目的有
      • factory建立新物件時使用它們。
      • 在schema產生時,會分析它們以取得關於該Element的資訊,之後將這些資訊轉換為XML schema directive。
    • 以下範例
      • 宣告了一個m_Status,用來定義一個XML attribute status
      • uxmlChildElementsDescription回傳一個空IEnumerable,用來表明這個自訂的StatusBar沒有child。
      • Init()中,XML parser從property bag讀出的值設定給StatusBar.status
      • UxmlTraits class定義在StatusBar class中,讓Init()可以存取StatusBar的私有變數。
      • UxmlTraits繼承了VisualElement.UxmlTraits,它也擁有VisualElement.UxmlTraits的屬性
      • Init()會呼叫base.Init()以初始化base class的屬性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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);
}
}

// ...
}
- 注意:在UI Builder中創作時,UI Builder可能會多次呼叫`UxmlTraits.Init()`來同步UXML檔案中的值,建議使用`GetValueFromBag`而不是`TryGetValueFromBag`以確保當UI Builder取消設定(unset)element的值時,這個element不會殘留先前的值。
  1. 若想要有child的話,需要override uxmlChildElementsDescription
    1
    2
    3
    4
    5
    6
    7
    public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
    {
    get
    {
    yield return new UxmlChildElementDescription(typeof(VisualElement));
    }
    }
  2. 可以將你自訂的control放到namespace中來分類它們
    1
    2
    [assembly: UxmlNamespacePrefix("My.First.Namespace", "first")]
    [assembly: UxmlNamespacePrefix("My.Second.Namespace", "second")]

Reference:https://docs.unity3d.com/Manual/UIE-expose-custom-control-to-uxml.html#define-a-factory

評論