目录

02_LVGL学习笔记深理解样式Style机制与应用方法

02_LVGL学习笔记:深理解样式(Style)机制与应用方法

样式

LVGL 中, 样式(Style) 是用来控制对象(控件)外观的核心机制,涵盖了 颜色、边框、背景、文字、阴影、渐变、圆角 等视觉特性。通过样式,你可以轻松地为不同状态(如正常、按下、禁用等)指定不同的外观效果。

1. 样式的基本概念

1.1 样式对象(lv_style_t)

  • 样式对象中包含若干可配置的视觉属性,例如 背景色边框宽度文字颜色阴影圆角 等。
  • 每个属性都可以通过相关的 API(如 lv_style_set_bg_color()lv_style_set_border_width() )来设置。

1.2 属性类型

  • 背景(background) :如背景颜色、背景透明度、背景渐变等。
  • 边框(border) :如边框颜色、边框宽度、边框圆角等。
  • 文本(text) :如字体、文字颜色、文字对齐方式等。
  • 阴影(shadow) :如阴影偏移、阴影颜色、阴影宽度等。
  • 布局(layout) :如内边距(padding)、外边距(margin)等(主要用于布局系统)。
  • 轮廓(outline) :与边框类似,但通常用于获得“聚焦”效果。
  • 其他 :如图像(image)、透明度(opa)、转换(transform)等高级属性。

1.3 状态(lv_state_t)

  • LVGL 中,每个对象可能处于不同的状态( 状态可以组合 ),如 正常(LV_STATE_DEFAULT)按下(LV_STATE_PRESSED)禁用(LV_STATE_DISABLED)聚焦(LV_STATE_FOCUSED) 等。
  • 同一个对象可以在不同状态下应用不同的样式,例如按钮在按下时改变背景色。

1.4 优先级和叠加

  • 对象可以同时应用多个样式,这些样式将“叠加”到一起,后添加的样式优先级更高。
  • 样式属性可以相互覆盖,例如后添加的样式如果设置了 bg_color ,则会覆盖先前样式的 bg_color

2. 样式的创建与使用

2.1 创建样式

​ 样式存储在 lv_style_t 变量中。LVGL 的样式系统采用了动态分配与静态分配相结合的方式,目的是尽可能地节省内存。

static lv_style_t style_btn_default;
lv_style_init(&style_btn_default); // 初始化样式,确保处于一个已知的、干净的初始状态
lv_style_set_bg_color(&style_btn_default, lv_color_hex(0x000000));

只存储实际设置的属性

样式(lv_style_t)不会为所有可能的视觉属性预留固定空间,而是仅在需要时,通过动态分配(或扩展已有内存)来存储实际设置的属性值。这避免了为未使用的属性浪费内存。

2.2 给对象添加样式

完成样式初始化后,你可以通过以下方式为对象应用样式:

lv_obj_t *btn = lv_btn_create(lv_scr_act()); // 创建一个按钮对象            
lv_obj_add_style(btn, &style_btn_default, LV_STATE_DEFAULT);  // 应用于默认状态
  • 第三个参数表示应用到哪种状态或场景。传 0 表示应用到 LV_STATE_DEFAULT (即正常、释放的状态)。

2.3 设置不同状态下的样式

如果你想在 按钮按下(PRESSED) 时使用不同的颜色,可以再次创建一个样式用于按下状态:

static lv_style_t style_btn_pressed;
lv_style_set_bg_color(&style_btn, lv_color_hex(0x007ACC));    // 改变背景色
lv_obj_add_style(btn, &style_btn_pressed, LV_STATE_PRESSED);  // 应用于按下状态

这样,当按钮处于按下状态时,就会显示新的背景色。

2.4 样式的内存分配

假设你要创建一个按钮样式,只改变背景颜色和圆角属性。初始时,你可能这样写

static lv_style_t style_btn;
lv_style_init(&style_btn);  // 初始化样式

// 设置背景颜色为红色
lv_style_set_bg_color(&style_btn, lv_color_hex(0xFF0000));

// 设置圆角半径为 5 像素
lv_style_set_radius(&style_btn, 5);

实际情况:

  1. 初始状态

    当调用 lv_style_init(&style_btn) 时, style_btn.values_and_props 可能为空或分配了一个很小的内存块,因为还没有任何属性被设置。

  2. 设置背景颜色

    当你调用 lv_style_set_bg_color(&style_btn, lv_color_hex(0xFF0000)); 时,内部会检查这个样式是否已经为背景颜色属性分配了内存。如果没有,它就会分配一个足够存储“背景颜色”这一属性的数据块,然后把属性 ID 和对应的值(红色)存储进去。

  3. 设置圆角

    接下来,调用 lv_style_set_radius(&style_btn, 5); 会让系统检查 style_btn.values_and_props 是否有足够空间存储另一个属性(圆角)。如果空间不够,系统会动态扩展该内存块,把新的属性和值也存储进去。

这样, 只为你真正设置的属性分配内存 ,而不是预先为所有可能属性保留大量空间。最终, lv_style_t 只占用较小内存,同时能够高效地存储你实际用到的样式属性。这就是 LVGL 为了节省内存而采用动态分配和按需扩展的设计理念。

3. 普通样式和本地样式

3.1 普通样式(共享/常量样式)

​ 普通样式通常是以全局定义的方式存在,常见于主题或默认样式中。这类样式在编译时就已经确定好,并且被多个对象共享,内存开销小,因为它们是只读的。

示例:

static lv_style_t style_btn_default;
lv_style_init(&style_btn_default); // 初始化
lv_style_set_bg_color(&style_btn_default, lv_color_hex(0x000000));
lv_style_set_border_width(&style_btn_default, 2);

3.2 本地样式(Local styles)

​ 当你需要对单个对象进行定制化修改,而不希望影响到其他使用相同普通样式的对象时,LVGL 会为该对象创建一个本地样式副本。

  • 修改本地样式不会改变原始的普通样式,因此只会影响当前对象,从而实现个性化的外观设置。
lv_obj_t * btn_local = lv_btn_create(lv_scr_act());
lv_obj_set_style_bg_color(btn_local, lv_color_hex(0xFF5722), LV_PART_MAIN);
lv_obj_set_style_radius(btn_local, 8, LV_PART_MAIN);