LVGL Pro使用指南[02] LVGL XML 规范基础

本文说明LVGL XML规范基础。

介绍 链接到标题

基于LVGL XML规范实现的LVGL XML模块支持用 XML 描述UI,实现 LVGL 声明式 UI 框架。相较于拖拽式编辑,使用 XML 具有以下显著优势:

优势 具体说明
语法熟悉易懂​ 类 HTML 语法,学习门槛低,可读性强
​利于版本控制​ 纯文本格式,差异对比清晰,人类可读,无二进制文件困扰
​易于分享协作​ 可作为文本轻松复制、粘贴和发送
​模式可复用​ 代码片段可在项目间复制和重用
​易于自动化​ 脚本和 CI/CD 流水线可无缝处理 XML
​兼容 AI 工具​ AI 工具可读取、生成和重构 XML 代码
​模块化设计​ 能创建可复用组件,用于构建结构化 UI
编辑速度快​ 键盘输入通常比鼠标拖放操作更快捷
​支持运行时加载​ 可在运行时解析 XML,无需重新编译固件
​跨平台特性​ 同一份 XML 文件可在所有 LVGL 目标平台上运行

虽然 XML 文件可以手动编写,但还是强烈建议使用 ​​LVGL Pro 的XML编辑器​ 进行开发。该编辑器通过提供以下功能,能极大提升 UI 开发效率:

  • ​实时预览​​:对 XML 文件(components, screens)进行实时预览。
  • ​检查器模式​​:可视化显示组件尺寸、内边距等属性。
  • ​C 代码生成​​:根据 XML 文件生成对应的 C 代码。
  • ​自动补全与语法高亮​​:辅助编码,减少错误。
  • ​在线共享/预览​​:便于协作和测试。
  • ​Figma 集成​​:可将 Figma 设计导入。

UI元素 链接到标题

Widgets 控件 链接到标题

是UI的核心构造块,不能在运行时加载,需要以C代码形式编译到应用中。主要特征如下:

  • 在 XML 中,以 <widget> 根元素开头
  • 类似于 LVGL 的内置控件(build-in widget)
  • 可以包含自定义的逻辑
  • 运行时无法从 XML 中加载(因为包含的C代码)
  • 有丰富的 API,包含 set/get/add 函数
  • 需要用户自定义 XML 解析器将 XML 属性映射到 API 函数调用
  • 支持组合,例如包含其他 Widget(例如, Tabview 的标签页, Dropdown 的列表)
  • 在XML 编辑器中,可以用 XML 描述(能更快地看到效果效果并导出 C 代码)

Components 组件 链接到标题

简单的 UI 元素,可以在运行时加载。组件的主要特性是

  • 在 XML 中,以 <component> 根元素开头
  • 由 Widget 和/或其他Components组成
  • 仅在 XML 文件中定义,不能包含自定义 C 代码(可以作为事件回调调用 C 函数)
  • 可以从 XML 文件中加载(因为只包含 XML)
  • 可用于样式化 Widget 和其他组件,通过主题进行数据绑定、定义动画等
  • 可以包含 Widget 和/或 其他Components
  • 可以拥有简单的 API 来传递属性给它的子元素(例如,将 btn_text 传递给 Label 的文本)。

手动编写和 XML 编辑器编写的组件XML文件都可以在 LVGL 中注册,并创建实例。也就是说运行时 LVGL 也可以在Screen或其它组件内读取和使用 XML 文件中的组件。

Screens 链接到标题

Screens 类似于 Components:

  • 在 XML 中,以 <screen> 根元素开头
  • 由控件和/或其他组件构建
  • 可以在运行时从 XML 文件中加载
  • 没有 API

全局数据(Global data) 链接到标题

使用XML编辑器创建的项目含有一个特殊文件 globals.xml,其中定义全局数据,包含

  • styles  样式
  • consts  常量
  • images  图片
  • fonts  字体
  • subjects 数据绑定变量

支持同时加载多个 globals.xml 文件,但所有文件都在同一个全局作用域中,所以如果有重复的条目只会被添加一次。

LVGL使用XML的方式 链接到标题

LVGL 有两种方式使用XML文件

  • 运行时直接加载
  • 使用XML编辑器或CLI工具将XML转换为C代码

语法 链接到标题

命名 链接到标题

LVGL XML语法中的命名规则如下:

  • 符合标准的XML规范
  • 属性名(attribute names)使用小写字母并以 _ 分隔
  • 标签名(tag name)遵循一般的变量名规则: 必须以字母或 * 开头,其余部分可以由字母、 * 和数字组成
  • 尽可能遵循 LVGL API 的约定,例如:align="center"bg_color="0xff0000"
  • 对于颜色,支持以下语法(类似于 CSS 颜色表示法):0x112233#1122331122330x123#123123。注意:与 CSS 一样,0x123#123123 都表示 #112233
  • 参数/变量(params) 通过 $ 引用
  • 常量(consts)通过 # 引用
  • 样式(styles) 可以应用到组件的状态(state)或组件的某一个子元素上,例如:styles="style1 style2:pressed style3:focused:scrollbar"
  • 本地样式(仅存储在当前组件中)例如:<lv_label style_text_color="0xff0000" style_text_color:checked="0x00ff00"/>

类型(Types) 链接到标题

所有类型都可以用作 API 属性类型,但只有一小部分可以用作常量和 Subject 类型

简单类型 链接到标题

LVGL XML内置的简单类型如下:

类型名称 含义与说明 示例或备注
bool ​布尔值​​,表示逻辑上的“真”或“假”。 true或 false
int ​整数​​,默认范围大致为 -2B 到 2B。 与 C 语言中的 int32_t类型相同。
px ​像素单位​​。单位 px可以省略不写。 10等价于 10px
% ​百分比​​。值后必须附加 %作为单位。 含义与 lv_pct()函数相同。
content 表示 ​​内容大小​​,即根据内容自适应尺寸。 等价于 LV_SIZE_CONTENT
string 以 \0结尾的​​简单字符串​​。当属性中使用多个字符串或字符串数组时,应使用单引号 '将每个字符串括起来。 foo="'a' 'b'"
color 存储为 24 位 RGB 格式的​​颜色值​​ (lv_color_t)。 例如 0xFF0000表示红色
opa ​不透明度​​,取值范围为 0 到 255,或 0% 到 100%。与 CSS 类似,百分比值后必须跟有 % 128(约50%不透明) 或 50%
lv_obj 指向​​小部件 (Widget)​​ 的指针 (lv_obj_t*)。 -
screen 指向​​screen​​的指针 (同样是 lv_obj_t*)。 -
time_ms 以​​毫秒​​为单位的时间值。 -
deg_0.1 以 ​​0.1​​ 为精度的​​角度值​​。 900表示 90.0 度
scale_1/256 ​缩放比例​​,其中 256 代表 100% (原始大小),128 代表 50%,512 代表 200%,以此类推。 256 (100%), 128 (50%)

基于名称的类型(Name-based types) 链接到标题

在 XML 文件中,字体、图片、样式等通过字符串名称引用。例如,可以这样定义一个样式:<style name="red" bg_color="0xff0000"/>,之后就可以通过其名称red来引用这个样式。这意味着为了LVGL 能正确识别名称所指的对象,在 XML 加载 UI 时需要将实际的值与这些名称绑定

LVGL在注册组件XML文件和 globals.xml 文件时,其中大多数绑定(例如样式、字体、图像、动画、渐变等)会自动完成。但还有一些需要手动写代码连接

  • 事件回调函数(因为回调函数存在于代码中)
  • 引用内存中的字体或图像数据

数组(Arrays) 链接到标题

数组可以是任意类型,通过以下几种方式定义:

  • int[count]:表示一个整数数组。元素的数量将作为一个单独的参数传递。
  • string[NULL]:表示一个以 NULL 元素结尾的字符串数组。
  • string[]:表示一个没有 NULL 结尾、也没有数量参数的字符串数组。这种形式通常用于元素数量未知,或通过其他机制(例如其他设置项)提供数量信息。

枚举(Enums) 链接到标题

<enumdef> 可以在 <api> 标签中用于为 Widget 创建自定义枚举。但不适用于 Component。例如:

<api>
    <enumdef name="my_widget_mode" help="Possible modes" help-zh="Chinese help">
        <enum name="normal" help="Normal mode" help-zh="Normal mode in Chinese" value="0x10"/>
        <enum name="inverted" help="Inverted mode"/>
    </enumdef>

    <prop name="mode" help="help"type="enum:my_widget_mode" help="help"/>
</api>

当枚举类型后面加上一个加号(+)时,表示这个属性可以同时选择多个枚举值,并且这些值会被用按位或(bitwise OR)操作组合在一起。例如

<api>
    <!-- 定义一个枚举类型 my_axis -->
    <enumdef name="my_axis" help="Possible axis options">
        <enum name="primary_x" help="Primary X axis" value="0x01"/>
        <enum name="secondary_x" help="Secondary X axis" value="0x02"/>
        <enum name="primary_y" help="Primary Y axis" value="0x04"/>
        <enum name="secondary_y" help="Secondary Y axis" value="0x08"/>
    </enumdef>

    <!-- 定义一个属性,允许多选 -->
    <prop name="axis" type="my_axis+" help="S
    elect one or more axes"/>
</api>

<!-- 表示同时选择了 primary_x (0x01) 和 secondary_y (0x08)-->
<widget axis="primary_x|secondary_y"/>

复合类型(Compound types) 链接到标题

类型可以被组合,用于表达多种选项/类型。例如,对于宽度: type="px|%|content"

限制值(Limiting accepted values) 目前不支持;下面的示例说明了计划的语法, 限制用户从枚举中选择选项。例如:

  • 枚举: type="dir(top bottom)"
  • 颜色: type="color(0xff0000 0x00ff00 0x0000ff)"
  • 字符串: type="string('Ok' 'Cancel')

许可证 链接到标题

LVGL将LVGL XML视为其核心资产之一,有非常严格的限制,这里做简单摘要主要集中在限制上,完整的内容详见https://docs.lvgl.io/master/details/xml/xml/license.html

LVGL XML 规范(以下简称“规范”)定义一种基于 XML 的语言,用于描述 LVGL 生态系统中的用户界面。该规范受版权保护。根据诸多条款提供有限的授权使用。其许可证的目的是确保规范对使用 LVGL 的应用程序开发人员保持免费使用,同时限制其在第三方 UI 编辑器或设计工具中的使用。以此来防止未经授权的工具以与官方 LVGL 产品发生竞争,从而保护 LVGL 生态系统的长期完整性和可持续性。

限制条款

  • 禁止的工具开发:未经 LVGL LLC 书面许可,不得创建、发布或分发任何使用该规范读取、写入或解释 XML 文件的 UI 编辑器、可视化构建器、布局设计器、代码生成器或工具(无论是商业的、开源的,还是供公众使用、客户或合作伙伴使用,或任何组织外部使用)。
  • 禁止的功能实现:不得在任何提供与 LVGL UI 编辑器类似功能的 UI 创建、编辑或设计功能的软件或平台上实现或扩展该规范。
  • 禁止的公共开发:不得基于该规范构建公共 API、插件、转换器或 SDK。
  • 禁止的工具共享:不得共享或发布围绕该规范构建的内部工具。
  • 禁止的通用设计工具集成:不得将该规范用于 LVGL 生态系统之外的通用设计工具或框架。

基本来说可用的途径已经全部禁止,但也有提到可以用来创建内部工具来辅助开发,但必须未经许可不得发布、销售或外部分享。

参考 链接到标题

https://docs.lvgl.io/master/details/xml/xml/index.html