2-7-1+2_基础对象的样式(styles)
2-7-1+2_基础对象的样式(styles)
知识部分
Styles(风格样式)
Opacity, Blend modes and Transformations(不透明度,混合模式和变换) Cascading styles(层叠样式)
Inheritance(继承) Properties(属性)
Typical background properties(典型的背景属性) Transitions(过渡特效)
Themes (主题)
实践部分
States(状态) Parts(部分)
组合:部分和状态组合
Initialize styles and set/get properties(初始化样式和设置/获取属性) Add and remove styles to a widget(向控件添加和删除样式)
Add styles(添加样式) Replace styles(替换样式) Remove styles(删除样式)
Report style changes(通知样式更改)
Get a property's value on an object(获取对象的属性值) Local styles(本地样式)
知识部分
https://lvgl.100ask.net/9.1/overview/style.html文档位置

显示原文
"Styles" 用于设置对象的外观。lvgl 中的样式在很大程度上受到CSS的启发。简而言之,其概念如下:
样式是一个 lv_style_t 类型的变量,它可以保存诸如边框宽度、文字颜色等属性。类似于CSS中的 class 。
样式可以分配给对象以改变它们的外观。在分配时,可以指定目标部分(CSS中的伪元素)和目标状态(伪类)。例如,当滑块处于按下状态时,可以将 [ ] (https://lvgl.100ask.net/9.2/overview/style.html#id2)style_blue 样式添加到滑块的旋钮上。
同样的样式可以被任意数量的对象使用。
样式可以进行层叠,这意味着可以将多个样式分配给一个对象,每个样式可以具有不同的属性。因此,并非所有的属性都必须在一个样式中指定。 LVGL将在样式中搜索属性,直到找到定义该属性的样式,或者如果没有任何样式指定,则使用默认值。 例如, style_btn 可以生成默认的灰色按钮,而 style_btn_red 可以仅添加 background-color=red 覆盖背景颜色。
最近添加的样式具有更高的优先级。这意味着,如果一个属性在两个样式中都指定了,对象中最新的样式将被使用。
一些属性(例如文本颜色)如果在对象中未指定,则可以从父对象继承。对象也可以具有局部样式,其优先级高于 “普通” 样式。
与CSS不同(在CSS中,伪类描述不同的状态,例如 :focus ),在LVGL中,属性分配给了给定的状态。
当对象更改状态时,可以应用过渡效果。
Opacity, Blend modes and Transformations(不透明度,混合模式和变换)
OPA = Opacity(不透明度/透明度)
LV_OPA_COVER 表示完全不透明(opacity = 255,完全覆盖)其他常见值:
LV_OPA_TRANSP = 完全透明
LV_OPA_10 = 10% 不透明度
LV_OPA_50 = 50% 不透明度
如果 opa 、 blend_mode 、 transform_angle 或 transform_zoom 属性被设置为它们的非默认值,LVGL将为控件及其所有子级创建一个快照,以便将整个控件与设置的不透明度、混合模式和变换属性混合在一起。
显示原文
这些属性仅在控件的 MAIN 部分上产生作用。
创建的快照称为“中间层”或简称为“层”。如果只有 opa 和/或 blend_mode 设置为非默认值,LVGL可以从较小的块构建图层。这些块的大小可以通过 lv_conf.h 中的以下属性配置:
LV_LAYER_SIMPLE_BUF_SIZE : [字节] 的理想目标缓冲区大小。LVGL将尝试分配此内存大小。
LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE : [字节] 如果无法分配
LV_LAYER_SIMPLE_BUF_SIZE ,则使用该大小。
如果还使用了变换属性,则图层无法以块的形式渲染,而需要分配更大的内存。所需的内存取决于角度、缩放和枢轴参数以及要重绘的区域大小,但永远不会大于控件的大小(包括用于阴影、轮廓等的额外绘制大小)。
如果控件可以完全覆盖要重绘的区域,LVGL将创建一个RGB图层(渲染速度更快,占用的内存更少)。如果相反情况需要使用ARGB渲染。如果控件具有半径、 bg_opa != 255 、有阴影、轮廓等,则控件可能无法覆盖其区域。
控件的点击区域也会相应地进行变换。
显示原文
在一个样式中并不需要设置所有的属性。可以给一个对象添加更多的样式,并且后添加的样式可以修改或扩展外观。例如,创建一个通用的灰色按钮样式,然后为红色按钮创建一个新样式,在新样式中只设置新的背景颜色。
这就像在CSS中使用类列表一样,比如 <div class=".btn .btn-red"> 。
后添加的样式具有优先权,优先于先前设置的样式。因此,在上述灰色/红色按钮的例子
中,应该先添加普通按钮样式,然后再添加红色样式。但是,状态的优先级仍然会被考虑。因此,让我们来看一个例子:
基本按钮样式为默认状态设置了暗灰色的颜色,为按下状态设置了浅灰色的颜色
红色按钮样式只在默认状态下将背景颜色设置为红色
在这种情况下,当按钮释放(处于默认状态)时,它将是红色的,因为最近添加的样式(红色样式)完全匹配。当按钮被按下时,浅灰色的颜色更匹配,因为它完美描述了当前的状 态,所以按钮会是浅灰色的。
显示原文
一些属性(通常与文本相关的属性)可以从父对象的样式中继承。 只有在对象的样式中没有设置给定属性时(即使是默认状态下也是如此),继承才会应用。 在这种情况下,如果属性是可继承的,属性值将在父对象中搜索,直到某个对象为属性指定一个值。 父对象将使用自己的状态来确定值。因此,如果按钮被按下,并且文本颜色来自于这里,那么按下时文本颜色将会被使用。
显示原文
点击这里获取完整的样式属性列表 here。
Typical background properties(典型的背景属性)
显示原文
在控件的文档中,您会看到类似于“该控件使用典型的背景属性”的句子。这些“典型的背景属性”包括:
背景
边框
轮廓
阴影
填充
宽度和高度转换
X 和 Y 的平移
Transitions(过渡特效)
默认情况下,当对象改变状态(例如,被按下)时,新状态的新属性立即设置。然而,使用过渡效果可以在状态改变时播放动画。 例如,按下按钮时,它的背景颜色可以在 300 毫秒内动画过渡到按下状态的颜色。
过渡效果的参数存储在样式中。可以设置:
过渡时间
开始过渡前的延迟
动画路径(也称为定时或缓动函数)
要进行动画处理的属性
过渡属性可以为每个状态定义。例如,在默认状态下设置500毫秒的过渡时间意味着当对象进入默认状态时,将应用500毫秒的过渡时间。 在按下状态下设置100毫秒的过渡时间,则在进入按下状态时会有100毫秒的过渡。这个例子的配置意味着迅速进入按下状态,然后慢慢返回默认状态。
为了描述一个过渡,需要初始化一个 lv_transition_dsc_t 变量,并将其添加到一个样式中:
/*Only its pointer is saved so must static, global or dynamically allocated */
static const lv_style_prop_t trans_props[] =
{
LV_STYLE_BG_OPA,
LV_STYLE_BG_COLOR,
0, /*End marker*/
};
static lv_style_transition_dsc_t trans1; lv_style_transition_dsc_init(&trans1, trans_props, lv_anim_path_ease_out, duration_ms, delay_ms);
lv_style_set_transition(&style1, &trans1);
demo体验: https://docs.lvgl.io/9.1/overview/style.html#transition
http://lvgl.100ask.net/9.1/overview/style.html#transition
Themes (主题)
显示原文
主题是一系列的样式。如果有一个活动主题,LVGL会应用它到每个创建控件上。这将为UI提供一个默认的外观,可以通过添加更多样式来进行修改。
每个显示器可以有不同的主题。例如,你可以在TFT上有一个多彩的主题,在第二个单色显示器上有一个单色的主题。
要为显示器设置一个主题,需要两个步骤:
- 初始化一个主题
- 将初始化的主题分配给一个显示器。
主题初始化函数可以有不同的原型。下面的例子显示了如何设置“默认”主题:
lv_theme_t * th = lv_theme_default_init(display, /*使用该显示器的 DPI、大小等*/
LV_COLOR_PALETTE_BLUE,
LV_COLOR_PALETTE_CYAN, /*主色和辅助色板*/
false, /*亮或暗模式*/ &lv_font_montserrat_10,&lv_font_montserrat_14, &lv_font_montserrat_18); /*小、正常、大字体*/
lv_display_set_theme(display, th); /*将主题分配给显示器*/
包含的主题在 lv_conf.h 中已启用。如果默认主题由 LV_USE_THEME_DEFAULT 启用,
LVGL在创建显示器时会自动初始化和设置它。 demo体验:
https://docs.lvgl.io/9.1/overview/style.html#extending-the-current-theme http://lvgl.100ask.net/9.1/overview/style.html#extending-the-current-theme
实践部分
显示原文
对象可以处于以下状态的组合中:
LV_STATE_DEFAULT :(0x0000) 正常、释放的状态
LV_STATE_CHECKED :(0x0001) 切换或选中的状态
LV_STATE_FOCUSED :(0x0002) 通过键盘或编码器聚焦,或通过触摸板/鼠标点击
LV_STATE_FOCUS_KEY :(0x0004) 仅通过键盘或编码器聚焦,而非通过触摸板/鼠标
LV_STATE_EDITED :(0x0008) 由编码器编辑
LV_STATE_HOVERED :(0x0010) 鼠标悬停
LV_STATE_PRESSED :(0x0020) 被按下的状态 LV_STATE_SCROLLED :(0x0040) 正在滚动的状态 LV_STATE_DISABLED :(0x0080) 禁用的状态
LV_STATE_USER_1 :(0x1000) 自定义状态 LV_STATE_USER_2 :(0x2000) 自定义状态 LV_STATE_USER_3 :(0x4000) 自定义状态 LV_STATE_USER_4 :(0x8000) 自定义状态
对象可以处于多个状态的组合中,例如同时处于聚焦和按下状态。这被表示为
LV_STATE_FOCUSED | LV_STATE_PRESSED。
样式可以应用于任何状态或状态组合。例如,为默认和按下状态设置不同的背景颜色。 如果某个状态中未定义属性,则会使用与之最匹配的状态的属性。通常情况下,这意味着将使用带有 LV_STATE_DEFAULT 的属性。 如果即使对于默认状态,某个属性也未设置,则将使用默认值。(稍后会详细说明)
但是,“与之最匹配的状态的属性”到底是什么意思呢?状态有一个优先级,由它们的值表示
(请参见上面的列表)。值越高,优先级越高。 为了确定使用哪个状态的属性,我们来看一个例子。假设背景颜色定义如下:
LV_STATE_DEFAULT :白色
LV_STATE_PRESSED :灰色
LV_STATE_FOCUSED :红色
- 初始情况下,对象处于默认状态,所以情况很简单:属性在对象当前状态中完全定义为白色。
- 当对象被按下时,有两个相关属性:白色的默认属性(默认与每个状态相关)和灰色的按下属性。按下状态的优先级为0x0020,高于默认状态的优先级0x0000,因此会使用灰色。
- 当对象处于聚焦状态时,与按下状态发生的情况相同,将使用红色。(聚焦状态的优先级高于默认状态)
- 当对象处于聚焦和按下状态时,灰色和红色都可以。但是按下状态的优先级高于聚焦状态,因此会使用灰色。
- 可以为 LV_STATE_PRESSED | LV_STATE_FOCUSED 设置玫瑰色,此组合状态的优先级为0x0020 + 0x0002 = 0x0022,高于按下状态的优先级,因此将使用玫瑰色。
- 当对象处于选中状态时,没有属性来设置此状态的背景颜色。由于缺乏更好的选择,对象仍然保持默认状态的白色属性。
一些实用的注意事项:
状态的优先级(值)非常直观,这是用户自然期望的结果。例如,如果对象处于聚焦状态,用户仍然希望看到它是否被按下,因此按下状态具有更高的优先级。如果聚焦状态具有更高的优先级,它将覆盖按下的颜色。
如果要为所有状态(例如红色背景颜色)设置属性,只需为默认状态设置即可。如果对象在其当前状态下找不到属性,它将退回到默认状态的属性。
使用 OR 运算符来描述复杂情况下的属性(例如,按下 + 选中 + 聚焦)。
对于不同的状态,使用不同的样式元素可能是个好主意。例如,为释放、按下、选中 + 按下、聚焦、聚焦 + 按下、聚焦 + 按下 + 选中等状态找到背景颜色是相当困难的。相反,例如,使用按下和选中状态的背景颜色,并使用不同的边框颜色指示聚焦状态。
lv_style_init(&style_indicator); lv_style_set_bg_opa(&style_indicator, LV_OPA_COVER); lv_style_set_bg_color(&style_indicator,
lv_palette_main(LV_PALETTE_RED/*LV_PALETTE_CYAN*/));
lv_style_set_radius(&style_indicator, LV_RADIUS_CIRCLE);
lv_style_set_transition(&style_indicator,&transition_dsc);
/* LV_STATE_PRESSED按下操作*/ lv_obj_add_style(slider, &style_indicator,
LV_STATE_PRESSED);

显示原文
物体可以由具有自己样式的“部分”组成。在LVGL中,存在以下预定义部分:
LV_PART_MAIN :像矩形一样的背景
LV_PART_SCROLLBAR :滚动条(们)
LV_PART_INDICATOR :指示器,例如用于滑块、条形图、开关或复选框的勾选框
LV_PART_KNOB :像把手一样用来调节值
LV_PART_SELECTED :表示当前选择的选项或部分
LV_PART_ITEMS :如果控件具有多个类似元素(例如表格单元格)时使用
LV_PART_CURSOR :标记特定位置,例如文本区域或图表的光标
LV_PART_CUSTOM_FIRST :可以从这里开始添加自定义部分标识符。例如,一个 滑动条 具有三个部分:
背景
指示器
把手
这意味着滑动条的这三个部分都可以有自己的样式。稍后我们将看到如何向对象和部分添加样式。
根据2.7.1的代码
lv_style_init(&style_indicator);
lv_style_set_bg_opa(&style_indicator, LV_OPA_COVER);
lv_style_set_bg_color(&style_indicator,
lv_palette_main(LV_PALETTE_RED/*LV_PALETTE_CYAN*/));
lv_style_set_radius(&style_indicator, LV_RADIUS_CIRCLE);
lv_style_set_transition(&style_indicator,&transition_dsc);
/* LV_PART_INDICATOR设置类似*/
lv_obj_add_style(slider, &style_indicator,
LV_PART_INDICATOR);

组合:部分和状态组合
Part(部件)和 State(状态)的组合。
LV_PART_INDICATOR | LV_STATE_PRESSED
这是 位掩码(bitmask) 的组合方式。| 是按位或运算符,用来同时指定:
哪个部件(Part)
什么状态(State)
lv_style_init(&style_pressed_color); lv_style_set_bg_color(&style_pressed_color, lv_palette_darken(LV_PALETTE_CYAN, 2));
lv_obj_add_style(slider, &style_pressed_color, LV_PART_INDICATOR | LV_STATE_PRESSED); // 当指针部分被按下的时候,指针部分应用该样式
按位或既可以保证状态又可以保证部分
上图就是示例代码运行的结果就是我按下时且我的部分(这里为指示器

[LV_PART_INDICATOR])都为青色。
Initialize styles and set/get properties(初始化样式和设置/获取属性)
样式存储在 lv_style_t 类型的变量中。样式变量应该是静态的、全局的或者动态分配的。 换句话说,它们不能是函数内部的局部变量,在函数结束时会被销毁。 在使用样式之前,应该使用 lv_style_init(&my_style) 进行初始化。样式初始化后,可以添加或更改属性。
属性设置函数的格式如下: lv_style_set_<property_name>(&style, )。例如:
要删除一个属性,可以使用:
static lv_style_t style_btn; lv_style_init(&style_btn);
lv_style_set_bg_color(&style_btn, lv_color_hex(0x115588));//设置背景颜色
lv_style_set_bg_opa(&style_btn, LV_OPA_50);//设置不透明度
lv_style_set_border_width(&style_btn, 2);//设置
lv_style_set_border_color(&style_btn, lv_color_black());
static lv_style_t style_btn_red; lv_style_init(&style_btn_red);
lv_style_set_bg_color(&style_btn_red, lv_palette_main (LV_PALETTE_RED));
lv_style_set_bg_opa(&style_btn_red, LV_OPA_COVER);
lv_style_remove_prop(&style, LV_STYLE_BG_COLOR);
从样式中获取属性的值:
lv_style_value_t v;
lv_res_t res = lv_style_get_prop(&style, LV_STYLE_BG_COLOR, &v);
if(res == LV_RES_OK) { /*找到了*/
do_something(v.color);
}
lv_style_value_t 包含 3 个字段:
num:用于整数、布尔值和不透明度属性 color:用于颜色属性 ptr:用于指针属性
要重置一个样式(释放其所有数据),可以使用:
lv_style_reset(&style);
样式也可以定义为 const,以节省 RAM:
以后可以像其他样式一样使用 const 样式,但显然不能添加新属性。
const lv_style_const_prop_t style1_props[] = { LV_STYLE_CONST_WIDTH(50), LV_STYLE_CONST_HEIGHT(50), LV_STYLE_CONST_PROPS_END};
LV_STYLE_CONST_INIT(style1, style1_props);
Add and remove styles to a widget(向控件添加和删除样式)
显示原文
一个单独的样式并不是特别有用,必须将其分配给一个对象才能生效。
Add styles(添加样式)
显示原文
为了给对象添加样式,请使用 lv_obj_add_style(obj, &style, <selector>) 。 <selector> 是一个按位或运算的值,用于指定要添加样式的部分和状态。下面是一些示例:
LV_PART_MAIN | LV_STATE_DEFAULT
LV_STATE_PRESSED :按下状态下的主要部分。可以省略 LV_PART_MAIN 。
LV_PART_SCROLLBAR :默认状态下的滚动条部分。可以省略 LV_STATE_DEFAULT 。
LV_PART_SCROLLBAR | LV_STATE_SCROLLED:当对象被滚动时的滚动条部分。
LV_PART_INDICATOR | LV_STATE_PRESSED | LV_STATE_CHECKED:对象被按下和选中时的指示器部分。
使用 lv_obj_add_style() :
lv_obj_add_style(btn, &style_btn, 0); lv_obj_add_style(btn, &btn_red, LV_STATE_PRESSED);
改为红色*/
/*默认按钮样式*/
/*仅在按下时将部分颜色更
Replace styles(替换样式)
显示原文
使用下列语句来替换对象的特定样式:lv_obj_replace_style(obj, old_style, new_style, selector)。 此函数仅在 selector 匹配 lv_obj_add_style 中使用的 selector 时,才会将 old_style 替换为 new_style 。 两种样式,即 old_style 和 new_style 都不能为 NULL (添加和删除分别存在不同的函数)。 如果 obj 的样式中存在多个 old_style 和 selector 的组合,所有出现的情况都将被替换。函数的返回值指示是否至少进行了一次成功替换。
lv_obj_add_style(btn, &style_btn, 0); /* 添加按钮样式 */ lv_obj_replace_style(btn, &style_btn, &new_style_btn, 0); /* 用不同的样式替换按钮样式 */
Remove styles(删除样式)
显示原文
从对象中删除所有样式,请使用 lv_obj_remove_style_all(obj)。
要删除特定的样式,请使用 lv_obj_remove_style(obj, style, selector)。 此函数将仅在 selector 与
lv_obj_add_style() 中使用的 selector 匹配时删除 style 。 style 可以是 NULL ,以仅检查 selector 并删除所有匹配的样式。 selector 可以使用 LV_STATE_ANY 和 LV_PART_ANY 值,从任何状态或部件中删除样式。
Report style changes(通知样式更改)
显示原文
如果已经分配给一个对象的样式发生改变(例如添加或更改属性),那么使用该样式的对象应该收到通知。有三种选项可以做到这一点:
- 如果你知道改变的属性可以通过简单的重绘来应用(例如颜色或不透明度的变化),只需调用: lv_obj_invalidate(obj) 或者 lv_obj_invalidate(lv_screen_active())。
- 如果更改或添加了更复杂的样式属性,并且你知道哪些对象受到该样式的影响,请调用: lv_obj_refresh_style(obj, part, property)。要刷新所有部件和属性,请使用: lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY)。
- 要让LVGL检查所有对象以查看它们是否使用了样式,并在需要时刷新它们,请调用:
lv_obj_report_style_change(&style)。如果 style 是 NULL,则所有对象将收到有关样式更改的通知。
Get a property's value on an object(获取对象的属性值)
显示原文
获取物体的最终属性值
考虑层叠、继承、本地样式和过渡效果(见下文)
可以使用此类属性获取函数: lv_obj_get_style_<property_name>(obj, <part>) 。 这些函数使用物体的当前状态,如果没有更好的候选项,则返回默认值。 例如:
lv_color_t color = lv_obj_get_style_bg_color(btn, LV_PART_MAIN);
显示原文
除了“普通”样式外,对象还可以存储本地样式。 这个概念类似于CSS中的内联样式(例如 <div style="color:red"> ),但有一些修改。
函数对比一般加obj即为本地样式
/*本地样式*/
lv_obj_set_style_bg_color(slider, lv_color_red(), LV_PART_INDICATOR | LV_STATE_FOCUSED);
/*普通样式*/
lv_style_set_bg_color(&style_btn, lv_color_hex(0x115588));
本地样式与普通样式类似,但不能在其他对象之间共享。如果使用,本地样式会自动分配,并且在对象被删除时释放。它们很适合为对象添加本地定制。
与CSS不同,LVGL中的本地样式可以分配给状态( 伪类)和部分( 伪元素)。
要设置本地属性,请使用如下函数: lv_obj_set_style_<property_name>(obj, <value>,
<selector>); 例如:
lv_obj_set_style_bg_color(slider, lv_color_red(), LV_PART_INDICATOR | LV_STATE_FOCUSED);

浙公网安备 33010602011771号