Styles

Styles are used to set the appearance of the objects. A style is a structure with attributes like colors, paddings, opacity, font, etc.

There is a common style type called lv_style_t for every object type.

By setting the fields of the lv_style_t variables and assigning them to objects with lv_obj_set_style, you can influence the appearance of the objects.

Important

The objects only store a pointer to a style so the style cannot be a local variable which is destroyed after the function exits. You should use static, global or dynamically allocated variables.

/* file scope */
lv_style_t style_1;             /*OK! Global variables for styles are fine*/
static lv_style_t style_2;      /*OK! Static variables outside the functions are fine*/
void my_screen_create(void)
{
  /* function scope */
  static lv_style_t style_3;    /*OK! Static variables in the functions are fine*/
  lv_style_t style_4;           /*WRONG! Styles can't be local variables*/

  ...
}

Use the styles

Objects have a main style which determines the appearance of their background or main section. However, some object types have additional styles too.

For example, a slider has 3 styles:

  • Background (main style)

  • Indicator

  • Know

Some object types only have one style. For example:

  • Label

  • Image

  • Line, etc.

Every object type implements its own version of the style setter and getter functions. You should use these instead of lv_obj_set_style where possible. For example:

const lv_style_t * btn_style = lv_btn_get_style(btn, LV_BTN_STYLE_REL);
lv_btn_set_style(btn, LV_BTN_STYLE_REL, &new_style);

To see the styles supported by an object type (LV_<OBJ_TYPE>STYLE<STYLE_TYPE>), check the documentation of the particular Object type.

If you modify a style which is already used by one or more objects, then the objects have to be notified about the style is changed. There are two options to do this notification:

/*Notify an object about its style is modified*/
void lv_obj_refresh_style(lv_obj_t * obj);

/*Notify all objects with a given style. (NULL to notify all objects)*/
void lv_obj_report_style_mod(void * style);

lv_obj_report_style_mod will only refresh the Main styles of objects. If you change a different style, you will have to use lv_obj_refresh_style.

Inherit styles

If the Main style of an object is NULL, then its style will be inherited from its parent’s style. It makes easier to create a consistent design. Don’t forget a style describes a lot of properties at the same time. So for example, if you set a button’s style and create a label on it with NULL style, then the label will be rendered according to the button’s style. In other words, the button makes sure its children will look good on it.

Setting the glass style property will prevent inheriting that style (i.e. cause the child object to inherit its style from its grandparent). You should use it if the style is transparent so children use colors and features from its grandparent. Otherwise, the child objects would also be transparent.

Style properties

A style has 5 main parts: common, body, text, image and line. Each object type only uses the fields which are relevant to it. For example, Lines don’t care about the letter_space, because they are not concerned with rendering text.

To see which fields are used by an object type, see their Documentation.

The fields of a style structure are the followings:

Common properties

  • glass 1: Do not inherit this style

Body style properties

Used by the rectangle-like objects

  • body.main_color Main color (top color)

  • body.grad_color Gradient color (bottom color)

  • body.radius Corner radius. (set to LV_RADIUS_CIRCLE to draw circle)

  • body.opa Opacity (0..255 or LV_OPA_TRANSP, LV_OPA_10, LV_OPA_20LV_OPA_COVER)

  • body.border.color Border color

  • body.border.width Border width

  • body.border.part Border parts (LV_BORDER_LEFT/RIGHT/TOP/BOTTOM/FULL or ‘OR’ed values)

  • body.border.opa Border opacity (0..255 or LV_OPA_TRANSP, LV_OPA_10, LV_OPA_20LV_OPA_COVER)

  • body.shadow.color Shadow color

  • body.shadow.width Shadow width

  • body.shadow.type Shadow type (LV_SHADOW_BOTTOM/FULL)

  • body.padding.top Top padding

  • body.padding.bottom Bottom padding

  • body.padding.left Left padding

  • body.padding.right Right padding

  • body.padding.inner Inner padding (between content elements or children)

Text style properties

Used by the objects which show texts

  • text.color Text color

  • text.sel_color Selected text color

  • text.font Pointer to a font

  • text.opa Text opacity (0..255 or LV_OPA_TRANSP, LV_OPA_10, LV_OPA_20 … LV_OPA_COVER*)

  • text.letter_space Letter space

  • text.line_space Line space

Image style properties

Used by image-like objects or icons on objects

  • image.color Color for image re-coloring based on the brightness of its pixels

  • image.intense Re-color intensity (0..255 or LV_OPA_TRANSP, LV_OPA_10, LV_OPA_20LV_OPA_COVER)

  • image.opa Overall image opacity (0..255 or LV_OPA_TRANSP, LV_OPA_10, LV_OPA_20LV_OPA_COVER)

Line style properties

Used by objects containing lines or line-like elements

  • line.color Line color

  • line.width Line width

  • line.opa Line opacity (0..255 or LV_OPA_TRANSP, LV_OPA_10, LV_OPA_20LV_OPA_COVER)

Built-in styles

There are several built-in styles in the library:

Built-in styles in LittlevGL Embedded Graphics Library

As you can see, there are built-in styles for screens, buttons, solid containers, and transparent containers.

The lv_style_transp, lv_style_transp_fit and lv_style_transp_tight differ only in paddings: for lv_style_transp_tight all paddings are zero, for lv_style_transp_fit only horizontal and vertical paddings are zero but has inner padding.

Important

Transparent built-in styles have glass = 1 by default which means these styles (e.g. their colors) won’t be inherited by children.

The built in styles are global lv_style_t variables. You can use them like:

lv_btn_set_style(obj, LV_BTN_STYLE_REL, &lv_style_btn_rel)

Create new styles

You can either modify the built-in styles or can create new styles.

When creating new styles, it’s recommended to first copy a built-in style with lv_style_copy(&dest_style, &src_style) to be sure all fields are initialized with the proper value.

Do not forget to initialize the new style as static or global. For example:

static lv_style_t my_red_style;
lv_style_copy(&my_red_style, &lv_style_plain);
my_red_style.body.main_color = LV_COLOR_RED;
my_red_style.body.grad_color = LV_COLOR_RED;

Style animations

You can change the styles with animations using lv_style_anim_...() function. The lv_style_anim_set_styles() uses 3 styles. Two styles are required to represent the start and end state, and a third style required for the animation.

Here is an example to show how it works.

lv_anim_t a;
lv_style_anim_init(&a);                                                 /*A basic initialization*/
lv_style_anim_set_styles(&a, &style_to_anim, &style_start, &style_end); /*Set the styles to use*/
lv_style_anim_set_time(&a, duration, delay);                           /*Set the duration and delay*/
lv_style_anim_create(&a);                                               /*Create the animation*/

Essentially, style_start and style_end remain unchanged, and style_to_anim is interpolated over the course of the animation.

See lv_core/lv_style.h to know the whole API of style animations.

Check Animations for more information.

Style example

The example below demonstrates the usage of styles.

Styles usage example in LittlevGL Embedded Graphics Library

/*Create a style*/
static lv_style_t style1;
lv_style_copy(&style1, &lv_style_plain);    /*Copy a built-in style to initialize the new style*/
style1.body.main_color = LV_COLOR_WHITE;
style1.body.grad_color = LV_COLOR_BLUE;
style1.body.radius = 10;
style1.body.border.color = LV_COLOR_GRAY;
style1.body.border.width = 2;
style1.body.border.opa = LV_OPA_50;
style1.body.padding.left = 5;            /*Horizontal padding, used by the bar indicator below*/
style1.body.padding.right = 5;
style1.body.padding.top = 5;            /*Vertical padding, used by the bar indicator below*/
style1.body.padding.bottom = 5;
style1.text.color = LV_COLOR_RED;

/*Create a simple object*/
lv_obj_t *obj1 = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_style(obj1, &style1);                        /*Apply the created style*/
lv_obj_set_pos(obj1, 20, 20);                           /*Set the position*/

/*Create a label on the object. The label's style is NULL by default*/
lv_obj_t *label = lv_label_create(obj1, NULL);
lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, 0);       /*Align the label to the middle*/

/*Create a bar*/
lv_obj_t *bar1 = lv_bar_create(lv_scr_act(), NULL);
lv_bar_set_style(bar1, LV_BAR_STYLE_INDIC, &style1);    /*Modify the indicator's style*/
lv_bar_set_value(bar1, 70);                             /*Set the bar's value*/

Themes

Creating styles for the GUI is challenging because you need a deeper understanding of the library, and you need to have some design skills. Also, it takes a lot of time to create so many styles for many different objects.

Themes are introduced to speed up the design part. A theme is a style collection which contains the required styles for every object type. For example, 5 styles for a button to describe its 5 possible states. Check the Existing themes or try some in the Live demo section. The theme selector demo is useful to see how a given theme and color hue looks on the display.

To be more specific, a theme is a structure variable that contains a lot of lv_style_t * fields. For buttons:

theme.btn.rel       /*Released button style*/
theme.btn.pr        /*Pressed button style*/
theme.btn.tgl_rel   /*Toggled released button style*/
theme.btn.tgl_pr    /*Toggled pressed button style*/
theme.btn.ina       /*Inactive button style*/

A theme can initialized by: lv_theme_<name>_init(hue, font). Where hue is a Hue value from HSV color space (0..360) and font is the font applied in the theme (NULL to use the LV_FONT_DEFAULT)

When a theme is initialized its styles can be used like this:

Theme usage example in Littlev Embedded Graphics Library

/*Create a default slider*/
lv_obj_t *slider = lv_slider_create(lv_scr_act(), NULL);
lv_slider_set_value(slider, 70);
lv_obj_set_pos(slider, 10, 10);

/*Initialize the alien theme with a reddish hue*/
lv_theme_t *th = lv_theme_alien_init(10, NULL);

/*Create a new slider and apply the themes styles*/
slider = lv_slider_create(lv_scr_act(), NULL);
lv_slider_set_value(slider, 70);
lv_obj_set_pos(slider, 10, 50);
lv_slider_set_style(slider, LV_SLIDER_STYLE_BG, th->slider.bg);
lv_slider_set_style(slider, LV_SLIDER_STYLE_INDIC, th->slider.indic);
lv_slider_set_style(slider, LV_SLIDER_STYLE_KNOB, th->slider.knob);

You can ask the library to automatically apply the styles from a theme when you create new objects. To do this use lv_theme_set_current(th).

/*Initialize the alien theme with a reddish hue*/
lv_theme_t *th = lv_theme_alien_init(10, NULL);
lv_theme_set_current(th);

/*Create a slider. It will use the style from teh current theme.*/
slider = lv_slider_create(lv_scr_act(), NULL);

Themes can be enabled or disabled one by one in lv_conf.h.

Live update

By default, if lv_theme_set_current(th) is called again, it won’t refresh the styles of the existing objects. To enable live update of themes, enable LV_THEME_LIVE_UPDATE in lv_conf.h.

Live update will only update objects using the unchanged theme styles, i.e. objects created after the first call of lv_theme_set_current(th) or to which the theme’s styles were applied manually.