Widgets

Learn how to create and use widgets as reusable UI components with XML-based definition and automatic code generation.

Widgets are fundamental building blocks for creating reusable UI components alongside Components and Screens.

Overview

A Widget in LVGL Pro is defined using an XML file with a widget root element. Widgets provide a way to encapsulate UI behavior and appearance into reusable units that can be nested within other Widgets and Components.

Supported Child Elements

Widget definitions support these child XML tags:

  • consts - Define constant values for the widget
  • api - Define the widget's public API and properties
  • styles - Define styling rules and themes
  • view - Define the widget's visual structure and layout
  • previews - Define preview configurations for the Editor

Relationship to Components

Just like Components, Widgets can contain other Widgets and Components as children, allowing you to build complex hierarchies of nested UI elements.

Loading and Parsing

Widgets cannot be instantiated directly from XML in the final application. Instead, each Widget requires an XML parser that maps XML attributes to C function calls. LVGL provides:

  • Built-in XML parsers for standard widgets
  • Helper functions and required libraries for custom parsers
  • Many XML parser examples for reference

Built-in Widgets

The built-in LVGL widgets such as lv_slider, lv_label, and lv_chart already include XML parsers, making them directly available for use in XML files.

Example Usage

xml
<component>
  <view>
    <lv_label x="10" text="Hello"/>
  </view>
</component>

Built-in Widget Structure

Each built-in widget consists of three components:

  • C Implementation - Pure C code defining the widget behavior (e.g., lv_slider.c)
  • XML Definition - An XML schema file used by the Editor for validation and autocomplete (e.g., lv_slider.xml)
  • XML Parser - A C parser file that maps XML attributes to C function calls (e.g., lv_xml_slider_parser.c)

XML Parser

Creating a Custom Parser

To make custom Widgets accessible from XML, you need to create and register an XML parser. The parser translates XML attributes into C function calls.

Here's an example parser for a label widget:

 
void * lv_xml_label_create(lv_xml_parser_state_t * state, const char ** attrs)
{
  /* Create the label */
  void * obj = lv_label_create(lv_xml_state_get_parent(state));
  return obj;
}

void lv_xml_label_apply(lv_xml_parser_state_t * state, const char ** attrs)
{
  void * obj = lv_xml_state_get_item(state);

  /* Apply the common properties, e.g., width, height, styles, flags, etc. */
  lv_xml_obj_apply(state, attrs);

  /* Process the label-specific attributes */
  for(int i = 0; attrs[i]; i += 2) {
    const char * name = attrs[i];
    const char * value = attrs[i + 1];

    if(lv_streq("text", name)) lv_label_set_text(obj, value);
    if(lv_streq("long_mode", name)) lv_label_set_long_mode(obj, long_mode_text_to_enum(value));
    /* Process more props here ... */
  }
}

/* Helper to convert strings to enum values */
static lv_label_long_mode_t long_mode_text_to_enum(const char * txt)
{
  if(lv_streq("wrap", txt)) return LV_LABEL_LONG_MODE_WRAP;
  if(lv_streq("scroll", txt)) return LV_LABEL_LONG_MODE_SCROLL;

  LV_LOG_WARN("%s is an unknown value for label's long_mode", txt);
  return 0; /* Return 0 in the absence of a better option. */
}

The key pattern is using if(lv_streq("property", name)) lv_function_set(obj, value); to map any XML attribute to its corresponding C function call.

Creating Widgets in LVGL Pro Editor

Using the Editor vs Manual Coding

While you can create widgets by writing C code manually (similar to built-in LVGL widgets), using LVGL Pro Editor is significantly faster and simpler.

Generated Files

When you create an XML file with a widget root element, the Editor automatically generates the following C/H files:

Generated on Export (Overwritten Each Time):

  • <widget_name>_gen.h - Contains the generated API implementation
  • <widget_name>_private_gen.h - Contains private API and internal data structures
  • <widget_name>_gen.c - Contains widget internals including constructor, destructor, and event handlers

User-Editable (Created Once, Preserved):

  • <widget_name>.h - Header file that includes widget_name_gen.h and allows custom API definitions
  • <widget_name>.c - Implementation file containing hooks for custom code
  • <widget_name>_xml_parser.c - XML parser skeleton for processing widget attributes

Custom Code Hooks

The <widget_name>.c file contains three extension hooks:

  • Constructor Hook - Called when the widget and all its children are created, allowing modifications to child elements
  • Destructor Hook - Called when the widget is deleted, for freeing manually allocated memory
  • Event Hook - Called at the beginning of the widget's event callback for custom actions

This C file also contains implementations for all setter functions defined in the widget's API. Declarations are automatically exported in <widget_name>_gen.h.

Widget Elements

Elements are internal dynamic parts of a widget that can be accessed or created at runtime. Examples include:

  • Tabs in a tabview
  • List items in a dropdown
  • Series in a chart

Elements are defined in the api tag of your widget's XML, just like other API properties. For detailed information, see the widget element documentation.

How is this guide?

Last updated on

On this page