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
、#112233
、112233
、0x123
、#123
、123
。注意:与 CSS 一样,0x123
、#123
和123
都表示#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 生态系统之外的通用设计工具或框架。
基本来说可用的途径已经全部禁止,但也有提到可以用来创建内部工具来辅助开发,但必须未经许可不得发布、销售或外部分享。