解码LVGL样式

news/2025/11/2 17:50:02/文章来源:https://www.cnblogs.com/YouEmbedded/p/19185183

LVGL 样式系统:核心组成与特性

样式是控制控件外观(颜色、圆角、字体等)的核心机制,其设计围绕 “部件针对性控制”“状态动态切换” 和 “高效复用管理” 三大原则展开。

样式核心组成

样式部件(Part):控件的 “组成单元”

控件由多个功能独立的 “部件” 构成,样式可精准作用于某个部件(而非整个控件),实现精细化外观控制。核心部件如下:

部件宏 作用场景
LV_PART_MAIN 控件主体(如按钮的背景区域、输入框的文本容器,是最常用的部件)
LV_PART_SCROLLBAR 滚动条(如列表、文本框的滚动条,控制滚动条的颜色、宽度)
LV_PART_INDICATOR 指示器(如滑动条的进度条、复选框的勾选框,控制进度 / 选中状态的外观)
LV_PART_KNOB 旋钮(如滑动条的拖动块、圆弧控件的拖动点,控制可交互部件的外观)
LV_PART_SELECTED 选中项(如列表的选中行、下拉框的选中选项,控制选中状态的颜色、背景)
LV_PART_TICKS 刻度(如滑块、仪表盘的刻度线,控制刻度的颜色、长度)
LV_PART_CURSOR 光标(如输入框的文本光标,控制光标的颜色、宽度)
LV_PART_ANY 作用于控件的所有部件(如修改按钮的所有组成部分,无需分别指定部件)

样式状态(State):控件的 “动态状态”

控件在交互过程中会处于不同状态(如按下、禁用),样式可针对特定状态定义外观,实现状态变化时的自动切换。核心状态如下:

状态宏 触发场景
LV_STATE_DEFAULT 默认状态(无任何操作,控件正常显示)
LV_STATE_PRESSED 按下状态(鼠标 / 触摸按下控件,适用于按钮、滑动条等可交互控件)
LV_STATE_FOCUSED 聚焦状态(输入框被点击、键盘 Tab 切换到控件,适用于需要输入的控件)
LV_STATE_FOCUS_KEY 键盘聚焦状态(仅通过键盘 Tab 键聚焦,区别于鼠标 / 触摸聚焦)
LV_STATE_HOVERED 悬停状态(鼠标放在控件上,触摸设备无此状态,适用于 PC 端模拟器)
LV_STATE_DISABLED 禁用状态(控件不可操作,需通过lv_obj_add_flag(obj, LV_OBJ_FLAG_DISABLED)启用)
LV_STATE_CHECKED 勾选状态(复选框、单选按钮被选中,控制选中后的外观)
LV_STATE_SCROLLED 滚动状态(控件处于滚动中,如列表滚动时的背景色变化)
LV_STATE_ANY 作用于控件的所有状态(如修改按钮在默认、按下、聚焦等所有状态下的文本颜色)

样式系统核心特性

  • 样式复用:通过lv_style_t定义的通用样式,可通过lv_obj_add_style绑定到多个对象(如 “红色按钮样式” 应用到所有确认按钮),修改样式时所有关联对象同步更新,大幅减少重复代码。
  • 样式级联与优先级:一个对象可绑定多个样式,优先级遵循 “状态匹配度>样式类型>添加顺序”:
    • 精准匹配当前状态的样式(如LV_STATE_PRESSED)>通用状态样式(LV_STATE_ANY);
    • 本地样式(lv_obj_set_style_xxx直接设置)>通用样式(lv_style_t定义);
    • 同状态、同类型的样式,后添加的覆盖先添加的。
  • 有限属性传递:无传统意义的 “全量样式继承”,仅部分与排版 / 文本相关的关键属性会默认复用(如父容器的text_font被子标签复用),且子对象设置自己的样式后立即覆盖。
  • 过渡动画支持:通过lv_style_transition_dsc_t配置过渡规则(如背景色、边框宽度的动画参数),使样式属性在状态切换时平滑变化(如按钮按下时的颜色渐变),提升交互体验。
  • 主题统一管理:内置默认主题(如lv_theme_default),也可自定义主题作为全局基础样式,统一所有控件的默认外观(如全局字体、圆角风格),主题优先级低于对象自定义样式。

通过lv_obj_set_style_xxx()接口直接给单个对象设置本地样式属性(如背景色、文本字体),无需先定义通用样式对象(lv_style_t),接口格式统一为lv_obj_set_style_属性名(对象指针, 值, 样式选择器),核心用于精准控制单个对象的特定状态 / 部件样式;完整接口见lv_obj_style_gen.h
常用本地样式函数:

/*** 设置对象的宽度样式(控制边界宽度)* @param obj       目标对象指针(lv_obj_t*,不可为NULL)* @param value     宽度值(int32_t),单位为像素;LV_SIZE_CONTENT表示自适应内容* @param selector  样式选择器(lv_style_selector_t),格式为「部件 | 状态」,如LV_PART_MAIN | LV_STATE_DEFAULT*                  - 部件:指定作用的对象部件(如LV_PART_MAIN主部件、LV_PART_INDICATOR指示器)*                  - 状态:指定生效的对象状态(如LV_STATE_PRESSED按下、LV_STATE_DISABLED禁用)* @note            若同时设置min_width和max_width,实际宽度会被限制在[min, max]范围内;*                  与lv_obj_set_size()的区别:此函数通过样式控制,受状态影响;后者直接设置固定尺寸,不受样式状态影响*/
void lv_obj_set_style_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);/*** 设置对象的背景颜色* @param obj       目标对象指针(lv_obj_t*,不可为NULL)* @param value     背景颜色(lv_color_t),可通过lv_color_hex(0xRRGGBB)、lv_color_rgb(r,g,b)生成* @param selector  样式选择器(lv_style_selector_t),格式为「部件 | 状态」(如LV_PART_MAIN | LV_STATE_PRESSED)* @note            背景透明度需通过lv_obj_set_style_bg_opa()单独设置(默认完全透明);*                  若设置了背景渐变(lv_obj_set_style_bg_grad_color()),会覆盖纯色背景;*                  对无背景的部件(如某些控件的指示器)可能不生效,需确认目标部件是否支持背景属性*/
void lv_obj_set_style_bg_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);/*** 设置对象的边框宽度* @param obj       目标对象指针(lv_obj_t*,不可为NULL)* @param value     边框宽度(int32_t),单位为像素;0表示隐藏边框* @param selector  样式选择器(lv_style_selector_t),格式为「部件 | 状态」* @note            边框颜色需通过lv_obj_set_style_border_color()设置,透明度通过lv_obj_set_style_border_opa()控制;*                  边框占用对象边界空间(Bounding),内容区宽度 = 边界宽度 - 2×边框宽度;*                  可通过lv_obj_set_style_border_side()指定显示边框的方向(如仅显示上、下边框)*/
void lv_obj_set_style_border_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);/*** 设置对象的文本颜色* @param obj       目标对象指针(lv_obj_t*,不可为NULL,需为支持文本的控件如标签、按钮、输入框)* @param value     文本颜色(lv_color_t),生成方式同背景色* @param selector  样式选择器(lv_style_selector_t),格式为「部件 | 状态」* @note            仅对包含文本的部件生效(如按钮的主部件、标签的主部件);*                  文本透明度通过lv_obj_set_style_text_opa()控制(默认完全不透明);*                  文本装饰(如下划线)的颜色与文本颜色一致,无法单独设置*/
void lv_obj_set_style_text_color(lv_obj_t * obj, lv_color_t value, lv_style_selector_t selector);/*** 设置对象的上内边距(边框与内容区的顶部间距)* @param obj       目标对象指针(lv_obj_t*,不可为NULL)* @param value     上内边距值(int32_t),单位为像素;非负整数* @param selector  样式选择器(lv_style_selector_t),格式为「部件 | 状态」* @note            内边距影响内容区与边框的距离,以及子对象在父对象内的排列范围;*                  可通过lv_obj_set_style_pad_all()统一设置四方向内边距,单独设置某方向会覆盖统一设置;*                  与外边距(margin)的区别:内边距在边框内侧,外边距在边框外侧*/
void lv_obj_set_style_pad_top(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);/*** 设置对象的圆角半径* @param obj       目标对象指针(lv_obj_t*,不可为NULL)* @param value     圆角半径(int32_t),单位为像素;0表示直角* @param selector  样式选择器(lv_style_selector_t),格式为「部件 | 状态」* @note            对有背景或边框的部件生效(如按钮、容器),文本、线条等无边界控件不生效;*                  圆角大小受对象尺寸限制,最大圆角为宽/高的一半(超过会自动截断);*                  若同时设置阴影,阴影会随圆角同步变化(圆角阴影更自然)*/
void lv_obj_set_style_radius(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);/*** 设置对象的阴影宽度(阴影扩散范围)* @param obj       目标对象指针(lv_obj_t*,不可为NULL)* @param value     阴影宽度(int32_t),单位为像素;0表示隐藏阴影* @param selector  样式选择器(lv_style_selector_t),格式为「部件 | 状态」* @note            阴影颜色通过lv_obj_set_style_shadow_color()设置,透明度通过lv_obj_set_style_shadow_opa()控制;*                  阴影位置由lv_obj_set_style_shadow_offset_x/y()控制(默认向右下方偏移);*                  阴影不占用对象边界空间,仅为视觉效果,不影响布局*/
void lv_obj_set_style_shadow_width(lv_obj_t * obj, int32_t value, lv_style_selector_t selector);/*** 设置Flex布局的排列方向(仅启用LV_USE_FLEX时生效)* @param obj       目标对象指针(lv_obj_t*,不可为NULL,需为父容器)* @param value     Flex布局方向(lv_flex_flow_t),如LV_FLEX_FLOW_ROW(水平)、LV_FLEX_FLOW_COLUMN(垂直)* @param selector  样式选择器(lv_style_selector_t),格式为「部件 | 状态」(通常用LV_PART_MAIN | LV_STATE_DEFAULT)* @note            需先通过lv_obj_set_style_layout(obj, LV_LAYOUT_FLEX, ...)启用Flex布局;*                  配合lv_obj_set_style_flex_main_place()(主轴对齐)和lv_obj_set_style_flex_cross_place()(交叉轴对齐)使用;*                  作用于父容器,控制所有子对象的整体排列方向*/
void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector);/*** 设置对象的过渡动画(状态切换时的平滑过渡效果)* @param obj       目标对象指针(lv_obj_t*,不可为NULL)* @param value     过渡描述符指针(const lv_style_transition_dsc_t*),需通过lv_style_transition_dsc_init()初始化* @param selector  样式选择器(lv_style_selector_t),格式为「部件 | 状态」(常用LV_PART_MAIN | LV_STATE_ANY)* @note            过渡描述符需定义过渡属性(如背景色、边框宽度)、动画路径、时长等;*                  仅在对象状态变化时触发(如从默认→按下),初始加载时不触发;*                  过渡描述符需为static/全局变量(避免栈内存释放导致的野指针)*/
void lv_obj_set_style_transition(lv_obj_t * obj, const lv_style_transition_dsc_t * value, lv_style_selector_t selector);

样式使用步骤

步骤 1:初始化样式

样式变量需为静态(static)、全局或动态分配(不能是函数局部变量,函数结束后会被销毁),通过lv_style_init()初始化。

函数解析:

/*** 初始化样式对象,为后续设置样式属性(颜色、尺寸、边框等)做准备* @param style  待初始化的样式对象指针(lv_style_t*,不可为NULL)* @note         必须在使用样式前调用,否则通过 lv_style_set_xxx() 设置属性会导致未定义行为;*               样式对象需提前声明(如 lv_style_t my_style;),传入指针前确保已分配内存(栈/堆均可);*               初始化后可通过 lv_style_set_text_color()、lv_style_set_border_width() 等接口设置具体样式属性;*               同一样式可被多个对象共享(通过 lv_obj_add_style(obj, &my_style, 0)),修改样式会同步影响所有关联对象;*               LVGL 9.x 中样式无需手动销毁,随对象生命周期自动管理,避免重复初始化同一样式对象(可能导致资源泄漏)*/
void lv_style_init(lv_style_t * style);

示例:

/*** 初始化样式:创建“基础按钮样式”和“警告按钮样式”* @note 样式变量用static修饰,避免函数结束后内存释放*/
static void style_init(void) {// 初始化“基础按钮样式”(通用样式,可复用)static lv_style_t style_base;lv_style_init(&style_base); // 初始化样式结构体// 初始化“警告按钮样式”(基于基础样式扩展,修改部分属性)static lv_style_t style_warning;lv_style_init(&style_warning);// 初始化“过渡动画样式”(用于按钮按下时的渐变效果)static lv_style_t style_trans;lv_style_init(&style_trans);
}

步骤 2:设置样式属性

通过lv_style_set_xxx()接口设置属性(如背景色、圆角),接口格式统一为lv_style_set_属性名(样式指针, 值),完整接口见lv_style_gen.h

常用函数解析:

/*** 设置样式的宽度属性(控件的基础宽度)* @param style  样式对象指针(lv_style_t*,不可为NULL,需先通过lv_style_init初始化)* @param value  宽度值(int32_t),单位为像素;支持负数(特殊布局场景),0表示自适应内容* @note         该属性会直接影响控件的边界宽度(Bounding Width);*               若同时设置了lv_style_set_min_width和lv_style_set_max_width,实际宽度会被限制在[min, max]范围内;*               适用于所有控件,尤其在固定尺寸布局中常用(如按钮、输入框)*/
void lv_style_set_width(lv_style_t * style, int32_t value);/*** 设置样式的背景颜色* @param style  样式对象指针(lv_style_t*,不可为NULL)* @param value  颜色值(lv_color_t),可通过lv_color_hex(0xRRGGBB)、lv_color_rgb(r, g, b)或预设颜色(如lv_color_white())生成* @note         背景色透明度由lv_style_set_bg_opa()单独控制(默认完全不透明);*               若同时设置了背景渐变(lv_style_set_bg_grad_color()),会覆盖纯色背景,形成渐变效果;*               适用于容器、按钮、标签等所有需要背景的控件*/
void lv_style_set_bg_color(lv_style_t * style, lv_color_t value);/*** 设置样式的边框宽度* @param style  样式对象指针(lv_style_t*,不可为NULL)* @param value  边框宽度(int32_t),单位为像素;0表示隐藏边框* @note         边框颜色需通过lv_style_set_border_color()设置,透明度通过lv_style_set_border_opa()控制;*               边框会占用控件的边界空间(Bounding),即实际内容区宽度 = 边界宽度 - 2×边框宽度;*               可通过lv_style_set_border_side()指定显示边框的方向(如仅显示上边框、左右边框)*/
void lv_style_set_border_width(lv_style_t * style, int32_t value);/*** 设置样式的文本颜色* @param style  样式对象指针(lv_style_t*,不可为NULL)* @param value  文本颜色值(lv_color_t),生成方式同背景色(如lv_color_hex(0xFF0000)表示红色)* @note         仅对支持文本的控件生效(如标签lv_label、按钮文本、输入框等);*               文本透明度由lv_style_set_text_opa()控制,默认完全不透明;*               若控件同时设置了文本装饰(如下划线lv_text_decor_t),装饰线颜色与文本颜色一致*/
void lv_style_set_text_color(lv_style_t * style, lv_color_t value);/*** 设置样式的上内边距(边框与内容区的顶部间距)* @param style  样式对象指针(lv_style_t*,不可为NULL)* @param value  上内边距值(int32_t),单位为像素;不可为负数* @note         内边距影响控件内部内容的布局(如标签文本与边框的距离、子控件与父控件边框的距离);*               可通过lv_style_set_pad_all()统一设置上下左右内边距,单独设置某方向会覆盖统一设置;*               与外边距(lv_style_set_margin_top())的区别:内边距在控件边界内部,外边距在边界外部*/
void lv_style_set_pad_top(lv_style_t * style, int32_t value);/*** 设置样式的圆角半径* @param style  样式对象指针(lv_style_t*,不可为NULL)* @param value  圆角半径(int32_t),单位为像素;0表示直角,值越大圆角越明显* @note         对有背景或边框的控件生效(如按钮、容器、输入框),文本、线条等无边界控件不生效;*               若同时设置了阴影(lv_style_set_shadow_width()),阴影也会随圆角同步变化;*               过大的圆角(超过控件宽高的一半)会被自动限制为最大可能值(如正方形控件最大圆角为宽高的1/2)*/
void lv_style_set_radius(lv_style_t * style, int32_t value);/*** 设置样式的阴影宽度(阴影的扩散范围)* @param style  样式对象指针(lv_style_t*,不可为NULL)* @param value  阴影宽度(int32_t),单位为像素;0表示隐藏阴影* @note         阴影颜色通过lv_style_set_shadow_color()设置,透明度通过lv_style_set_shadow_opa()控制;*               阴影位置由lv_style_set_shadow_offset_x()和lv_style_set_shadow_offset_y()控制(默认向右下方偏移);*               阴影不占用控件的边界空间(Bounding),不会影响布局,仅为视觉效果*/
void lv_style_set_shadow_width(lv_style_t * style, int32_t value);/*** 设置样式的文本字体* @param style  样式对象指针(lv_style_t*,不可为NULL)* @param value  字体对象指针(const lv_font_t*),需使用LVGL支持的字体(如lv_font_montserrat_16、自定义字体)* @note         字体需在lv_conf.h中启用(如#define LV_FONT_MONTSERRAT_16 1),否则无法生效;*               文本尺寸会随字体自动变化,无需手动调整;*               适用于所有文本类控件,同一控件可通过不同状态(如选中/未选中)绑定不同字体*/
void lv_style_set_text_font(lv_style_t * style, const lv_font_t * value);/*** 设置样式的透明度(整体透明度,影响控件所有元素)* @param style  样式对象指针(lv_style_t*,不可为NULL)* @param value  透明度值(lv_opa_t),范围0~255:0表示完全透明,255表示完全不透明* @note         该属性是整体透明度,会覆盖背景、边框、文本等单独设置的透明度(如bg_opa、text_opa);*               常用于控件的淡入淡出动画(通过动态修改opa值实现);*               与lv_style_set_opa_layered()的区别:opa影响整个控件,opa_layered仅影响控件的层级叠加部分*/
void lv_style_set_opa(lv_style_t * style, lv_opa_t value);/*** 设置Flex布局的排列方式(仅在启用LV_USE_FLEX时生效)* @param style  样式对象指针(lv_style_t*,不可为NULL)* @param value  Flex布局类型(lv_flex_flow_t),如LV_FLEX_FLOW_ROW(水平排列)、LV_FLEX_FLOW_COLUMN(垂直排列)* @note         需先通过lv_style_set_layout(style, LV_LAYOUT_FLEX)启用Flex布局,否则该属性无效;*               配合lv_style_set_flex_main_place()(主轴对齐)、lv_style_set_flex_cross_place()(交叉轴对齐)使用;*               适用于父控件,控制子控件的整体排列方向(如工具栏按钮水平排列、列表项垂直排列)*/
void lv_style_set_flex_flow(lv_style_t * style, lv_flex_flow_t value);/*** 初始化过渡描述符(定义样式属性过渡动画的核心配置)* @param dsc       过渡描述符指针(lv_style_transition_dsc_t*,不可为NULL),需为static/全局变量(避免栈内存释放)* @param props     过渡属性数组(const lv_style_prop_t*),指定哪些样式属性需要过渡(如LV_STYLE_BG_COLOR),必须以0结尾* @param path      动画路径函数(lv_anim_path_cb_t),定义过渡的速度曲线(如线性、缓入缓出)* @param time      过渡时长(uint32_t),单位为毫秒(ms),如200表示动画持续0.2秒* @param delay     过渡延迟时间(uint32_t),单位为毫秒(ms),0表示立即开始,500表示延迟0.5秒后开始* @param user_data 自定义数据(void*),可选参数,通常传NULL,用于复杂动画的额外参数传递* @note           过渡描述符是样式过渡动画的“配置文件”,必须通过此函数初始化后才能被lv_style_set_transition()使用;*                 props数组必须以0结尾(如{LV_STYLE_BG_COLOR, LV_STYLE_BORDER_WIDTH, 0}),否则会导致未定义行为;*                 常用动画路径函数:*                    - lv_anim_path_linear:线性过渡(速度均匀);*                    - lv_anim_path_ease_in:缓入(开始慢,逐渐加快);*                    - lv_anim_path_ease_out:缓出(开始快,逐渐减慢);*                    - lv_anim_path_ease_in_out:缓入缓出(中间快,两头慢);*                 描述符初始化后可重复使用(绑定到多个样式),修改描述符会影响所有关联的样式*/
void lv_style_transition_dsc_init(lv_style_transition_dsc_t * dsc, const lv_style_prop_t * props, lv_anim_path_cb_t path, uint32_t time, uint32_t delay, void * user_data);/*** 为样式设置过渡动画效果(使样式属性在状态切换时平滑变化)* @param style  样式对象指针(lv_style_t*,不可为NULL,需先初始化)* @param value  过渡描述符指针(const lv_style_transition_dsc_t*),需通过lv_style_transition_dsc_init()初始化;*               传NULL表示取消过渡效果* @note         过渡动画作用:当控件状态变化(如从LV_STATE_DEFAULT→LV_STATE_PRESSED)时,*                  使指定的样式属性(如背景色、边框宽度)从旧值平滑过渡到新值,而非突然变化;*               过渡描述符需提前初始化,包含以下核心信息:*                  - 过渡属性(如LV_STYLE_BG_COLOR、LV_STYLE_BORDER_WIDTH);*                  - 动画路径(如lv_anim_path_linear线性变化、lv_anim_path_ease_in缓入);*                  - 过渡时长(如100ms)和延迟时间(如0ms立即开始);*               过渡描述符必须是static/全局变量(避免栈内存释放导致的野指针);*               需配合lv_obj_add_style()将样式应用到控件,并指定作用状态(如LV_STATE_ANY表示所有状态切换均生效)*/
void lv_style_set_transition(lv_style_t * style, const lv_style_transition_dsc_t * value);

示例:

// 续上:设置样式属性(LVGL 9.2版本适配)
static void style_init(void) {// -------------------------- 基础按钮样式(style_base) --------------------------static lv_style_t style_base;lv_style_init(&style_base);// 主体部件样式(LVGL 9.x中part通过对象类型自动关联,状态在应用样式时指定):lv_style_set_bg_color(&style_base, lv_color_hex(0x0099FF)); // 背景色:蓝色lv_style_set_bg_opa(&style_base, LV_OPA_100); // 背景不透明度:100%lv_style_set_border_color(&style_base, lv_color_hex(0x0066CC)); // 边框色:深蓝色lv_style_set_border_width(&style_base, 2); // 边框宽度:2像素lv_style_set_radius(&style_base, 10); // 圆角:10像素(圆润效果)lv_style_set_shadow_width(&style_base, 8); // 阴影宽度:8像素lv_style_set_shadow_color(&style_base, lv_color_hex(0x99CCFF)); // 阴影色:浅蓝lv_style_set_shadow_offset_y(&style_base, 4); // 阴影Y偏移:4像素(向下)// 文本相关样式:lv_style_set_text_color(&style_base, lv_color_hex(0xFFFFFF)); // 文本色:白色lv_style_set_text_font(&style_base, &lv_font_montserrat_20); // 字体:20号英文// 尺寸相关样式:lv_style_set_width(&style_base, 120); // 固定宽度:120像素lv_style_set_height(&style_base, LV_SIZE_CONTENT); // 高度:自适应内容// -------------------------- 警告按钮样式(style_warning) --------------------------static lv_style_t style_warning;lv_style_init(&style_warning);// 仅修改与基础样式不同的属性(优先级高于style_base):lv_style_set_bg_color(&style_warning, lv_color_hex(0xFFFF99)); // 背景色:黄色lv_style_set_border_color(&style_warning, lv_color_hex(0xFFCC00)); // 边框色:深黄lv_style_set_text_color(&style_warning, lv_color_hex(0xCC6600)); // 文本色:橙棕lv_style_set_shadow_color(&style_warning, lv_color_hex(0xFFFFCC)); // 阴影色:浅黄// -------------------------- 过渡动画样式(style_trans) --------------------------static lv_style_t style_trans;lv_style_init(&style_trans);// 定义过渡属性:背景色、边框色、边框宽度(状态变化时这些属性会动画过渡)static const lv_style_prop_t trans_props[] = {LV_STYLE_BG_COLOR, LV_STYLE_BORDER_COLOR, LV_STYLE_BORDER_WIDTH, 0};// 初始化过渡描述符:static lv_style_transition_dsc_t trans_dsc;lv_style_transition_dsc_init(&trans_dsc, trans_props, lv_anim_path_linear, 100, 0, NULL);// 将过渡效果添加到样式:lv_style_set_transition(&style_trans, &trans_dsc); // LVGL 9.x中无需指定state,通过应用时的state生效
}

步骤 3:将样式应用到对象

通过lv_obj_add_style()将样式添加到对象,指定作用的部件和状态,支持多样式叠加。

/*** 给对象绑定通用样式(lv_style_t),指定样式作用的“部件+状态”,实现样式复用* @param obj       目标对象指针(lv_obj_t*,不可为NULL)*                  - 需为已创建的LVGL控件(如按钮、容器、标签等,通过lv_xxx_create创建)*                  - 样式绑定后,对象会立即应用样式属性,状态变化时自动切换对应样式* @param style     通用样式指针(const lv_style_t*,不可为NULL)*                  - 需先通过lv_style_init初始化,再通过lv_style_set_xxx设置属性(如背景色、圆角)*                  - 样式对象需为全局/静态变量(避免局部变量释放导致野指针,样式属性失效)* @param selector  样式选择器(lv_style_selector_t),格式为「部件常量 | 状态常量」,用于限定样式作用范围*                  - 部件(Part):指定样式作用的对象部件,常用值:*                    > LV_PART_MAIN:主部件(默认,如按钮的主体、容器的背景)*                    > LV_PART_INDICATOR:指示器部件(如滑动条的滑块、复选框的勾选框)*                    > LV_PART_KNOB:旋钮部件(如旋钮控件的旋转部分)*                  - 状态(State):指定样式生效的对象状态,常用值:*                    > LV_STATE_DEFAULT:默认状态(控件未被操作时)*                    > LV_STATE_PRESSED:按下状态(控件被点击/触摸时)*                    > LV_STATE_DISABLED:禁用状态(控件不可交互时)*                    > LV_STATE_ANY:所有状态(样式对任意状态生效)* @note           样式叠加规则:同一对象绑定多个通用样式,若selector的“部件+状态”完全匹配,后绑定的样式优先级更高(同属性覆盖前一个);*                 状态优先级规则:精准匹配当前状态的样式(如LV_STATE_PRESSED)> 通用状态样式(LV_STATE_ANY),即使精准状态样式先绑定;*                 与本地样式的优先级:通过lv_obj_set_style_xxx设置的本地样式,优先级高于所有通过此接口绑定的通用样式;*                 样式复用:同一style可绑定到多个对象(如“红色按钮样式”绑定到所有确认按钮),修改style会同步更新所有关联对象;*                 重复绑定:同一style+selector绑定到同一对象,不会重复生效(仅首次绑定有效,后续绑定无意义)*/
void lv_obj_add_style(lv_obj_t * obj, const lv_style_t * style, lv_style_selector_t selector);

示例:

/*** 样式应用示例:创建“基础按钮”和“警告按钮”,叠加过渡动画*/
void style_application_demo(void) {// -------------------------- 初始化所有样式(合并style_init,避免static变量跨函数访问问题) --------------------------// 基础按钮样式static lv_style_t style_base;lv_style_init(&style_base);lv_style_set_bg_color(&style_base, lv_color_hex(0x0099FF));lv_style_set_bg_opa(&style_base, LV_OPA_100);lv_style_set_border_color(&style_base, lv_color_hex(0x0066CC));lv_style_set_border_width(&style_base, 2);lv_style_set_radius(&style_base, 10);lv_style_set_shadow_width(&style_base, 8);lv_style_set_shadow_color(&style_base, lv_color_hex(0x99CCFF));lv_style_set_shadow_offset_y(&style_base, 4);lv_style_set_text_color(&style_base, lv_color_hex(0xFFFFFF));lv_style_set_text_font(&style_base, &lv_font_montserrat_20);lv_style_set_width(&style_base, 120);lv_style_set_height(&style_base, LV_SIZE_CONTENT);// 警告按钮样式(覆盖基础样式差异项)static lv_style_t style_warning;lv_style_init(&style_warning);lv_style_set_bg_color(&style_warning, lv_color_hex(0xFFFF99));lv_style_set_border_color(&style_warning, lv_color_hex(0xFFCC00));lv_style_set_text_color(&style_warning, lv_color_hex(0xCC6600));lv_style_set_shadow_color(&style_warning, lv_color_hex(0xFFFFCC));// 通用过渡动画样式static lv_style_t style_trans;lv_style_init(&style_trans);static const lv_style_prop_t trans_props[] = {LV_STYLE_BG_COLOR, LV_STYLE_BORDER_COLOR, LV_STYLE_BORDER_WIDTH, 0};static lv_style_transition_dsc_t trans_dsc;lv_style_transition_dsc_init(&trans_dsc, trans_props, lv_anim_path_linear, 100, 0, NULL);lv_style_set_transition(&style_trans, &trans_dsc);// 按下状态专属样式static lv_style_t style_press;lv_style_init(&style_press);lv_style_set_bg_color(&style_press, lv_color_hex(0xFF6666));  // 按下背景:红色lv_style_set_border_width(&style_press, 4);                  // 按下边框:4像素lv_style_set_border_color(&style_press, lv_color_hex(0xCC3333)); // 按下边框色:深红// 按下状态过渡(慢动画500ms)static lv_style_transition_dsc_t trans_press;static const lv_style_prop_t trans_press_props[] = {LV_STYLE_BG_COLOR, LV_STYLE_BORDER_WIDTH, 0};lv_style_transition_dsc_init(&trans_press, trans_press_props, lv_anim_path_linear, 500, 0, NULL);lv_style_set_transition(&style_press, &trans_press);// -------------------------- 创建基础容器与控件 --------------------------// 获取当前活跃屏幕lv_obj_t *scr = lv_scr_act();// -------------------------- 应用1:基础按钮(style_base + style_trans) --------------------------lv_obj_t *btn_base = lv_btn_create(scr);// LVGL 9.x:lv_obj_add_style 移除LV_PART_MAIN(默认作用于主部件),参数顺序为「对象→样式→状态」lv_obj_add_style(btn_base, &style_base, LV_STATE_DEFAULT);  // 基础样式:默认状态lv_obj_add_style(btn_base, &style_trans, LV_STATE_ANY);     // 过渡样式:所有状态// 按钮位置:左中,偏移20像素lv_obj_align(btn_base, LV_ALIGN_LEFT_MID, 20, 0);// 按钮子标签:显示“Base”lv_obj_t *label_base = lv_label_create(btn_base);lv_label_set_text(label_base, "Base");lv_obj_center(label_base);  // 标签在按钮内居中// -------------------------- 应用2:警告按钮(style_base + style_warning + style_trans) --------------------------lv_obj_t *btn_warning = lv_btn_create(scr);// 样式叠加逻辑:基础样式(底层)→ 警告样式(中层,覆盖差异)→ 过渡样式(顶层)lv_obj_add_style(btn_warning, &style_base, LV_STATE_DEFAULT);   // 基础样式:底层lv_obj_add_style(btn_warning, &style_warning, LV_STATE_DEFAULT); // 警告样式:中层(覆盖基础)lv_obj_add_style(btn_warning, &style_trans, LV_STATE_ANY);     // 过渡样式:顶层// 按钮位置:右中,偏移-20像素lv_obj_align(btn_warning, LV_ALIGN_RIGHT_MID, -20, 0);// 按钮子标签:显示“Warning”lv_obj_t *label_warning = lv_label_create(btn_warning);lv_label_set_text(label_warning, "Warning");lv_obj_center(label_warning);// -------------------------- 应用3:带按下状态的按钮(style_base + style_press + style_trans) --------------------------lv_obj_t *btn_press = lv_btn_create(scr);// 样式叠加:基础样式(默认)→ 按下样式(仅按压时生效)→ 过渡样式(所有状态)lv_obj_add_style(btn_press, &style_base, LV_STATE_DEFAULT);   // 基础样式:默认状态lv_obj_add_style(btn_press, &style_press, LV_STATE_PRESSED);  // 按下样式:仅按压时生效lv_obj_add_style(btn_press, &style_trans, LV_STATE_ANY);     // 过渡样式:所有状态// 按钮位置:居中,偏移100像素(在基础/警告按钮下方)lv_obj_align(btn_press, LV_ALIGN_CENTER, 0, 100);// 按钮子标签:显示“Press Me”lv_obj_t *label_press = lv_label_create(btn_press);lv_label_set_text(label_press, "Press Me");lv_obj_center(label_press);
}

效果:

image

样式优先级规则

当一个对象应用多个样式时,优先级从高到低为:

  • 子对象的本地样式lv_obj_set_style_xxx(obj, ...) 直接设置的样式(覆盖所有传递 / 继承);
  • 子对象后添加的通用样式lv_obj_add_style(obj, style2, state) 后添加的样式(同状态下覆盖先添加的);
  • 子对象先添加的通用样式lv_obj_add_style(obj, style1, state) 先添加的样式;
  • 父对象传递的特定属性:仅布局属性(如 layout)和部分文本属性(如 text_font),且子对象未设置自己的样式;
  • LVGL 控件默认样式:控件自带的默认外观(如按钮默认灰色背景)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/953712.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025 年 11 月 CBN 砂轮厂家最新推荐:磨粒精筛 + 工艺焕新,高稳定产品选购指南

工业磨削作业对 CBN 砂轮的稳定性与磨削效率要求不断提高,磨粒纯度与生产工艺成为关键影响因素。本次推荐基于行业权威协会 2025 年第三季度专项测评结果,测评覆盖 50 余家源头厂家,采用 “三维十项” 科学评估体系…

设备调试基础实验

ping -6 www.baidu.com # 使用ipv6平百度华为路由器: pwd # flash:/ 根目录 dir # 等于ls mkdir # 创建文件夹 rmdir # 删除文件夹 rename 文件名 新文件名 # 修改文件名 copy 文件 文件 # 复制文件 move # 移…

20231302邱之钊密码系统设计实验二一

《密码系统设计》实验二 在 Ubuntu或openEuler中(推荐 openEuler)中调试运⾏商⽤密码检测中⼼https://www.scctc.org.cn/xzzx/sfydm/ydmxz/提供的源代码,⾄少运⾏SM2,SM3,SM4代码。使⽤GmSSL命令验证你代码的正确…

2025 年 11 月运动木地板厂家最新推荐,成分精纯与效能升级!—— 产能、专利、环保三维数据透视

体育场馆建设对运动木地板的成分精纯度与综合效能要求不断提高,市场上部分产品存在原材杂质多、环保不达标等问题,影响使用安全与场馆寿命。为筛选优质品牌,本次推荐从产能、专利、环保三维度开展测评。产能维度核查…

2025 年 11 月运动木地板厂家最新推荐,配方精研与效能焕新!—— 实力品牌深度解析采购无忧之选!

运动木地板的配方设计与效能表现,直接决定体育场馆的使用体验与安全系数。当前市场部分品牌存在木材配方不合理、性能参数不达标等问题,增加采购风险。为挖掘实力品牌,本次测评从品牌实力核心维度开展:核查品牌成立…

2025 年 11 月运动木地板厂家最新推荐,成分焕新与效能强化!—— 精准检测与稳定性能深度解析

当下体育场馆对运动木地板的成分品质与性能稳定性要求持续提升,市场中部分产品存在木材纤维结构松散、减震效能衰减等问题,给运动安全与场馆运营带来隐患。为筛选优质品牌,本次推荐联合专业检测机构,依据国际运动地…

【软考】信安中级密码学专题

针对信安中级里,密码学相关案例题的知识点和真题密码学的三大目标 ‌Confidentiality 机密性(保密性):确保信息未经非授权的访问,避免信息泄露。 Integrity 完整性:防止信息非法的修改和毁坏,…

算法 第二次作业

算法 第二次作业找第k小的数的分治算法(快速选择算法) 自然语言描述: 选择一个元素作为“基准”:从数组中选择一个元素作为基准,选择的方法可以有多种,例如随机选择、选择数组的第一个元素、选择数组的中间元素等…

JavaScript异步编程:从回调地狱到优雅解决方案

异步编程是JavaScript的核心能力,但回调嵌套易导致"回调地狱"。本文将介绍现代JS异步处理的演进之路,助你写出更简洁高效的代码。1. Promise:异步操作的基石 Promise 通过链式调用解决回调嵌套问题: fet…

使用JavaScript和Node.js构建简单的RESTful API

引言:本文将指导你如何使用JavaScript和Node.js的Express框架构建一个简单的RESTful API。我们将创建一个简单的用户管理系统,包括获取用户列表、添加新用户以及删除用户。 正文与代码演示:设置项目:首先,创建一个…

JavaScript中的闭包:原理、应用与代码

在JavaScript的众多概念中,闭包(Closure)无疑是一个既深奥又强大的特性。闭包不仅能够帮助我们封装私有变量,实现模块化编程,还能在函数之间传递状态,使得函数的行为更加丰富和灵活。本文将深入探讨闭包的原理,…

2025 年 11 月 PVC 地板厂家最新推荐,聚焦原料安全与功效稳定的专业产品解析

PVC 地板因适用场景广泛,全球市场需求逐年攀升,但原料安全不达标、功效随使用波动等问题,让采购方面临决策难题。为解决这一痛点,国际地材专业测评协会联合材料安全机构,参照氨糖行业对原料安全、功效稳定的专业评…

2025 年 11 月 PVC 地板厂家最新推荐,聚焦原料合规与功效持久的专业产品解析

PVC 地板全球市场需求旺盛,但原料不合规、功效随使用周期快速衰退等问题,成为采购方核心顾虑。为提供科学选购依据,国际地材合规测评协会联合材料性能机构,参照氨糖行业对原料合规、功效持久的专业评估标准,开展 …

2025 年 11 月 PVC 地板厂家最新推荐,聚焦成分安全与功效持续的优质产品解析

PVC 地板在全球各场景广泛应用,但成分安全隐患、功效随使用衰减等问题频发。为解决采购痛点,国际地材安全测评协会联合材料研究机构,参照氨糖行业对成分安全、功效持续的严格标准,开展 2025 年 11 月 PVC 地板专项…

2025 年 11 月 PVC 地板厂家最新推荐,聚焦原料品质与功效长效性的优质产品解析

PVC 地板市场规模持续扩大,但原料品质参差不齐、功效随使用周期衰退等问题,成为采购方核心顾虑。为提供科学选购依据,国际地材品质认证协会联合材料检测机构,参照氨糖行业对原料纯度、功效稳定性的严苛评估体系,开…

React Hooks:提升前端开发效率的关键

在现代前端开发中,React作为最受欢迎的JavaScript库之一,其生态系统不断演进,带来了许多创新和优化。其中,React Hooks的出现无疑是一个革命性的里程碑。自React 16.8版本引入以来,Hooks已经成为了前端开发者们提…

网络设备命令行

1. 命令行视图进入设备时是用户视图 用户视图:查看运行状态和统计信息等功能 系统视图:配置系统参数以及进入其他功能配置视图 其他视图:用户可以进行接口参数和协议参数配置用户视图切成系统视图命令 system-view …

基于BESO方法实现MBB梁一体化拓扑优化

一、MBB梁拓扑优化问题定义 设计目标:在满足刚度约束下实现质量最小化(或刚度最大化下的质量约束) 设计变量:材料密度分布(0-1离散变量) 约束条件:总质量 ≤ 目标质量(体积分数约束) 关键节点位移 ≤ 允许值 …

究极干货 —— 用最纯粹的语言,解析 DeepSeek OCR

究极干货 —— 用最纯粹的语言,解析 DeepSeek OCR这是一篇 “纯干货” 文章,用 8500 字的最纯粹的语言,解析 DeepSeek OCR,与大家探讨 AI 记忆系统的各种可能性~楔子 最近看到了一篇极具启发性的论文:《DeepSeek-…

【图文详细】用HBuilder X写PHP并且能够在浏览器运行打开 - 昵

【图文详细】用HBuilder X写PHP并且能够在浏览器运行打开 今天教大家如何使用HBuilder X写PHP。 用到的工具: HBuilder X,配置phpstudy端口和url、登录账号下载php语言服务 phpStudy,仅仅查看端口,启动apache、mysq…