Components
Overview
<component>
can have <consts>
, <api>
, <styles>
, and <view>
tags inside.
Unlike widgets (which are always compiled into the application), components can either:
Be loaded at runtime from XML.
Be exported to C code.
Usage from Exported Code
From each component XML file, a C and H file is exported with a single function inside:
lv_obj_t * component_name_create(lv_obj_t * parent, ...api properties...);
When a component is used in another component’s XML code and the code is exported, this create
function will be called.
This means that components do not have a detailed set/get API but can be created with a fixed set of parameters.
If the user needs to access or modify values dynamically, it is recommended to use a subject.
The user can also call these _create_
functions at any time from the application code.
Usage from XML
Registration
Once a component is created (e.g., my_button
), it can be registered by calling either:
lv_xml_component_register_from_file("A:lvgl/examples/others/xml/my_button.xml");
lv_xml_component_register_from_data("my_button", xml_data_of_my_button);
These registration functions process the XML data and store relevant information internally. This is required to make LVGL recognize the component by name.
When loaded from a file, the file name is used as the component name.
Instantiation
After registration, a new instance of any registered component can be created with:
lv_obj_t * obj = lv_xml_create(lv_screen_active(), "my_button", NULL);
The created widget is a normal LVGL widget that can be used like any other manually created widget.
The last parameter can be NULL
or an attribute list, like this:
/* Can be local */
char * my_button_attrs[] = {
"x", "10",
"y", "-10",
"align", "bottom_left",
"btn_text", "New button",
NULL, NULL,
};
lv_obj_t * btn1 = lv_xml_create(lv_screen_active(), "my_button", my_button_attrs);
Parameters
The properties of child elements can be adjusted, such as:
<lv_label x="10" text="Hello"/>
These parameters can be set to a fixed value. However, with the help of <prop>
elements inside the <api>
tag,
they can also be passed when an instance is created. Only the whole property can be passed, but not individual <param>
elements.
Additionally, when a component is created, it can use the extended widget's attributes
(see <view extends="...">
).
This means that components inherit the API of the extended widget as well.
The following example demonstrates parameter passing and the use of the
text
label property on a component:
<!-- h3.xml -->
<component>
<view extends="lv_label"/>
</component>
<!-- red_button.xml -->
<component>
<api>
<prop type="string" name="btn_text" default="None"/>
</api>
<view extends="lv_button" style_radius="0" style_bg_color="0xff0000">
<h3 text="Some text"/>
<h3 text="$btn_text" y="40"/>
</view>
</component>
lv_xml_component_register_from_file("A:path/to/h3.xml");
lv_xml_component_register_from_file("A:path/to/red_button.xml");
/* Creates a button with "None" text */
lv_xml_create(lv_screen_active(), "red_button", NULL);
/* Use attributes to set the button text */
const char * attrs[] = {
"btn_text", "Click here",
NULL, NULL,
};
lv_xml_create(lv_screen_active(), "red_button", attrs);
Example
Load components at runtime
C code
View on GitHub#include "../../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_XML
void lv_example_xml_1(void)
{
/*A red button created from builti-in LVGL widgets
*It has an API parameter too to change its text.*/
const char * red_button_xml =
"<component>"
" <api>"
" <prop name=\"button_text\" type=\"string\" default=\"None\"/>"
" </api>"
" <view extends=\"lv_button\" radius=\"0\" style_bg_color=\"0xa91500\">"
" <lv_label text=\"$button_text\" align=\"center\"/>"
" </view>"
"</component>";
/*The card is just an lv_obj where a label and two red buttons are used.
* Its API allow setting a title (label test) and the action (the text of a button)*/
const char * card_xml =
"<component>"
" <api>"
" <prop name=\"title\" type=\"string\" default=\"Hello world\"/>"
" <prop name=\"action\" type=\"string\"/>"
" </api>"
" <view width=\"200\" height=\"content\">"
" <lv_label text=\"$title\" align=\"top_mid\"/>"
" <red_button y=\"20\" align=\"top_left\" button_text=\"Cancel\"/>"
" <red_button y=\"20\" align=\"top_right\" button_text=\"$action\"/>"
" </view>"
"</component>";
/* Motor card is a special case of a card where the title and action are already set*/
const char * motor_card_xml =
"<component>"
" <view extends=\"card\" title=\"Motor start?\" action=\"Start\">"
" </view>"
"</component>";
/*Register all the custom components*/
lv_xml_component_register_from_data("red_button", red_button_xml);
lv_xml_component_register_from_data("card", card_xml);
lv_xml_component_register_from_data("motor_card", motor_card_xml);
lv_obj_t * card;
/*Create a card with the default values*/
card = lv_xml_create(lv_screen_active(), "card", NULL);
/*Create a motor card too. The returned value can be adjusted freely*/
card = lv_xml_create(lv_screen_active(), "motor_card", NULL);
lv_obj_set_y(card, 90);
/*Pass properties to a card*/
const char * attrs[] = {
"y", "180",
"action", "Apply",
"title", "New title",
NULL, NULL,
};
card = lv_xml_create(lv_screen_active(), "card", attrs);
}
#endif
C code
View on GitHub#include "../../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_XML
void lv_example_xml_2(void)
{
lv_result_t res;
res = lv_xml_component_register_from_file("A:lvgl/examples/others/xml/my_h3.xml");
if(res != LV_RESULT_OK) {
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "Couldn't open the XML files.");
lv_obj_center(label);
return;
}
lv_xml_component_register_from_file("A:lvgl/examples/others/xml/my_card.xml");
lv_xml_component_register_from_file("A:lvgl/examples/others/xml/my_button.xml");
lv_xml_component_register_from_file("A:lvgl/examples/others/xml/view.xml");
lv_xml_register_font("lv_montserrat_18", &lv_font_montserrat_18);
lv_obj_t * obj = lv_xml_create(lv_screen_active(), "view", NULL);
lv_obj_set_pos(obj, 10, 10);
const char * my_button_attrs[] = {
"x", "10",
"y", "-10",
"align", "bottom_left",
"btn_text", "New button",
NULL, NULL,
};
lv_xml_component_unregister("my_button");
lv_xml_create(lv_screen_active(), "my_button", my_button_attrs);
const char * slider_attrs[] = {
"x", "200",
"y", "-15",
"align", "bottom_left",
"value", "30",
NULL, NULL,
};
lv_obj_t * slider = lv_xml_create(lv_screen_active(), "lv_slider", slider_attrs);
lv_obj_set_width(slider, 100);
}
#endif