LVGL Graphics¶
LVGL (Light and Versatile Graphics Library) is a free and open-source embedded graphics library to create beautiful UIs for any MCU, MPU and display type. ESPHome supports LVGL version 8.
Prerequisites¶
To use LVGL with a display in ESPHome, you’ll need an ESP32 or RP2040. PSRAM is not a strict requirement but it is generally recommended, especially for large color displays.
The graphic display should be configured with auto_clear_enabled: false
and should not have any lambda
set. The LVGL component will take care of the display rendering. For most displays, the update_interval
should be set to never
, but note that some displays such as OLED and ePaper will need the update interval set to a suitable value.
For interactivity, a Touchscreen (capacitive highly preferred), a Rotary Encoder Sensor or a custom keypad made up from discrete Binary Sensors can be used.
Check out the detailed examples in the Cookbook which demonstrate a number of ways you can integrate your environment with LVGL and ESPHome.
TL;DR¶
To get started, it is sufficient to add a display and an empty LVGL configuration. If neither pages
nor widgets
is specified, then a default “hello world” page will be shown.
# Example minimal configuration entry
lvgl:
display:
- platform: ...
# ...
auto_clear_enabled: false
update_interval: never
To make LVGL your own you will need to add widgets to the display. For example, to show a label with the text “Hello World!” in the center of the screen:
lvgl:
widgets:
- label:
align: CENTER
text: 'Hello World!'
Now read on to learn more about the configuration options and how to customize your LVGL display.
Basics¶
In LVGL, graphical elements like buttons, labels, sliders, etc. are called widgets or objects. See LVGL Widgets for a complete list of widgets supported within ESPHome. Not all LVGL widgets are implemented, just those commonly used to support home automation needs/tasks.
Every widget has a parent object where it is created. For example, if a label is created on a button, the button is the parent of the label. Complex widgets internally consist of several smaller/simpler widgets; these are known as parts, each of which can have separate properties from the main widget.
Pages in ESPHome are implemented as LVGL screens, which are special objects which have no parent. There is always one active page on a display.
Widgets can be assigned with an ID so that they can be referenced in automations.
Some widgets integrate also as native ESPHome components:
LVGL Widget |
ESPHome component |
---|---|
|
|
|
|
|
|
|
|
|
|
|
These are useful with Home Assistant automations interacting directly with the widgets.
Main Configuration¶
Although LVGL is a complex matrix of objects-parts-states-styles, ESPHome simplifies this into a hierarchy.
At the highest level of the LVGL object hierarchy is the display (represented by the hardware driver). A display can have one or more pages associated with it. Each page contains a hierarchy of objects for graphical widgets representing a layout to be presented on the display.
The following configuration variables apply to the main lvgl
component, in order to establish the principal operating conditions. Some styling options can be set at this level too, but only for inheritance purposes.
Configuration variables:
displays (Optional, list, ID): A list of display IDs where LVGL should perform rendering based on its configuration. This may be omitted if there is a single display configured, which will be used automatically.
- touchscreens (Optional, list): A list of touchscreens interacting with the LVGL widgets on the display. If you configure a single touchscreen it will be used automatically, and this config entry will not be required.
touchscreen_id (Required, ID): ID of a touchscreen configuration related to a display.
long_press_time (Optional, Time): For the touchscreen, delay after which the
on_long_pressed
interaction trigger will be called. Defaults to400ms
.long_press_repeat_time (Optional, Time): For the touchscreen, repeated interval after
long_press_time
, whenon_long_pressed_repeat
interaction trigger will be called. Defaults to100ms
.
- encoders (Optional, list): A list of rotary encoders interacting with the LVGL widgets on the display.
group (Optional, string): A name for a group of widgets which will interact with the the input device. See the common properties of the widgets for more information on groups.
initial_focus (Optional, ID): An optional ID for a widget to be given focus on startup (especially useful if there is only one focusable widget.)
enter_button (Required, ID): The ID of a Binary Sensor, to be used as
ENTER
key.- sensor (Optional, ID): The ID of a Rotary Encoder Sensor; or a list with buttons for left/right interaction with the widgets:
left_button (Optional, ID): The ID of a Binary Sensor, to be used as
LEFT
key.right_button (Optional, ID): The ID of a Binary Sensor, to be used as
RIGHT
key.
long_press_time (Optional, Time): For the rotary encoder, delay after which the
on_long_pressed
interaction trigger will be called. Defaults to400ms
. Can be disabled withnever
.long_press_repeat_time (Optional, Time): For the rotary encoder, repeated interval after
long_press_time
, whenon_long_pressed_repeat
interaction trigger will be called. Defaults to100ms
. Can be disabled withnever
.
- keypads (Optional, list): A list of keypads interacting with the LVGL widgets on the display.
group (Optional, string): A name for a group of widgets which will interact with the the input device. See the common properties of the widgets for more information on groups.
up (Optional, ID): The ID of a Binary Sensor, to be used as
UP
key.down (Optional, ID): The ID of a Binary Sensor, to be used as
DOWN
key.right (Optional, ID): The ID of a Binary Sensor, to be used as
RIGHT
key.left (Optional, ID): The ID of a Binary Sensor, to be used as
LEFT
key.esc (Optional, ID): The ID of a Binary Sensor, to be used as
ESC
key.del (Optional, ID): The ID of a Binary Sensor, to be used as
DEL
key.backspace (Optional, ID): The ID of a Binary Sensor, to be used as
BACKSPACE
key.enter (Optional, ID): The ID of a Binary Sensor, to be used as
ENTER
key.next (Optional, ID): The ID of a Binary Sensor, to be used as
NEXT
key.prev (Optional, ID): The ID of a Binary Sensor, to be used as
PREV
key.home (Optional, ID): The ID of a Binary Sensor, to be used as
HOME
key.end (Optional, ID): The ID of a Binary Sensor, to be used as
END
key.long_press_time (Optional, Time): For the keypad, delay after which the
on_long_pressed
interaction trigger will be called. Defaults to400ms
. Can be disabled withnever
.long_press_repeat_time (Optional, Time): For the keypad, repeated interval after
long_press_time
, whenon_long_pressed_repeat
interaction trigger will be called. Defaults to100ms
. Can be disabled withnever
.
Tip
When using binary sensors (from physical keys) to interact with LVGL, if there are only three keys available, they are best used when configured as a rotary encoder, where
LEFT
andRIGHT
act like the rotary wheel, andENTER
generates anon_press
trigger. With four or more keys, a keypad configuration is generally more appropriate. For example, a keypad consisting of five keys might usePREV
,NEXT
,UP
,DOWN
andENTER
;PREV
/NEXT
are used to select a widget within the group,UP
/DOWN
changes the selected value andENTER
generates anon_press
trigger.The
long_press_time
andlong_press_repeat_time
can be fine-tuned also by setting them tonever
and using theautorepeat
filter on each binary sensor separately.Tip
When using an encoder input device the navigation works as follows:
By turning the encoder you can focus on the next/previous object.
When you press the encoder on a simple object (like a button), it will be clicked.
If you press the encoder on a complex object (like a list, message box, etc.) the object will go to edit mode whereby you can adjust the value of the object by turning the encoder.
To leave edit mode, long press the button.
resume_on_input (Optional, boolean): If LVGL is paused and the user interacts with the screen, resume the activity of LVGL. Defaults to
true
. “Interacts” means to release a touch or button, or rotate an encoder.color_depth (Optional, string): The color depth at which the contents are generated. Currently only
16
is supported (RGB565, 2 bytes/pixel), which is the default value.buffer_size (Optional, percentage): The percentage of screen size to allocate buffer memory. Default is
100%
(or1.0
). For devices without PSRAM, the recommended value is25%
.draw_rounding (Optional, int): An optional value to use for rounding draw areas to a specified boundary. Defaults to 2. Useful for displays that require draw windows to be on specified boundaries (usually powers of 2.)
log_level (Optional, string): Set the logger level specifically for the messages of the LVGL library:
TRACE
,INFO
,WARN
,ERROR
,USER
,NONE
. Defaults toWARN
.byte_order (Optional, int16): The byte order of the data LVGL outputs; either
big_endian
orlittle_endian
. Defaults tobig_endian
.disp_bg_color (Optional, color): Solid color used to fill the background. Can be changed at runtime with the
lvgl.update
action.disp_bg_image (Optional, image): The ID of an existing image configuration, to be used as background wallpaper. To change the image at runtime use the
lvgl.update
action. Also see image for a note regarding supported image formats.default_font (Optional, ID): The ID of the font used by default to render the text or symbols. Defaults to LVGL’s internal
montserrat_14
if not specified.style_definitions (Optional, list): A batch of style definitions to use in LVGL widget’s
styles
configuration. See below for more details.gradients (Optional, list): A list of gradient definitions to use in bg_grad styles. See below for more details.
theme (Optional, list): A list of styles to be applied to all widgets. See below for more details.
widgets (Optional, list): A list of LVGL Widgets to be drawn on the root display. May not be used if
pages
(below) is configured.- pages (Optional, list): A list of page IDs. Each page acts as a parent for widgets placed on it. May not be used with
widgets
(above). Options for each page: skip (Optional, boolean): Option to skip this page when navigating between them with lvgl.page.next, lvgl.page.previous.
layout (Optional): See Layouts for details. Defaults to
NONE
.widgets (Optional, list): A list of LVGL Widgets to be drawn on the page.
All other options from Style properties to be applied to this page.
- pages (Optional, list): A list of page IDs. Each page acts as a parent for widgets placed on it. May not be used with
page_wrap (Optional, boolean): Wrap from the last to the first page when navigating between them with lvgl.page.next, lvgl.page.previous. Defaults to
true
.- top_layer (Optional, list): A special kind of Always on Top page, which acts as a parent for widgets placed on it. It’s shown above all the pages, which may be useful for widgets which always need to be visible.
layout (Optional): See Layouts for details. Defaults to
NONE
.widgets (Optional, list): A list of LVGL Widgets to be drawn on the page.
All other options from Style properties to be applied to this page.
layout (Optional): See Layouts for details. Defaults to
NONE
.All other options from Style properties to be applied to all widgets directly.
Example:
# Example configuration entry
lvgl:
displays:
- my_display
pages:
- id: main_page
widgets:
- label:
align: CENTER
text: 'Hello World!'
See Page navigation footer in the Cookbook for an example which demonstrates how to implement a page navigation bar at the bottom of the screen.
Multiple LVGL configurations¶
If you have multiple displays configured, and wish to have different content displayed on each display, you can configure multiple LVGL configurations. For example:
lvgl:
- id: lvgl_1
displays: display_1
widgets:
- label:
text: 'Hello World #1!'
- id: lvgl_2
displays: display_2
widgets:
- label:
text: 'Hello World #2!'
Colors¶
Colors can be specified anywhere in the LVGL configuration either by referencing a preconfigured ESPHome color ID or by representing the color in the common hexadecimal notation. For example, 0xFF0000
would be red.
You may also use any of the standard CSS color names, e.g. springgreen
.
Opacity¶
Various parts of the widgets (like background, borders etc.) support opacity. It can be overridden with a string: TRANSP
for fully transparent, COVER
for fully opaque, or percentage between 0%
and 100%
. Actual default values depend on widget specifics.
Fonts¶
Two font choices are available:
ESPHome fonts
You can use fonts configured normally, the glyphs will be rendered while building the binary. This has the advantage that you can define custom sets of glyphs of any size, with icons or diacritic characters of your choice, for any language, from any TrueType/OpenType font, allowing a more optimal flash space usage because you don’t need to include all glyphs for all sizes you wish to use.
Tip
For best results, set bpp: 4
to get the glyphs rendered with proper anti-aliasing.
Check out MDI icons in text, Toggle state icon button and Battery status icon in the Cookbook for examples which demonstrate how to use icons and text with TrueType/OpenType fonts.
Library fonts
The LVGL library offers by default prerendered sets with ASCII characters (0x20-0x7F
), the degree symbol (0xB0
), the bullet symbol (0x2022
) from Montserrat Medium, and 60 symbols from FontAwesome (see below). You can use the IDs below when specifying the text_font
parameter:
montserrat_8
: 8px fontmontserrat_10
: 10px fontmontserrat_12
: 12px fontmontserrat_14
: 14px font (default, included ifdefault_font
option is missing)montserrat_16
: 16px fontmontserrat_18
: 18px fontmontserrat_20
: 20px fontmontserrat_22
: 22px fontmontserrat_24
: 24px fontmontserrat_26
: 26px fontmontserrat_28
: 28px fontmontserrat_30
: 30px fontmontserrat_32
: 32px fontmontserrat_34
: 34px fontmontserrat_36
: 36px fontmontserrat_38
: 38px fontmontserrat_40
: 40px fontmontserrat_42
: 42px fontmontserrat_44
: 44px fontmontserrat_46
: 46px fontmontserrat_48
: 48px font
The binary will only include any of the above if used in the configuration.
You can display the embedded symbols among the text by their codepoint address preceded by \u
. For example: \uF00C
:
Note
The text_font
parameter affects the size of symbols, since all the built-in font arrays based on Montserrat include these symbols at the respective sizes. If you set text_font
on a widget to a custom ESPHome font, these symbols will likely not display, unless you include them manually from a FontAwesome OpenType file.
For escape sequences to work, you have to put them in strings enclosed in double quotes.
In addition to the above, the following special fonts are available from LVGL as built-in:
unscii_8
: 8 px pixel perfect font with only ASCII characters.unscii_16
: 16 px pixel perfect font with only ASCII characters.simsun_16_cjk
: 16 px font with normal range + 1000 most common CJK Radicals.dejavu_16_persian_hebrew
: 16 px font with normal range + Hebrew, Arabic, Persian letters and all their forms.
Style properties¶
LVGL follows CSS’s border-box model. A widget’s box is built from the following parts:
bounding box: the box defined with
width
andheight
of the widgets (pixels or parent content area percentage; not drawn, just for calculations).border: the border line, drawn on the inner side of the bounding box (pixels).
outline: the outline, drawn on the outer side of the bounding box (pixels).
padding: space to keep between the border of the widget and its content or children (I don’t want my children too close to my sides, so keep this space).
content: the content area which is the size of the bounding box reduced by the border width and padding (it’s what’s referenced as the
SIZE_CONTENT
option of certain widgets).
You can adjust the appearance of widgets by changing their foreground, background, border color and/or font. Some widgets allow for more complex styling, effectively changing all or part of their appearance.
Styling variables:
bg_color (Optional, color): Color for the background of the widget. Defaults to
0xFFFFFF
(white).bg_grad (Optional, gradient): A gradient to apply to the background.
bg_grad_color (Optional, color): Color to make the background gradually fade to. Defaults to
0
(black).bg_dither_mode (Optional, dict): Set dithering of the background gradient. One of
NONE
,ORDERED
,ERR_DIFF
. Defaults toNONE
.bg_grad_dir (Optional, dict): Choose the direction of the background gradient:
NONE
,HOR
,VER
. Defaults toNONE
.bg_main_stop (Optional, 0-255): Specify where the gradient should start:
0
= upper left,128
= in the center,255
= lower right. Defaults to0
.bg_grad_stop (Optional, 0-255): Specify where the gradient should stop:
0
= upper left,128
= in the center,255
= lower right. Defaults to255
.opa (Optional, opacity): Opacity of the entire widget. Inherited from parent. Defaults to
COVER
.bg_opa (Optional, opacity): Opacity of the widget background.
opa_layered (Optional, opacity): Opacity of the entire layer the widget is on. Inherited from parent. Defaults to
COVER
.bg_image_src (Optional, image): The ID of an existing image configuration, to show as the background of the widget.
bg_image_opa (Optional, opacity): Opacity of the background image of the widget.
bg_image_recolor (Optional, color): Color to mix with every pixel of the background image of the widget.
bg_image_recolor_opa (Optional, opacity): Opacity of the recoloring of the background image of the widget.
border_width (Optional, int16): Set the width of the border in pixels. Defaults to
0
.border_color (Optional, color): Color to draw borders of the widget. Defaults to
0
(black).border_opa (Optional, opacity): Opacity of the borders of the widget. Defaults to
COVER
.border_post (Optional, boolean): If
true
the border will be drawn after all children of the widget have been drawn. Defaults tofalse
.- border_side (Optional, list): Select which borders of the widgets to show (multiple can be specified as a YAML list, defaults to
NONE
): NONE
TOP
BOTTOM
LEFT
RIGHT
INTERNAL
- border_side (Optional, list): Select which borders of the widgets to show (multiple can be specified as a YAML list, defaults to
clip_corner (Optional, boolean): If set to
true
, overflowing content will be clipped off by the widget’s rounded corners (radius
>0
).color_filter_opa (Optional, opacity): Opacity of the color filter. Currently color filters are applied only by the default LVGL theme, this option allows the effect of those to be disabled by setting to
TRANSP
.outline_width (Optional, int16): Set the width of the outline in pixels. Defaults to
0
.outline_color (Optional, color): Color used to draw an outline around the widget. Defaults to
0
(black).outline_opa (Optional, opacity): Opacity of the outline of the widget. Defaults to
COVER
.outline_pad (Optional, int16): Distance between the outline and the widget itself. Defaults to
0
.pad_all (Optional, int16): Set the padding in all directions, in pixels.
pad_top (Optional, int16): Set the padding on the top, in pixels.
pad_bottom (Optional, int16): Set the padding on the bottom, in pixels.
pad_left (Optional, int16): Set the padding on the left, in pixels.
pad_right (Optional, int16): Set the padding on the right, in pixels.
pad_row (Optional, int16): Set the padding between the rows of the children elements, in pixels.
pad_column (Optional, int16): Set the padding between the columns of the children elements, in pixels.
radius (Optional, uint16): The radius to be used to form the widget’s rounded corners. 0 = no radius (square corners); 65535 (max) = pill shaped widget (true circle if it has same width and height, radius then should be set to half the width/height).
shadow_color (Optional, color): Color used to create a drop shadow under the widget. Defaults to
0
(black).shadow_ofs_x (Optional, int16): Horizontal offset of the shadow, in pixels. Defaults to
0
.shadow_ofs_y (Optional, int16): Vertical offset of the shadow, in pixels. Defaults to
0
.shadow_opa (Optional, opacity): Opacity of the shadow. Defaults to
COVER
.shadow_spread (Optional, int16): Spread of the shadow, in pixels. Defaults to
0
.shadow_width (Optional, int16): Width of the shadow, in pixels. Defaults to
0
.transform_angle (Optional, 0-360): Transformation angle of the widget (eg. rotation)
transform_height (Optional, int16 or percentage): Transformation height of the widget (eg. stretching)
transform_pivot_x (Optional, int16): Horizontal anchor point of the transformation. Relative to the widget’s top left corner.
transform_pivot_y (Optional, int16): Vertical anchor point of the transformation. Relative to the widget’s top left corner.
transform_zoom (Optional, 0.1-10): Transformation zoom of the widget (eg. resizing)
translate_x (Optional, int16 or percentage): Movement of the widget with this value in horizontal direction.
translate_y (Optional, int16 or percentage): Movement of the widget with this value in vertical direction.
Themes¶
The widgets support lots of Style properties to customize their appearance and behavior.
You can configure a global theme for all widgets at the top level with the theme
configuration variable. In the example below, all the arc
, slider
and button
widgets will, by default, use the styles and properties defined here. A combination of styles and states can be chosen for every widget.
lvgl:
theme:
arc:
scroll_on_focus: true
group: general
slider:
scroll_on_focus: true
group: general
button:
scroll_on_focus: true
group: general
border_width: 2
outline_pad: 6
pressed:
border_color: 0xFF0000
checked:
border_color: 0xFFFF00
focused:
border_color: 0x00FF00
Naturally, you can override these at the individual configuration level of each widget. This can be done in batches, using the style_definitions
configuration variable of the main component.
In the example below, you defined date_style
:
lvgl:
style_definitions:
- id: date_style # choose an ID for your definition
text_font: unscii_8
align: center
text_color: 0x000000
bg_opa: cover
radius: 4
pad_all: 2
And then you apply these selected styles to two labels, and only change very specific style y
locally:
widgets:
- label:
id: day_label
styles: date_style # apply the definition here by the ID chosen above
y: -20
- label:
id: date_label
styles: date_style
y: +20
Additionally, you can change the styles based on the state property of the widgets or their parts. If you want to set a property for all states (e.g. red background color) just set it for the default state at the root of the widget. If the widget can’t find a property for its current state it will fall back to this.
In the example below, you have an arc
with some styles set here. Note how you change the arc_color
of the indicator
part, based on state changes:
- arc:
id: my_arc
value: 75
min_value: 1
max_value: 100
indicator:
arc_color: 0xF000FF
pressed:
arc_color: 0xFFFF00
focused:
arc_color: 0x808080
So the precedence happens like this: state based styles override the locally specified styles, which override the style definitions, which override the theme, which overrides the top level styles. The value precedence of states is quite intuitive and it’s something the user would expect naturally. For example, if a widget is focused the user will still want to see if it’s pressed, therefore the pressed state has a higher precedence. (If the focused state had a higher precedence it would override the pressed color, defeating its purpose.)
Feel free to experiment to discover inheritance and precedence of the styles based on states between the nested widgets.
Theme and style definitions The Cookbook contains an example which demonstrates how to implement a gradient style for your widgets.
Layouts¶
Layouts aim to position widgets automatically, eliminating the need to specify x
and y
coordinates to position each widget. This is a great way to simplify your configuration as it allows you to omit alignment options.
The layout configuration options are applied to any parent widget or page, influencing the appearance of the children. The position and size calculated by the layout overwrites the normal x
, y
, width
, and height
settings of the children.
Check out Flex layout positioning, Grid layout positioning and Weather forecast panel in the Cookbook for examples which demonstrate how to automate widget positioning, potentially reducing the size of your device’s YAML configuration, and saving you from lots of manual calculations.
The hidden
, ignore_layout
and floating
flags can be used on widgets to ignore them in layout calculations.
Configuration variables:
- layout (Optional, dict): A dictionary describing the layout configuration:
type (Optional, string):
FLEX
,GRID
orNONE
. Defaults toNONE
.Further options from below depending on the chosen type.
Flex
The Flex layout in LVGL is a subset implementation of CSS Flexbox.
It can arrange items into rows or columns (tracks), handle wrapping, adjust spacing between items and tracks and even handle growing the layout to make the item(s) fill the remaining space with respect to minimum/maximum width and height.
Terms used:
track: the rows or columns main direction flow: row or column in the direction in which the items are placed one after the other.
cross direction: perpendicular to the main direction.
wrap: if there is no more space in the track a new track is started.
gap: the space between the rows and columns or the items on a track.
grow: if set on an item it will grow to fill the remaining space on the track. The available space will be distributed among items respective to their grow value (larger value means more space). It dictates what amount of the available space the widget should take up. For example if all items on the track have a
grow
set to1
, the space in the track will be distributed equally to all of them. If one of the items has a value of 2, that one would take up twice as much of the space as either one of the others.
Configuration variables:
- flex_flow (Optional, string): Select the arrangement of the children widgets:
ROW
: place the children in a row without wrapping.
COLUMN
: place the children in a column without wrapping.
ROW_WRAP
: place the children in a row with wrapping (default).
COLUMN_WRAP
: place the children in a column with wrapping.
ROW_REVERSE
: place the children in a row without wrapping but in reversed order.
COLUMN_REVERSE
: place the children in a column without wrapping but in reversed order.
ROW_WRAP_REVERSE
: place the children in a row with wrapping but in reversed order.
COLUMN_WRAP_REVERSE
: place the children in a column with wrapping but in reversed order.flex_align_main (Optional, string): Determines how to distribute the items in their track on the main axis. For example, flush the items to the right on with
flex_flow: ROW_WRAP
(known as justify-content in CSS). Possible options below.flex_align_cross (Optional, string): Determines how to distribute the items in their track on the cross axis. For example, if the items have different height place them to the bottom of the track (known as align-items in CSS). Possible options below.
flex_align_track (Optional, string): Determines how to distribute the tracks (known as align-content in CSS). Possible options below.
Values for use with
flex_align_main
,flex_align_cross
,flex_align_track
:
START
: means left horizontally and top vertically (default).
END
: means right horizontally and bottom vertically.
CENTER
: simply center.
SPACE_EVENLY
: items are distributed so that the spacing between any two items (and the space to the edges) is equal. Does not apply toflex_align_track
.
SPACE_AROUND
: items are evenly distributed in the track with equal space around them. Note that visually the spaces aren’t equal, since all the items have equal space on both sides. The first item will have one unit of space against the container edge, but two units of space between the next item because that next item has its own spacing that applies. Does not apply toflex_align_track
.
SPACE_BETWEEN
: items are evenly distributed in the track: first item is on the start line, last item on the end line. Does not apply toflex_align_track
.
pad_row (Optional, int16): Set the padding between the rows, in pixels.
pad_column (Optional, int16): Set the padding between the columns, in pixels.
flex_grow (Optional, int16): Can be used to make one or more children fill the available space on the track. When one or more children have
flex_grow
set, the available space will be distributed proportionally to the grow values. Defaults to0
, which disables growing.
# Example flex layout
- obj:
layout:
type: flex
pad_row: 4
pad_column: 4px
flex_align_main: center
flex_align_cross: start
flex_align_track: end
widgets:
- animimg:
flex_grow: 1
Grid
The Grid layout in LVGL is a subset implementation of CSS Grid.
It can arrange items into a 2D “table” that has rows or columns (tracks). The item(s) can span through multiple columns or rows. The track’s size can be set in pixels, to the largest item of the track (CONTENT
) or in “free units” to distribute the free space proportionally.
Terms used:
tracks: the rows or the columns.
gap: the space between the rows and columns or the items on a track.
free unit (FR): a proportional distribution unit for the space available on the track. It accepts a unitless integer value that serves as a proportion. It dictates what amount of the available space the widget should take up. For example if all items on the track have a
FR
set to1
, the space in the track will be distributed equally to all of them. If one of the items has a value of 2, that one would take up twice as much of the space as either one of the others.
Configuration variables:
grid_rows (Required): The number of rows in the grid, expressed a list of values in pixels,
CONTENT
orFR(n)
(free units, wheren
is a proportional integer value).grid_columns (Required): The number of columns in the grid, expressed a list of values in pixels,
CONTENT
orFR(n)
(free units, wheren
is a proportional integer value).grid_row_align (Optional, string): How to align the row. Works only when
grid_rows
is given in pixels. Possible options below.grid_column_align (Optional, string): How to align the column. Works only when
grid_columns
is given in pixels. Possible options below.pad_row (Optional, int16): Set the padding between the rows, in pixels.
pad_column (Optional, int16): Set the padding between the columns, in pixels.
In a grid layout, all the widgets placed on the grid will get some additional configuration variables to help with placement:
grid_cell_row_pos (Required, int16): Position of the widget, in which row to appear (0 based count).
grid_cell_column_pos (Required, int16): Position of the widget, in which column to appear (0 based count).
grid_cell_x_align (Optional, string): How to align the widget horizontally within the cell. Can also be applied through Style properties. Possible options below.
grid_cell_y_align (Optional, string): How to align the widget vertically within the cell. Can also be applied through Style properties. Possible options below.
grid_cell_row_span (Optional, int16): How many rows to span across the widget. Defaults to
1
.grid_cell_column_span (Optional, int16): How many columns to span across the widget. . Defaults to
1
.Note
These
grid_cell_
variables apply to widget configuations!
Values for use with grid_column_align
, grid_row_align
, grid_cell_x_align
, grid_cell_y_align
:
START
: means left horizontally and top vertically (default).
END
: means right horizontally and bottom vertically.
CENTER
: simply center.
STRETCH
: stretch the widget to the cell in the respective direction. Does not apply togrid_column_align
,grid_row_align
.
SPACE_EVENLY
: items are distributed so that the spacing between any two items (and the space to the edges) is equal.
SPACE_AROUND
: items are evenly distributed in the track with equal space around them. Note that visually the spaces aren’t equal, since all the items have equal space on both sides. The first item will have one unit of space against the container edge, but two units of space between the next item because that next item has its own spacing that applies.
SPACE_BETWEEN
: items are evenly distributed in the track: first item is on the start line, last item on the end line.
# Example grid layout
- obj:
layout:
type: grid
grid_row_align: end
grid_rows: [25px, fr(1), content]
grid_columns: [40, fr(1), fr(1)]
pad_row: 6px
pad_column: 0
widgets:
- image:
grid_cell_row_pos: 0
grid_cell_column_pos: 0
Tip
To visualize real, calculated sizes of transparent widgets you can temporarily set outline_width: 1
on them.
Gradients¶
- A gradient is a sequence of colors which can be applied to an object using the
bg_grad
style option. Gradients are defined in the gradients section of the LVGL configuration by providing two or more color stop points. Each entry has the following options:
id (Required, ID): The ID with which you will be able to reference the gradient later.
direction (Optional, string): The direction of the gradient. Possible options are
none
(the default)hor
orver
.dither (Optional, string): A dithering selection. Possible options are
none
(the default)err_diff
orordered
.- stops (Required, list): A list of at least 2 color stop points. Each stop point has the following options:
color (Required, Color): The color of the stop point.
position (Required, float): The position of the stop point. Must be a float between 0.0 and 1.0, a percentage between 0% and 100%, or an integer between 0 and 255.
# Example gradient showing full hue range.
gradients:
- id: color_bar
direction: hor
dither: none
stops:
- color: 0xFF0000
position: 0
- color: 0xFFFF00
position: 42
- color: 0x00FF00
position: 84
- color: 0x00FFFF
position: 127
- color: 0x0000FF
position: 169
- color: 0xFF00FF
position: 212
- color: 0xFF0000
position: 255
Widgets¶
LVGL supports a list of LVGL Widgets which can be used to draw interactive objects on the screen.
Actions¶
Widgets support general or specific actions - see the LVGL Widgets section for more information.
Several actions are available for the LVGL component itself, these are outlined below. Note that if multiple LVGL instances are configured, an lvgl_id config entry will be required to specify which instance the action relates to. This is not required if there is only a single LVGL instance configured.
lvgl.widget.redraw
¶
This action redraws the entire screen, or optionally only a widget on it.
id (Optional): The ID of a widget configured in LVGL which you want to redraw; if omitted, the entire screen will be redrawn.
lvgl_id (Optional): The ID of the LVGL instance to redraw.
on_...:
then:
- lvgl.widget.redraw:
lvgl_id: lvgl1 # optional when only one LVGL instance is configured
lvgl.pause
¶
This action pauses the activity of LVGL, including rendering.
show_snow (Optional, boolean): When paused, display random colored pixels across the entire screen in order to minimize screen burn-in, to relief the tension put on each individual pixel. See Prevent burn-in of LCD for an example which demonstrates how to use this.
lvgl_id (Optional): The ID of the LVGL instance to pause.
on_...:
then:
- lvgl.pause:
show_snow: true
lvgl.resume
¶
This action resumes the activity of LVGL, including rendering.
lvgl_id (Optional): The ID of the LVGL instance to resume.
on_...:
then:
- lvgl.resume:
lvgl.update
¶
This action allows changing/updating the disp_bg_color
or disp_bg_image
configuration variables of the main component, making it possible to change the background color or wallpaper at any time.
# Examples:
on_...:
then:
- lvgl.update:
disp_bg_color: 0x0000FF
- lvgl.update:
disp_bg_image: cat_image
lvgl.page.next
, lvgl.page.previous
¶
This action changes the page to the next/previous based on the configuration (pages with their skip
option enabled are…skipped). Page changes will wrap around at the end.
animation (Optional): Animate page changes as specified. One of:
NONE
,OVER_LEFT
,OVER_RIGHT
,OVER_TOP
,OVER_BOTTOM
,MOVE_LEFT
,MOVE_RIGHT
,MOVE_TOP
,MOVE_BOTTOM
,FADE_IN
,FADE_OUT
,OUT_LEFT
,OUT_RIGHT
,OUT_TOP
,OUT_BOTTOM
. Defaults toNONE
.time (Optional, Time): Duration of the page change animation. Defaults to
50ms
.
on_...:
then:
- lvgl.page.next:
animation: OUT_LEFT
time: 300ms
on_...:
then:
- lvgl.page.previous:
animation: OUT_RIGHT
time: 300ms
lvgl.page.show
¶
This action shows a specific page (including pages with their skip
option enabled).
id (Required): The ID of the page to be shown.
animation (Optional): Animate page changes as specified. One of:
NONE
,OVER_LEFT
,OVER_RIGHT
,OVER_TOP
,OVER_BOTTOM
,MOVE_LEFT
,MOVE_RIGHT
,MOVE_TOP
,MOVE_BOTTOM
,FADE_IN
,FADE_OUT
,OUT_LEFT
,OUT_RIGHT
,OUT_TOP
,OUT_BOTTOM
. Defaults toNONE
.time (Optional, Time): Duration of the page change animation. Defaults to
50ms
.
on_...:
then:
- lvgl.page.show:
id: secret_page
on_...:
then:
- lvgl.page.show: secret_page # shorthand version
lvgl.widget.focus
¶
This action moves the input focus to the nominated widget. Used mainly with encoder inputs to select a specific widget to receive input events. It may also allow the focus to be frozen on that widget, or can be used to move the focus to the next or previous widget in the focus group.
The required config options take one of several forms:
id (Required): The ID of the widget to be given focus.
freeze (Optional, boolean): If true will lock the focus to this widget.
editing (Optional, boolean): Sets the editing mode of the widget, i.e. encoder rotation will change the value of the widget, not move the focus. Defaults to false.
or
action (Required): Should be one of
next
,previous
,mark
orrestore
.group (Optional): The ID of the group within which to move the focus. The default group will be used if not specified
freeze (Optional, boolean): If true will lock the focus to the now selected widget.
The next
and previous
actions will move the focus to the next or previous widget within the group.
The mark
action will save the currently focused widget within the group, and restore it when the restore
action is triggered.
on_...:
then:
- lvgl.widget.focus:
id: my_button
freeze: true
on_...:
then:
- lvgl.widget.focus: my_button
on_...:
then:
- lvgl.widget.focus:
group: encoder_group
direction: next
freeze: true
on_...:
then:
- lvgl.widget.focus: previous
Conditions¶
lvgl.is_idle
¶
This condition checks if the amount of time specified has passed since the last touch event.
timeout (Required, templatable, int): Amount of time expected since the last touch event.
lvgl_id (Optional): The ID of the LVGL instance to monitor.
# In some trigger:
on_...:
then:
- if:
condition:
lvgl.is_idle:
timeout: 5s
then:
- light.turn_off:
id: display_backlight
transition_length: 3s
lvgl.is_paused
¶
This condition checks if LVGL is in the paused state or not.
lvgl_id (Optional): The ID of the LVGL instance to monitor.
# In some trigger:
on_...:
then:
- if:
condition: lvgl.is_paused
then:
- lvgl.resume:
Triggers¶
Widget level interaction triggers are available, plus a few for the LVGL component itself:
on_idle
¶
LVGL has a notion of screen inactivity – i.e. the time since the last user interaction with the screen is tracked. This can, for example, be used to dim the display backlight or turn it off after a moment of inactivity (like a screen saver). Every use of an input device (touchscreen, rotary encoder) counts as an activity and resets the inactivity counter.
The on_idle
triggers are activated when inactivity time becomes longer than the specified timeout
. You can configure any desired number of timeouts with different actions.
timeout (Required, templatable, int): Time that has elapsed since the last touch event, after which the trigger will be invoked.
lvgl:
...
on_idle:
- timeout: 30s
then:
- lvgl.page.show: main_page
- timeout: 60s
then:
- light.turn_off: display_backlight
- lvgl.pause:
See Turn off screen when idle for an example which demonstrates how to implement screen saving with idle settings.
on_pause
¶
This trigger is triggered when LVGL is paused. This can be used to perform any desired actions when the screen is locked, such as turning off the display backlight.
on_resume
¶
This trigger is triggered when LVGL is resumed. This can be used to perform any desired actions when the screen is unlocked, such as turning on the display backlight.