LVGL Pro使用指南[15] LVGL XML 控件
概述 链接到标题
控件(Widgets) 是LVGL的主要构建块之一,与组件(Components)和 Screens并列。控件的 XML 文件以 <widget> 作为根元素, 支持以下子标签:
<consts>:定义常量。<api>:定义 API 接口。<styles>:定义样式。<view>:定义视图。<previews>:定义预览。 控件 可以嵌套在其他 控件 或 组件 中。控件 不能直接从 XML 加载,但可以通过编写和注册简单的 XML 解析器来实现。
对于一般的界面开发用户,实现控件的场景也并不多。同时绝大多数情况都只会使用<api>标签描述控件的接口,让LVGL XML可以通过接口使用控件的功能,而控件的解释器是需要通过C来实现,这不是本文的说明范围。基于以上因素让说明的控件的XML的必要性并不大,这也就是到本系列文章接近尾声的时候才开始写控件的原因。
内置控件 链接到标题
LVGL 提供了许多内置的控件,例如:lv_slider,lv_label,lv_chart等等,在LVGL的仓库内有专门的xml来描述这些控件的接口: https://github.com/lvgl/lvgl/tree/master/xmls
这些xml会描述控件的接口,并注释如何使用,例如其中的lv_slider.xml文件:
<!--
Example
<lv_spinner anim_duration="1500" arc_sweep="90"/>
-->
<widget>
<api>
<prop name="anim_duration" type="int" help="Set the animation time of the spinner."/>
<prop name="arc_sweep" type="int" help="Set the animation arc length of the spinner. The animation is suited to values between 180 and 360."/>
</api>
</widget>
控件的解析器代码放在 https://github.com/lvgl/lvgl/tree/master/src/xml
API 链接到标题
控件通过<api>标签描述其接口,该标签下主要通过 <prop>(属性)子标签描述接口。
属性 链接到标题
属性是描述小部件接口的核心部分,例如下面的示例表示该控件有一个text属性可以设置,类型是字符串:
<api>
<prop name="text" type="string" help="Text of the label."/>
</api>
参数 链接到标题
属性可以由多个参数构成,例如
<api>
<prop name="bind_text" help="Bind a subject's value to a label.">
<param name="bind_text" type="subject" help="Integer or string subject"/>
<param name="fmt" type="string" help="Format string, e.g. %d °C "/>
</prop>
</api>
名称与属性相同的参数可以直接引用。其他参数则使用 “属性-参数(property-param)” 的方式引用。未设置的参数的情况:
- 使用默认值(如果已定义)
- 类型特定的默认值(例如 0、false、NULL)
在解析器中每个 <prop> 都映射到一个设置函数。 同一属性下的<param>会被传递给同一个设置函数。
<enumdef>
链接到标题
<enumdef> 仅用于 控件,此标签用于为参数值定义枚举。例如
<api>
<enumdef name="my_widget_mode" help="Possible modes">
<enum name="normal" help="Normal mode" value="0x10"/>
<enum name="inverted" help="Inverted mode"/>
</enumdef>
<prop name="mode" help="Set Widget mode">
<param name="mode" type="enum:my_widget_mode"/>
</prop>
</api>
<element>
链接到标题
<element>仅用于 控件,此标签用于定义子控件(sub-widgets)或内部结构(例如:图表序列、下拉列表、标签视图)。也常用于创建类似 “插槽(slots)” 的结构(类似 tabview 的 tab),例如窗口部件中的内容区和标题区,允许直接在其中创建子对象。
<element>以包含 和 子标签:
<arg>是必需的,用于创建或获取 element 时传入。<prop>是可选的,映射到 setter 函数。
下面是一个示例,用于定义一个可以动态添加到 控件 的 “indicator”。它会创建 my_indicator_t * 类型的元素,类似于 lv_chart_add_series 的方式。
<api>
<element name="indicator" type="my_indicator_t" help="The indicator of my_widget" access="add">
<!-- args are passed when the element is created -->
<arg name="color" type="color"/>
<arg name="max_value" type="int"/>
<!-- props can be set by setters at any time -->
<prop name="value" type="int"/>
</element>
</api>
Element 的 access 类型:
- add: 动态创建多个元素,例如 tabview 的 tabs。
- get: 访问隐式创建的元素,例如 dropdown 的列表部分。
- set: 访问按索引存在的部分,例如 table 的 cells。
- custom:映射自定义 C 函数到 XML,例如 bind_state_is_eq。
add 与 get 类型的 element 都会返回一个对象,因此需要声明 type。该 type 可以是任何自定义类型,例如 type="my_data"。在导出的 C 代码中,返回值会保存在 my_data_t * 类型的变量中。如果 type="lv_obj",该 element 允许拥有子控件 或 组件。
Element 在 <view> 中以 <widget-element> 的形式引用。名称部分使用 - 分隔。
注意: Element 只能在 XML 中定义其 API;实现必须写在 C 代码中。
access="add"
链接到标题
通过add创建的名为indicator的Element
<api>
<element name="indicator" type="obj" help="The indicator of my_widget" access="add">
<arg name="color" type="color"/>
<arg name="max_value" type="int"/>
<prop name="value">
<param name="value" type="int"/>
</prop>
</element>
</api>
使用方法如下:
<my_widget width="100px">
<my_widget-indicator name="indic1" color="0xff0000" max_value="120" value="30"/>
</my_widget>
通过LVGL Pro Editor会生成以下add原型,需要另外写C代码实现:
lv_obj_t * my_widget_add_indicator(lv_obj_t * parent, lv_color_t color, int32_t max_value);
void my_widget_set_indicator_value(lv_obj_t * obj, int32_t value);
access="get"
链接到标题
通过get创建的名为control_button的Element
<api>
<element name="control_button" type="obj" help="A control button of my_widget" access="get">
<arg name="index" type="int"/>
<prop name="title" type="string"/>
</element>
</api>
使用方法如下:
<my_widget width="100px">
<my_widget-control_button name="btn1" index="3" title="Hello"/>
</my_widget>
通过LVGL Pro Editor会生成以下get原型,需要另外写C代码实现:
lv_obj_t * my_widget_get_control_button(lv_obj_t * parent, int32_t index);
void my_widget_set_control_button_title(lv_obj_t * obj, const char * text);
access="set"
链接到标题
通过set创建的名为item的Element
<api>
<element name="item" type="obj" access="set">
<arg name="index" type="int"/>
<prop name="icon" type="img_src"/>
<prop name="color" type="color"/>
</element>
</api>
使用方法如下:
<my_widget width="100px">
<my_widget-item index="3" icon_src="image1" color="0xff0000"/>
</my_widget>
通过LVGL Pro Editor会生成以下set原型,需要另外写C代码实现:
void my_widget_set_item_icon(lv_obj_t * parent, int32_t index, const void * icon_src);
void my_widget_set_item_color(lv_obj_t * parent, int32_t index, lv_color_t color);
access="custom"
链接到标题
通过custom创建的名为bind_color的Element
<element name="bind_color" access="custom">
<arg name="subject" type="subject"/>
<arg name="new_color" type="color"/>
<arg name="ref_value" type="int"/>
</element>
使用方法如下:
```xml
<my_widget width="100px">
<my_widget-bind_color subject="subject_1" color="0xff0000" ref_value="15"/>
</my_widget>
通过LVGL Pro Editor会生成以下自定义原型,需要另外写C代码实现:
void my_widget_bind_color(lv_obj_t * parent, lv_subject_t * subject, lv_color_t color, int32_t ref_value);
参考 链接到标题
https://docs.lvgl.io/master/xml/ui_elements/widgets.html https://docs.lvgl.io/master/xml/ui_elements/api.html