跳转到内容

LVGL Graphics

LVGL(Light and Versatile Graphics Library,轻量通用图形库)是一个免费且开源的嵌入式图形库,可为任何 MCU、MPU 和显示类型创建精美的 UI。ESPHome 支持 LVGL 9 版本。

要在 ESPHome 中将 LVGL 与显示配合使用,你需要 ESP32 或 RP2040。PSRAM 并非严格要求,但通常建议使用,特别是对于大尺寸彩色显示器。

图形显示应以 auto_clear_enabled: false 配置,且不应设置任何 lambda。LVGL 组件将处理显示渲染。对于大多数显示器,update_interval 应设为 never,但请注意,某些显示器(如 OLED 和电子墨水屏)需要将更新间隔设为合适的值,或使用 update_when_display_idle 选项,或使用 on_draw_end 触发器手动更新显示。

如需交互,可以使用触摸屏(强烈建议使用电容式)、旋转编码器或由离散二进制传感器组成的自定义键盘。

查看 食谱 中的详细示例,这些示例展示了将环境与 LVGL 和 ESPHome 集成的多种方式。

NOTE

强烈建议在尝试添加自己的内容之前,使用此示例在新设备上验证显示和 LVGL 配置是否正确。检查显示颜色是否与示例图片匹配(布局将因显示尺寸而异)。

要开始使用,只需添加一个显示和一个空的 LVGL 配置即可。如果既未指定 pages 也未指定 widgets,则会显示默认的”hello world”页面。

# 测试配置条目示例
display:
- platform: ...
# ...
auto_clear_enabled: false
update_interval: never
lvgl:

要使 LVGL 成为你自己的,你需要向显示添加组件。例如,要在屏幕中央显示一个包含文本”Hello World!”的标签:

# 最小配置条目示例
lvgl:
widgets:
- label:
align: CENTER
text: 'Hello World!'

继续阅读以了解有关配置选项以及如何自定义 LVGL 显示的更多信息。

在 LVGL 中,像按钮、标签、滑块等图形元素称为组件(widgets)或对象。参见 组件 以了解 ESPHome 中支持的组件完整列表。并非所有 LVGL 组件都已实现,仅实现了常用于支持家庭自动化需求/任务的那些组件。

每个组件都有一个父对象,组件在其中创建。例如,如果在按钮上创建标签,则该按钮是标签的父对象。复杂的组件内部由多个较小/简单的组件组成;这些称为部分(parts),每部分都可以具有与主组件不同的属性。

ESPHome 中的页面实现为 LVGL 屏幕,屏幕是没有父对象的特殊对象。显示上始终有一个活动页面。

可以为组件分配 ID,以便在自动化中引用它们。

一些组件还作为原生 ESPHome 组件集成:

LVGL 组件ESPHome 组件
button开关、二进制传感器
switch、checkbox开关
slider、arc、spinbox数字、传感器
dropdown、roller选择
label、textarea文本、文本传感器
led灯

这些在通过 Home Assistant 自动化 直接与组件交互时很有用。

尽管 LVGL 是对象-部分-状态-样式的复杂矩阵,ESPHome 将其简化为层次结构。

LVGL 对象层次结构的最高层是显示(由硬件驱动表示)。显示可以关联一个或多个页面。每个页面包含表示要在显示上呈现的布局的组件对象层次结构。

以下配置变量适用于主 lvgl 组件,以建立基本运行条件。在此级别也可以设置一些样式选项,但仅用于继承目的。

配置变量:

  • displays(可选,list,ID):LVGL 应基于其配置执行渲染的显示 ID 列表。如果仅配置了一个显示,则可以省略,该显示将被自动使用。
  • touchscreens(可选,list):与显示上 LVGL 组件交互的触摸屏列表。如果配置了一个触摸屏,它将自动使用,无需此配置条目。
    • touchscreen_id(必需,ID):与显示相关的触摸屏配置的 ID。
    • long_press_time(可选,Time):对于触摸屏,on_long_pressed 交互触发器 被调用前的延迟。默认为 400ms。
    • long_press_repeat_time(可选,Time):对于触摸屏,on_long_pressed_repeat 交互触发器 被调用后的重复间隔。默认为 100ms。
  • encoders(可选,list):与显示上 LVGL 组件交互的旋转编码器列表。
    • group(可选,string):将与输入设备交互的组件组名称。有关组的更多信息,请参见组件的公共属性。
    • initial_focus(可选,ID):启动时获得焦点的组件的可选 ID(如果只有一个可聚焦组件则特别有用)。
    • enter_button(必需,ID):用作 ENTER 键的 二进制传感器 的 ID。
    • sensor(可选,ID):旋转编码器 的 ID;或用于与组件进行左/右交互的按钮列表:
    • long_press_time(可选,Time):对于旋转编码器,on_long_pressed 交互触发器 被调用前的延迟。默认为 400ms。可以使用 never 禁用。
    • long_press_repeat_time(可选,Time):对于旋转编码器,on_long_pressed_repeat 交互触发器 被调用后的重复间隔。默认为 100ms。可以使用 never 禁用。
  • rotary_sensitivity(可选,int16):以 1/256 单位调整旋转编码器的灵敏度。例如,128 可将旋转速度减半,512 可加速到两倍,256 不变。
  • keypads(可选,list):与显示上 LVGL 组件交互的键盘列表。

TIP

当使用二进制传感器(来自物理按键)与 LVGL 交互时,如果只有三个按键可用,则最好将其配置为旋转编码器,其中 LEFT 和 RIGHT 的作用类似于旋转滚轮,而 ENTER 生成 on_press 触发器。如果有四个或更多按键,通常键盘配置更合适。例如,由五个键组成的键盘可以使用 PREV、NEXT、UP、DOWN 和 ENTER;PREV/NEXT 用于在组内选择组件,UP/DOWN 更改选定的值,ENTER 生成 on_press 触发器。

long_press_time 和 long_press_repeat_time 还可以通过将它们设为 never 并在每个二进制传感器上单独使用 autorepeat 过滤器来进行微调。

TIP

当使用编码器输入设备时,导航方式如下:

  • 旋转编码器可聚焦到上一个/下一个对象。
  • 在简单对象(如按钮)上按下编码器时,它将点击该对象。
  • 如果在复杂对象(如列表、消息框等)上按下编码器,对象将进入编辑模式,可以通过旋转编码器调整对象的值。
  • 要退出编辑模式,请长按按钮。
  • rotation(可选,int16):以指定角度旋转显示内容。有效值为 0、90、180 和 270。默认为 0。
  • update_when_display_idle(可选,boolean):使用 Epaper Spi 或更新耗时较长的其他显示器时,将此选项设为 true 将使显示仅在空闲时才更新。更新期间 LVGL 将暂停。使用此选项时,显示的 update_interval 应设为 never,因为显示将由 LVGL 自动更新。
  • paused(可选,boolean):当为 true 时,LVGL 将初始处于暂停状态,直到调用 lvgl.resume: 之前显示不会更新。默认为 false。用于防止电子墨水屏在启动时更新显示,直到数据准备就绪,以避免显示空白屏幕或未设置样式的内容。
  • resume_on_input(可选,boolean):如果 LVGL 处于暂停状态且用户与屏幕交互,则恢复 LVGL 的活动。默认为 true。“交互”指释放触摸或按钮,或旋转编码器。
  • color_depth(可选,string):生成内容的颜色深度。目前仅支持 16(RGB565,每像素 2 字节),这也是默认值。
  • buffer_size(可选,percentage):为缓冲区内存分配的屏幕大小百分比。如果未配置,默认为 100%,如果全尺寸缓冲区分配失败,则在运行时回退到 12%。对于没有 PSRAM 的设备,推荐值为 25%。
  • draw_rounding(可选,int):用于将绘制区域四舍五入到指定边界的可选值。默认为 2。对于需要将绘制窗口置于指定边界(通常是 2 的幂)的显示器很有用。
  • log_level(可选,string):专门为 LVGL 库消息设置日志级别:VERBOSE、DEBUG、INFO、WARN、ERROR、NONE。默认为 WARN。
  • byte_order(可选,string):LVGL 输出数据的字节顺序;big_endian 或 little_endian。将尝试根据显示元数据自动配置。如果显示驱动未提供信息,则默认为 big_endian。
  • refresh_interval(可选,Time):屏幕刷新的最小间隔。默认为 16ms。
  • default_font(可选,ID):默认用于渲染文本或符号的字体 的 ID。如果未指定,默认为 LVGL 内置的 montserrat_14。
  • style_definitions(可选,list):在 LVGL 组件的 styles 配置中使用的样式定义集合。更多详情参见下文。
  • gradients(可选,list):在 bg_grad 样式中使用的渐变定义列表。更多详情参见下文。
  • theme(可选,dict):主题配置。支持 dark_mode 和每个组件的样式默认值。更多详情参见下文。
  • widgets(可选,list):要在根显示上绘制的组件 列表。如果配置了 pages(见下文),则不可使用。
  • pages(可选,list):页面 ID 列表。每个页面作为放置在其上组件的父对象。不可与 widgets(上方)一起使用。每个页面的选项:
    • skip(可选,boolean):使用 lvgl.page.next、lvgl.page.previous 在页面间导航时跳过此页面的选项。
    • layout(可选):详情参见 布局。默认为 NONE。
    • widgets(可选,list):要在页面上绘制的组件 列表。
    • 样式属性 的所有其他选项,应用于此页面。
  • page_wrap(可选,boolean):使用 lvgl.page.next、lvgl.page.previous 在页面间导航时,从最后一页循环到第一页。默认为 true。
  • top_layer(可选,list):一种特殊的”始终置顶”页面,作为放置在其上组件的父对象。它显示在所有页面之上,对于需要始终可见的组件可能很有用。
    • layout(可选):详情参见 布局。默认为 NONE。
    • widgets(可选,list):要在页面上绘制的组件 列表。
    • 样式属性 的所有其他选项,应用于此页面。
  • bottom_layer(可选,list):一个特殊层,放置在所有页面后面。用于设置显示的背景颜色或图像。取代了已弃用的 disp_bg_color、disp_bg_image 和 disp_bg_opa 选项。
    • layout(可选):详情参见 布局。默认为 NONE。
    • widgets(可选,list):要在该层上绘制的组件 列表。
    • 样式属性 的所有其他选项,应用于该层。
  • layout(可选):详情参见 布局。默认为 NONE。
  • animations(可选,list):动画 列表,随时间更改组件样式属性。
  • 样式属性 的所有其他选项,直接应用于所有组件。

示例:

# 页面配置条目示例
lvgl:
displays:
- my_display
pages:
- id: main_page
widgets:
- label:
align: CENTER
text: 'Hello World!'

查看食谱中的 页面导航页脚,该示例展示了如何在屏幕底部实现页面导航栏。

buffer_size 选项是显示大小的百分比。例如,如果你有 320x240 的显示器,缓冲区大小为 320 * 240 * 2 字节(对于 RGB565)= 153600 字节。如果将缓冲区大小设为 50%,则缓冲区将为 76800 字节。如果设为 25%,则缓冲区将为 38400 字节。默认值为 100%。

在 RAM 有限(即无 PSRAM)的设备上使用大显示器时,可能需要减小缓冲区大小以避免 RAM 耗尽。如果未指定,缓冲区大小将为 100%,但如果全尺寸缓冲区分配失败,则会在运行时尝试回退到 12%。如果设置了特定的缓冲区大小,则不会尝试回退。缓冲区分配失败将在日志中产生错误消息,并将 LVGL 组件标记为”Failed”。

一般来说,较大的缓冲区将提供更好的性能,但将缓冲区大小从 100% 减少的效果并不像你想的那么糟糕。LVGL 库设计为高效的,仅重绘屏幕上发生变化的部分。

当 PSRAM确实可用时,小于 100% 的缓冲区大小也可以用来提高性能。在这种情况下,建议使用 12% 的缓冲区大小,如果可能的话将分配在内部 RAM 中,这将提高显示重绘速度,因为内部 RAM 的访问速度远快于 PSRAM。但这可能会减少可用于其他组件的内部 RAM。大于 25% 的缓冲区大小将始终(如果可用)分配在 PSRAM 中。

如果配置了多个显示,并希望每个显示上显示不同的内容,则可以配置多个 LVGL 配置。例如:

# 多显示配置示例
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!'

rotation 选项允许以指定角度旋转显示内容。有效值为 0、90、180 和 270。默认为 0。 在 LVGL 配置中使用此选项将自动调整显示和触摸输入(如果配置了触摸屏)以匹配指定的旋转。使用时,显示配置中不应包含旋转选项,触摸屏配置也不应对触摸屏进行变换(除非需要,例如触摸屏轴与显示不匹配时)。

如果显示驱动可以在硬件中旋转显示内容(例如,大多数 mipi_spi 显示型号可以这样做),LVGL 将自动使用它来提高性能。如果不能,LVGL 将在软件中执行旋转,这将降低性能。在 ESP32P4 上,软件旋转使用 PPA 外设进行硬件加速。

使用 LVGL 旋转时,触摸屏坐标将自动旋转。

显示方向可以在运行时通过 lvgl.display.set_rotation 操作更改。

LVGL 遵循 CSS 的 border-box 模型。组件的框由以下部分组成:

  • 包围框(bounding box):使用 width 和 height 定义的框(像素或父内容区域百分比;不绘制,仅用于计算)。
  • 边框(border):边框线,绘制在包围框的内侧(像素)。
  • 轮廓(outline):轮廓,绘制在包围框的外侧(像素)。
  • 内边距(padding):边框与内容或子组件之间保留的空间(我不希望我的子组件离我的边缘太近,所以保留这个空间)。
  • 内容(content):内容区域,其大小等于包围框减去边框宽度和内边距(它是某些组件的 SIZE_CONTENT 选项所引用的内容)。

你可以通过更改组件的前景色、背景色、边框颜色和/或字体来调整其外观。一些组件允许更复杂的样式设置,实际上可以更改全部或部分外观。

这些样式属性可应用于任何组件,尽管并非所有组件都使用所有属性。

  • opa(可选,opacity):整个组件的透明度。从父对象继承。默认为 COVER。
  • opa_layered(可选,opacity):组件所在整个层的透明度。从父对象继承。默认为 COVER。
  • base_dir(可选):设置组件的基本方向。可选 LTR、RTL、AUTO(默认)。
  • bg_color(可选,color):组件背景的颜色。默认为 0xFFFFFF(白色)。
  • bg_opa(可选,opacity):组件背景的透明度。
  • bg_grad(可选,gradient):应用于背景的渐变。
  • bg_grad_color(可选,color):使背景逐渐淡入的颜色。默认为 0(黑色)。
  • bg_grad_dir(可选,dict):选择背景渐变的方向:NONE、HOR、VER。默认为 NONE。
  • bg_main_stop(可选,0-255):指定渐变应开始的位置:0 = 左上角,128 = 中心,255 = 右下角。默认为 0。
  • bg_grad_stop(可选,0-255):指定渐变应停止的位置:0 = 左上角,128 = 中心,255 = 右下角。默认为 255。
  • bg_main_opa(可选,opacity):设置第一个渐变颜色的透明度。默认为 COVER。
  • bg_grad_opa(可选,opacity):设置第二个渐变颜色的透明度。默认为 COVER。
  • bg_image_src(可选,image):现有图像配置的 ID,用作组件的背景。
  • bg_image_opa(可选,opacity):组件背景图像的透明度。
  • bg_image_recolor(可选,color):与组件背景图像的每个像素混合的颜色。
  • bg_image_recolor_opa(可选,opacity):组件背景图像重新着色的透明度。
  • blend_mode(可选):描述如何将颜色与背景混合。可选 NORMAL(默认)、ADDITIVE、SUBTRACTIVE、MULTIPLY、DIFFERENCE。
  • blur_radius(可选,int16):设置模糊的强度。在渲染子组件之前,分别应用于每个组件部分。默认为 0。
  • blur_backdrop(可选,boolean):如果为 true,组件的背景将被模糊。该部分应具有较小的透明度以便可见。如果为 false,则在绘制子组件之前,该部分将被模糊。默认为 false。
  • blur_quality(可选):可选 AUTO、SPEED、PRECISION。设为 SPEED 时,模糊算法将优先保证速度而非质量。PRECISION 将强制使用更高质量但更慢的模糊。AUTO 将自动选择质量(默认)。
  • border_width(可选,int16):以像素为单位设置边框宽度。默认为 0。
  • border_color(可选,color):绘制组件边框的颜色。默认为 0(黑色)。
  • border_opa(可选,opacity):组件边框的透明度。默认为 COVER。
  • border_post(可选,boolean):如果为 true,边框将在绘制完组件的所有子组件之后绘制。默认为 false。
  • border_side(可选,list):选择显示组件的哪些边框(可以 YAML 列表形式指定多个,默认为 NONE):
    • NONE
    • TOP
    • BOTTOM
    • LEFT
    • RIGHT
    • INTERNAL
  • radius(可选,uint16):用于形成组件圆角的半径。0 = 无半径(方形角);65535(最大)= 药丸形组件(如果宽度和高度相同则为正圆,此时半径应设为宽度/高度的一半)。
  • clip_corner(可选,boolean):如果设为 true,溢出的内容将被组件的圆角(radius > 0)裁剪。
  • color_filter_opa(可选,opacity):颜色过滤器的透明度。目前颜色过滤器仅由默认 LVGL 主题应用,此选项允许通过将透明度设为 TRANSP 来禁用这些效果。
  • anim_duration(可选,int16):动画持续时间,以毫秒为单位。其含义因组件而异。例如,文本区域光标闪烁时间或滚轮滚动时间。更多详情参见 组件 文档。
  • image_opa(可选,opacity):设置图像的透明度。
  • image_recolor(可选,color):与图像的每个像素混合的颜色。注意 image_recolor_opa 默认为 TRANSP,因此也必须设置它。
  • image_recolor_opa(可选,opacity):图像重新着色的透明度。
  • recolor(可选,color):与组件混合的颜色。默认为 0(黑色)。注意 recolor_opa 默认为 TRANSP,因此也必须设置它。
  • recolor_opa(可选,opacity):设置颜色混合的强度。中间值产生半透明效果。
  • outline_width(可选,int16):以像素为单位设置轮廓宽度。它像边框一样,但绘制在矩形外部。默认为 0。
  • outline_color(可选,color):用于绘制组件轮廓的颜色。默认为 0(黑色)。
  • outline_opa(可选,opacity):组件轮廓的透明度。默认为 COVER。
  • outline_pad(可选,int16):轮廓与组件本身之间的距离。默认为 0。
  • pad_all(可选,int16):在所有方向上设置内边距,以像素为单位。它使内容区域在所有方向上变小。
  • pad_top(可选,int16):在顶部设置内边距,以像素为单位。它使内容区域在该方向上变小。
  • pad_bottom(可选,int16):在底部设置内边距,以像素为单位。它使内容区域在该方向上变小。
  • pad_left(可选,int16):在左侧设置内边距,以像素为单位。它使内容区域在该方向上变小。
  • pad_right(可选,int16):在右侧设置内边距,以像素为单位。它使内容区域在该方向上变小。
  • pad_row(可选,int16):设置子元素行之间的内边距,以像素为单位。详情参见 布局。
  • pad_column(可选,int16):设置子元素列之间的内边距,以像素为单位。详情参见 布局。
  • pad_radial(可选,int16):将文本标签从刻度刻度/组件部分余量中移开。
  • margin_top(可选,int16):在顶部设置外边距。在布局中,组件将与其同级元素保持此间距。
  • margin_bottom(可选,int16):在底部设置外边距。在布局中,组件将与其同级元素保持此间距。
  • margin_left(可选,int16):在左侧设置外边距。在布局中,组件将与其同级元素保持此间距。
  • margin_right(可选,int16):在右侧设置外边距。在布局中,组件将与其同级元素保持此间距。
  • shadow_color(可选,color):用于在组件矩形下方创建阴影的颜色。默认为 0(黑色)。
  • shadow_offset_x(可选,int16):阴影的水平偏移量,以像素为单位。默认为 0。
  • shadow_offset_y(可选,int16):阴影的垂直偏移量,以像素为单位。默认为 0。
  • shadow_opa(可选,opacity):阴影的透明度。默认为 COVER。
  • shadow_spread(可选,int16):阴影的扩散量,以像素为单位。默认为 0。
  • shadow_width(可选,int16):阴影的宽度,以像素为单位。默认为 0。
  • drop_shadow_opa(可选,opacity):截取组件的一部分并模糊它。设置阴影的透明度。默认为 0。
  • drop_shadow_radius(可选,int16):设置模糊的强度。在渲染子组件之前,分别应用于每个组件部分。默认为 0。
  • drop_shadow_offset_x(可选,int16):在 X 方向上设置阴影的偏移量(像素)。默认为 0。
  • drop_shadow_offset_y(可选,int16):在 Y 方向上设置阴影的偏移量(像素)。默认为 0。
  • drop_shadow_color(可选,color):设置阴影的颜色。默认为 0(黑色)。
  • drop_shadow_quality(可选):可选 AUTO、SPEED、PRECISION。设为 SPEED 时,模糊算法将优先保证速度而非质量。PRECISION 将强制使用更高质量但更慢的模糊。AUTO 将自动选择质量。默认为 PRECISION。
  • transform_rotation(可选,0-360):组件的变换旋转角度。
  • transform_width(可选,int16 或 percentage):以该值在两侧拉伸组件宽度。百分比值相对于组件的宽度。
  • transform_height(可选,int16 或 percentage):以该值在两侧拉伸组件高度。百分比值相对于组件的高度。
  • transform_pivot_x(可选,int16):变换的水平锚点。相对于组件的左上角。
  • transform_pivot_y(可选,int16):变换的垂直锚点。相对于组件的左上角。
  • transform_scale(可选,0.1-10):组件的变换缩放(均匀缩放)。
  • transform_scale_x(可选,0.1-10):水平缩放组件。
  • transform_scale_y(可选,0.1-10):垂直缩放组件。
  • transform_skew_x(可选,0-360):以角度水平倾斜组件。
  • transform_skew_y(可选,0-360):以角度垂直倾斜组件。
  • translate_x(可选,int16 或 percentage):以该值在水平方向移动组件。百分比值相对于组件的宽度。在布局、对齐和其他定位之后应用。
  • translate_y(可选,int16 或 percentage):以该值在垂直方向移动组件。百分比值相对于组件的高度。在布局、对齐和其他定位之后应用。
  • translate_radial(可选,int16 或 percentage):以该值沿父对象中心移动组件对象(例如,沿刻度圆周一圈)。

NOTE

属性名称 transform_angle、transform_zoom、shadow_ofs_x 和 shadow_ofs_y 已弃用。请分别使用 transform_rotation、transform_scale、shadow_offset_x 和 shadow_offset_y。

组件的各个部分(如背景、边框等)支持透明度。可以通过以下几种方式指定:

  • 作为字符串:TRANSP 表示完全透明,COVER 表示完全不透明
  • 作为 0.0-1.0 范围内的浮点值
  • 作为 0% 到 100% 之间的百分比。
  • 从 lambda 中返回 0-255 范围内的整数。

默认值取决于组件的具体特性。

LVGL 配置中的任何位置都可以指定颜色,可以通过引用预先配置的 ESPHome 颜色 ID,或者使用常见的十六进制表示法。例如,0xFF0000 表示红色。

你也可以使用任何 标准 CSS 颜色名称,例如 springgreen。

当使用 lambda 提供颜色时,可以使用 lv_color_hex 函数将十六进制值转换,或返回 Color ID——这在使用 映射 时很有用。示例:

# 通过 Lambda 直接设置颜色的示例
- label:
id: my_label
text: 'Hello World!'
text_color: !lambda return lv_color_hex(0xFF0000);

渐变是一系列颜色,可以通过 bg_grad 样式选项应用于对象。渐变在 LVGL 配置的 gradients 部分中定义,通过提供两个或更多颜色停止点。每个条目具有以下选项:

  • id(必需,ID):以后将用于引用渐变的 ID。
  • direction(必需,string):渐变的方向:hor(或 horizontal)或 ver(或 vertical)。
  • stops(必需,list):至少 2 个颜色停止点的列表。每个停止点具有以下选项:
    • color(必需,Color):停止点的颜色。
    • opa(可选,opacity):此停止点的透明度。默认为 COVER(完全不透明)。
    • position(必需,float):停止点的位置。必须是 0.0 到 1.0 之间的浮点数、0% 到 100% 之间的百分比,或 0 到 255 之间的整数。
# 展示完整色相范围的渐变示例。
lvgl:
...
gradients:
- id: color_bar
direction: hor
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

有两种字体选择:

你可以使用正常配置的字体,字形将在构建二进制文件时渲染。其优势在于你可以定义任意大小的自定义字符合集,包含你选择的图标或变音符字符,适用于任何语言,来源于任何 TrueType/OpenType 字体,从而可以更优化地使用闪存空间,因为你不需要包含你希望使用的所有大小的所有字形。

TIP

为获得最佳效果,请设置 bpp: 4 以使用适当的抗锯齿功能渲染字形。

查看食谱中的 文本中的 MDI 图标、切换状态图标按钮 和 电池状态图标,这些示例展示了如何使用 TrueType/OpenType 字体配合图标和文本。

LVGL 库默认提供预渲染的字符集,包含 ASCII 字符(0x20-0x7F)、度数符号(0xB0)、项目符号(0x2022)(来自 Montserrat Medium),以及来自 FontAwesome 的 60 个符号(见下文)。在指定 text_font 参数时可以使用以下 ID:

  • montserrat_8:8px 字体
  • montserrat_10:10px 字体
  • montserrat_12:12px 字体
  • montserrat_14:14px 字体(默认,如果缺少 default_font 选项则包含)
  • montserrat_16:16px 字体
  • montserrat_18:18px 字体
  • montserrat_20:20px 字体
  • montserrat_22:22px 字体
  • montserrat_24:24px 字体
  • montserrat_26:26px 字体
  • montserrat_28:28px 字体
  • montserrat_30:30px 字体
  • montserrat_32:32px 字体
  • montserrat_34:34px 字体
  • montserrat_36:36px 字体
  • montserrat_38:38px 字体
  • montserrat_40:40px 字体
  • montserrat_42:42px 字体
  • montserrat_44:44px 字体
  • montserrat_46:46px 字体
  • montserrat_48:48px 字体

固件仅在配置中使用了上述字体时才包含它们。

你可以通过 \u 前缀的码点地址在文本中显示嵌入的符号。例如:\uF00C:

NOTE

text_font 参数影响符号的大小,因为所有基于 Montserrat 的内置字体数组都在各自大小包含这些符号。如果在组件上将 text_font 设为自定义的 ESPHome 字体,这些符号可能无法显示,除非你手动从 FontAwesome OpenType 文件中包含它们。

要使转义序列生效,必须将它们放在用双引号括起来的字符串中。

除上述外,LVGL 还提供以下特殊内置字体:

  • unscii_8:8 px 完美像素字体,仅含 ASCII 字符。
  • unscii_16:16 px 完美像素字体,仅含 ASCII 字符。
  • simsun_16_cjk:16 px 字体,包含正常范围 + 1000 个最常见的 CJK 部首。
  • dejavu_16_persian_hebrew:16 px 字体,包含正常范围 + 希伯来语、阿拉伯语、波斯语字母及其所有形式。

你可以在顶层使用 theme: 配置变量配置全局主题。

  • dark_mode(可选,boolean):启用 LVGL 内置的深色默认主题,该主题自动为所有组件应用深色配色方案(深色背景、浅色文本)。默认为 false。
# 示例:启用深色主题
lvgl:
theme:
dark_mode: true

你还可以将默认样式应用于给定类型的所有组件。在下面的示例中,所有 arc、slider 和 button 组件将默认使用在此定义的样式和属性。可以为每个组件选择样式和状态的组合。这些每个组件的样式与 dark_mode 配合使用——你可以启用深色主题,仍然可以覆盖特定组件的样式。

# 主题配置条目示例
lvgl:
theme:
dark_mode: true
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

当然,你可以在每个组件的单独配置级别覆盖这些设置。这可以通过使用主组件的 style_definitions 配置变量批量完成。 在下面的示例中,你定义了 date_style:

# 样式定义配置条目示例
lvgl:
...
style_definitions:
- id: date_style # 为你的定义选择一个 ID
text_font: unscii_8
align: center
text_color: 0x000000
bg_opa: cover
radius: 4
pad_all: 2

然后你将这些选定的样式应用到两个标签,并且仅局部更改特定样式 y:

# 样式定义应用示例
widgets:
- label:
id: day_label
styles: date_style # 通过上面选择的 ID 在此应用定义
y: -20
- label:
id: date_label
styles: date_style
y: +20

此外,你还可以根据组件或其部分的状态属性更改样式。如果你想为所有状态设置属性(例如红色背景颜色),只需在组件的根级别为默认状态设置即可。如果组件找不到当前状态的属性,它将回退到此处。

在下面的示例中,你有一个设置了某些样式的 arc。注意如何根据状态更改 indicator 部分的 arc_color:

# 基于状态更改样式示例
- arc:
id: my_arc
value: 75
min_value: 1
max_value: 100
adjustable: true
indicator:
arc_color: 0xF000FF
pressed:
arc_color: 0xFFFF00
focused:
arc_color: 0x808080

因此优先级是这样的:基于状态的样式覆盖局部指定的样式,后者覆盖样式定义,后者覆盖主题,后者覆盖顶层样式。状态的优先级非常直观,用户会自然地期望它。例如,如果组件被聚焦,用户仍然希望看到它是否被按下,因此按下状态的优先级更高。(如果聚焦状态的优先级更高,它将覆盖按下颜色,从而使其目的落空。)

请随意实验,以发现嵌套组件之间基于状态的样式继承和优先级。

食谱中的 主题和样式定义 包含一个示例,展示了如何为组件实现渐变样式。

大多数 LVGL 样式和组件属性可以设为常数值或 lambda(将在运行时求值)。使用 lambda 时,返回值必须与原生 LVGL 库预期的类型和范围一致,这可能不同于 YAML 中使用的类型。这尤其适用于任何表示为浮点数的值——LVGL 库不使用浮点数,而是使用缩放整数。具有以下原生类型的属性需要注意:

  • opacity LVGL 透明度是 0 到 255 之间的整数。
  • angle LVGL 角度以 1/10 度表示,通常在 0 - 3600 范围内。
  • color LVGL 使用内部颜色类型——在 lambda 中构造颜色请使用 lv_color_hex(0xRRGGBB)。
  • scale 缩放级别应乘以 256(有效范围为 0 到 2560,对应于 0-10.0)。
  • percentage 要将小数值转换为百分比,请使用 lv_pct(value * 100)

LVGL 支持一组组件,可用于在屏幕上绘制交互式对象。

组件支持通用或特定的操作——更多详情参见 组件 部分。

LVGL 组件本身还提供了几个操作,下面进行了概述。注意,如果配置了多个 LVGL 实例,则需要 lvgl_id 配置条目来指定操作关联的实例。如果仅配置了一个 LVGL 实例,则不需要。

此操作允许在运行时更改/更新样式的属性。可用于实现动态主题(如浅色/深色模式),或根据用户交互更改组件的外观。

该操作接受一个样式 ID 和一个要更新的属性字典。这些属性可以是上面列出的任何样式属性,也可以是常量或 lambda。

# 示例配置条目
lvgl:
...
style_definitions:
- id: my_style
bg_color: 0xFFFFFF
border_color: 0x000000
border_width: 2
# 更新样式的操作
on_...:
- lvgl.style.update:
id: my_style
bg_color: 0xFF0000
border_color: 0x00FF00

此操作暂停 LVGL 的活动,包括渲染。

  • show_snow(可选,boolean):暂停时,在整个屏幕上显示随机颜色的像素,以最小化屏幕烧屏,缓解每个像素的应力。查看 防止 LCD 烧屏 以了解如何使用此功能的示例。
  • lvgl_id(可选):要暂停的 LVGL 实例的 ID。
on_...:
- lvgl.pause:
show_snow: true

此操作恢复 LVGL 的活动,包括渲染。

  • lvgl_id(可选):要恢复的 LVGL 实例的 ID。
on_...:
- lvgl.resume:

此操作旋转 LVGL 显示。

  • rotation(必需,templatable,int):旋转显示的角度。有效值为 0、90、180 和 270。注意角度是绝对的,不是相对的,因此显示的当前旋转不会影响结果。使用 lambda 时,必须返回以度为单位的角度。
  • lvgl_id(可选):要旋转的 LVGL 实例的 ID。
on_...:
- lvgl.display.set_rotation: 90
# 或使用返回角度(度数)的 lambda:
- lvgl.display.set_rotation: !lambda "return id(my_rotation_number).state;"

此操作允许在运行时更改/更新活动屏幕和 LVGL 显示层的样式和布局。顶层样式属性和 layout: 适用于当前活动屏幕;你还可以对 top_layer 和/或 bottom_layer 进行样式设置和布局。

  • layout(可选):更新活动屏幕的布局选项。只能更改布局选项,不能更改布局类型。
  • top_layer / bottom_layer(可选):更新相应显示层的样式属性和 layout:。
# 示例:
on_...:
- lvgl.update:
bottom_layer:
bg_color: 0x0000FF
bg_opa: cover
- lvgl.update:
top_layer:
opa: 0.5
- lvgl.update:
layout:
flex_flow: column

lvgl.page.next / lvgl.page.previous 操作

Section titled “lvgl.page.next / lvgl.page.previous 操作”

此操作根据配置将页面更改为下一个/上一个(启用了 skip 选项的页面将被跳过)。页面更改将在末尾循环。

  • animation(可选):按指定方式为页面更改设置动画。可选: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。默认为 NONE。
  • time(可选,Time):页面更改动画的持续时间。默认为 50ms。
on_...:
- lvgl.page.next:
animation: OUT_LEFT
time: 300ms
on_...:
- lvgl.page.previous:
animation: OUT_RIGHT
time: 300ms

此操作显示特定页面(包括启用了 skip 选项的页面)。

  • id(必需):要显示的页面的 ID。
  • animation(可选):按指定方式为页面更改设置动画。可选: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。默认为 NONE。
  • time(可选,Time):页面更改动画的持续时间。默认为 50ms。
on_...:
- lvgl.page.show:
id: secret_page
on_...:
- lvgl.page.show: secret_page # 简写形式

lvgl.animation.start / lvgl.animation.stop 操作

Section titled “lvgl.animation.start / lvgl.animation.stop 操作”

启动或停止一个或多个随时间更改组件样式属性的动画。更多详情参见 LVGL 动画。

此条件检查自上次触摸事件以来是否已过去指定时间。

  • timeout(必需,templatable,int):自上次触摸事件以来预期的时间。
  • lvgl_id(可选):要监控的 LVGL 实例的 ID。
# In some trigger:
on_...:
- if:
condition:
lvgl.is_idle:
timeout: 5s
then:
- light.turn_off:
id: display_backlight
transition_length: 3s

此条件检查 LVGL 是否处于暂停状态。

  • lvgl_id(可选):要监控的 LVGL 实例的 ID。
# In some trigger:
on_...:
- if:
condition: lvgl.is_paused
then:
- lvgl.resume:

此条件检查指定页面是否为当前显示的页面。

  • id(必需):要检查的页面的 ID。可以作为简单值提供。
# In some trigger:
on_...:
- if:
condition:
lvgl.page.is_showing: main_page
then:
- logger.log: "Main page is showing"

除组件级别的交互触发器外,LVGL 组件本身还提供几个触发器:

LVGL 有屏幕非活动的概念——即跟踪自上次用户与屏幕交互以来的时间。例如,这可以用于在一段时间不活动后调暗或关闭显示背光(就像屏幕保护程序)。每次使用输入设备(触摸屏、旋转编码器)都算作一次活动,并重置非活动计数器。

当非活动时间超过指定的 timeout 时,on_idle 触发器 将被激活。你可以配置任意数量的具有不同操作的超时。

  • timeout(必需,templatable,int):自上次触摸事件以来经过的时间,之后将调用触发器。
lvgl:
...
on_idle:
- timeout: 30s
then:
- lvgl.page.show: main_page
- timeout: 60s
then:
- light.turn_off: display_backlight
- lvgl.pause:

查看 空闲时关闭屏幕 以了解如何使用空闲设置实现屏幕保护的示例。

此触发器在 LVGL 暂停时触发。可用于在屏幕锁定时执行任何所需操作,例如关闭显示背光。

此触发器在 LVGL 恢复时触发。可用于在屏幕解锁时执行任何所需操作,例如打开显示背光。

此触发器在 LVGL 设置完成后触发。它在 lvgl 组件和任何组件上均可用,可用于执行无法通过静态配置完成的任何与 LVGL 相关的设置。在组件上使用它时,它并不专门作用于该组件,但可用于将与该组件相关的操作与其配置放在一起。

此触发器在每次 LVGL 绘制操作之前执行。

此触发器在 LVGL 完成绘制所有更新的屏幕元素后执行。它可用于例如触发显示组件(如电子墨水屏)的更新,该组件需要将缓冲区发送到显示才能更新。

lvgl:
on_draw_end:
- component.update: my_display_id

当显示方向改变时,这些触发器触发, 由显示的有效宽高比确定:当显示宽度大于高度时触发 on_landscape(方形显示被视为横向),当显示高度大于宽度时触发 on_portrait。 匹配的触发器在启动时也会触发一次以建立初始方向。随后的更改通常由 lvgl.display.set_rotation 操作引起。

lvgl:
on_landscape:
- logger.log: Display is now landscape
on_portrait:
- logger.log: Display is now portrait
  • on_invalidate_area:区域无效化(标记为重新绘制)时发生。
  • on_resolution_change:显示分辨率改变时发生。
  • on_color_format_change:显示颜色格式改变时发生。
  • on_refr_request:发生需要重新绘制的事情时发生。
  • on_refr_start:刷新周期开始前发送。
  • on_refr_ready:刷新完成时发送。
  • on_render_start:渲染开始前发送。
  • on_render_ready:渲染完成时发送。
  • on_flush_start:刷新回调被调用前发送。
  • on_flush_finish:刷新回调返回后发送。
  • on_flush_wait_start:刷新等待回调被调用前发送。
  • on_flush_wait_finish:刷新等待回调返回后发送。
  • on_update_layout_complete:布局更新完成时发送。
  • on_vsync:垂直同步事件。
  • on_vsync_request:垂直同步请求。