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 屏幕,屏幕是没有父对象的特殊对象。显示上始终有一个活动页面。
一些组件还作为原生 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 组件交互的触摸屏列表。如果配置了一个触摸屏,它将自动使用,无需此配置条目。
- 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 组件交互的键盘列表。
- group(可选,string):将与输入设备交互的组件组名称。有关组的更多信息,请参见组件的公共属性。
- up(可选,ID):用作
UP键的 二进制传感器 的 ID。 - down(可选,ID):用作
DOWN键的 二进制传感器 的 ID。 - right(可选,ID):用作
RIGHT键的 二进制传感器 的 ID。 - left(可选,ID):用作
LEFT键的 二进制传感器 的 ID。 - esc(可选,ID):用作
ESC键的 二进制传感器 的 ID。 - del(可选,ID):用作
DEL键的 二进制传感器 的 ID。 - backspace(可选,ID):用作
BACKSPACE键的 二进制传感器 的 ID。 - enter(可选,ID):用作
ENTER键的 二进制传感器 的 ID。 - next(可选,ID):用作
NEXT键的 二进制传感器 的 ID。 - prev(可选,ID):用作
PREV键的 二进制传感器 的 ID。 - home(可选,ID):用作
HOME键的 二进制传感器 的 ID。 - end(可选,ID):用作
END键的 二进制传感器 的 ID。 - long_press_time(可选,Time):对于键盘,
on_long_pressed交互触发器 被调用前的延迟。默认为400ms。可以使用never禁用。 - long_press_repeat_time(可选,Time):对于键盘,
on_long_pressed_repeat交互触发器 被调用后的重复间隔。默认为100ms。可以使用never禁用。
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):要在页面上绘制的组件 列表。
- 样式属性 的所有其他选项,应用于此页面。
- skip(可选,boolean):使用
- page_wrap(可选,boolean):使用
lvgl.page.next、lvgl.page.previous在页面间导航时,从最后一页循环到第一页。默认为true。 - top_layer(可选,list):一种特殊的”始终置顶”页面,作为放置在其上组件的父对象。它显示在所有页面之上,对于需要始终可见的组件可能很有用。
- bottom_layer(可选,list):一个特殊层,放置在所有页面后面。用于设置显示的背景颜色或图像。取代了已弃用的
disp_bg_color、disp_bg_image和disp_bg_opa选项。 - layout(可选):详情参见 布局。默认为
NONE。 - animations(可选,list):动画 列表,随时间更改组件样式属性。
- 样式属性 的所有其他选项,直接应用于所有组件。
示例:
# 页面配置条目示例lvgl: displays: - my_display pages: - id: main_page widgets: - label: align: CENTER text: 'Hello World!'查看食谱中的 页面导航页脚,该示例展示了如何在屏幕底部实现页面导航栏。
选择缓冲区大小
Section titled “选择缓冲区大小”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 配置
Section titled “多个 LVGL 配置”如果配置了多个显示,并希望每个显示上显示不同的内容,则可以配置多个 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):NONETOPBOTTOMLEFTRIGHTINTERNAL
- 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 个颜色停止点的列表。每个停止点具有以下选项:
# 展示完整色相范围的渐变示例。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有两种字体选择:
ESPHome 字体
Section titled “ESPHome 字体”你可以使用正常配置的字体,字形将在构建二进制文件时渲染。其优势在于你可以定义任意大小的自定义字符合集,包含你选择的图标或变音符字符,适用于任何语言,来源于任何 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因此优先级是这样的:基于状态的样式覆盖局部指定的样式,后者覆盖样式定义,后者覆盖主题,后者覆盖顶层样式。状态的优先级非常直观,用户会自然地期望它。例如,如果组件被聚焦,用户仍然希望看到它是否被按下,因此按下状态的优先级更高。(如果聚焦状态的优先级更高,它将覆盖按下颜色,从而使其目的落空。)
请随意实验,以发现嵌套组件之间基于状态的样式继承和优先级。
食谱中的 主题和样式定义 包含一个示例,展示了如何为组件实现渐变样式。
使用 Lambda 进行样式设置
Section titled “使用 Lambda 进行样式设置”大多数 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 实例,则不需要。
lvgl.style.update 操作
Section titled “lvgl.style.update 操作”此操作允许在运行时更改/更新样式的属性。可用于实现动态主题(如浅色/深色模式),或根据用户交互更改组件的外观。
该操作接受一个样式 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: 0x00FF00lvgl.pause 操作
Section titled “lvgl.pause 操作”此操作暂停 LVGL 的活动,包括渲染。
- show_snow(可选,boolean):暂停时,在整个屏幕上显示随机颜色的像素,以最小化屏幕烧屏,缓解每个像素的应力。查看 防止 LCD 烧屏 以了解如何使用此功能的示例。
- lvgl_id(可选):要暂停的 LVGL 实例的 ID。
on_...: - lvgl.pause: show_snow: truelvgl.resume 操作
Section titled “lvgl.resume 操作”此操作恢复 LVGL 的活动,包括渲染。
- lvgl_id(可选):要恢复的 LVGL 实例的 ID。
on_...: - lvgl.resume:lvgl.display.set_rotation 操作
Section titled “lvgl.display.set_rotation 操作”此操作旋转 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.update 操作
Section titled “lvgl.update 操作”此操作允许在运行时更改/更新活动屏幕和 LVGL 显示层的样式和布局。顶层样式属性和 layout: 适用于当前活动屏幕;你还可以对 top_layer 和/或 bottom_layer 进行样式设置和布局。
# 示例:on_...: - lvgl.update: bottom_layer: bg_color: 0x0000FF bg_opa: cover - lvgl.update: top_layer: opa: 0.5 - lvgl.update: layout: flex_flow: columnlvgl.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: 300mslvgl.page.show 操作
Section titled “lvgl.page.show 操作”此操作显示特定页面(包括启用了 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 动画。
lvgl.is_idle 条件
Section titled “lvgl.is_idle 条件”此条件检查自上次触摸事件以来是否已过去指定时间。
- 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: 3slvgl.is_paused 条件
Section titled “lvgl.is_paused 条件”此条件检查 LVGL 是否处于暂停状态。
- lvgl_id(可选):要监控的 LVGL 实例的 ID。
# In some trigger:on_...: - if: condition: lvgl.is_paused then: - lvgl.resume:lvgl.page.is_showing 条件
Section titled “lvgl.page.is_showing 条件”此条件检查指定页面是否为当前显示的页面。
- id(必需):要检查的页面的 ID。可以作为简单值提供。
# In some trigger:on_...: - if: condition: lvgl.page.is_showing: main_page then: - logger.log: "Main page is showing"除组件级别的交互触发器外,LVGL 组件本身还提供几个触发器:
on_idle 触发器
Section titled “on_idle 触发器”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:查看 空闲时关闭屏幕 以了解如何使用空闲设置实现屏幕保护的示例。
on_pause 触发器
Section titled “on_pause 触发器”此触发器在 LVGL 暂停时触发。可用于在屏幕锁定时执行任何所需操作,例如关闭显示背光。
on_resume 触发器
Section titled “on_resume 触发器”此触发器在 LVGL 恢复时触发。可用于在屏幕解锁时执行任何所需操作,例如打开显示背光。
on_boot 触发器
Section titled “on_boot 触发器”此触发器在 LVGL 设置完成后触发。它在 lvgl 组件和任何组件上均可用,可用于执行无法通过静态配置完成的任何与 LVGL 相关的设置。在组件上使用它时,它并不专门作用于该组件,但可用于将与该组件相关的操作与其配置放在一起。
on_draw_start 触发器
Section titled “on_draw_start 触发器”此触发器在每次 LVGL 绘制操作之前执行。
on_draw_end 触发器
Section titled “on_draw_end 触发器”此触发器在 LVGL 完成绘制所有更新的屏幕元素后执行。它可用于例如触发显示组件(如电子墨水屏)的更新,该组件需要将缓冲区发送到显示才能更新。
lvgl: on_draw_end: - component.update: my_display_idon_landscape / on_portrait 触发器
Section titled “on_landscape / on_portrait 触发器”当显示方向改变时,这些触发器触发,
由显示的有效宽高比确定:当显示宽度大于高度时触发 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显示事件触发器
Section titled “显示事件触发器”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:垂直同步请求。