LVGL官方文档解读笔记---核心基础
这个笔记不总结具体控件,只讲述核心原理
本来对GUI编程有一些基础,然后参照网上LVGL的琐碎代码,也可以做出来一些小界面,但对于很多概念还是很模糊,故开此笔记对LVGL官方文档进行学习记录,以便于搞清一些基本概念和操作方法。
工作流
用户APP通常包括两个逻辑:UI逻辑和时间逻辑,UI逻辑表示用户创建了哪些控件,并对这些控件做了哪些样式和属性的修改,对这些控件做了哪些事件的绑定。时间逻辑用于向LVGL提供时间基准。
(1) 数据流
LVGL内部在时间基准的驱动下,通过lv_timer_handler()这个函数对整个图形界面进行更新。首先决定哪些控件需要被渲染(例如,E,G,H)。然后渲染逻辑负责进行渲染把控件由逻辑形态转化成像素形态,放进缓冲区,最后写进LCD面板的帧缓冲区。
(2) 事件流
事件触发的源头是输入设备,一次按键点击,一次触摸点击。输入设备驱动将原始的硬件输入转换成lvgl内部格式(lv_indev_data_t )。输入管理将lv_indev_data_t 中的输入内容(坐标,按键)转化成事件(单击,双击)。并将这些事件插入队列进行排队处理,在时间基驱动下定时处理。然后,事件目标定位通过坐标或者是当前聚焦项确定是哪个控件响应事件。最后,就会调用该控件的事件回调函数,处理业务逻辑,并进行UI更新,最终触发渲染更新。这就是事件驱动GUI的基本过程。
显示设备 vs 屏幕 vs 层
LVGL 的显示系统通过 显示设备(Display)、层(Layers)、屏幕(Screen) 三者配合,实现「多设备支持、分层渲染、多 UI 页面切换」的能力,关系可总结为:
- Display:硬件显示的抽象(如 TFT 屏),是 LVGL 与物理屏幕交互的 “桥梁”,支持多图层叠加。
- Layers:Display 内的逻辑分层(优先级从低到高:底层→活跃 Screen 层→顶层→系统层),上层内容可覆盖下层。
- Screen:UI 页面的 “根控件”,需挂载到某一层(通常是「活跃 Screen 层」),同一时刻一个层内仅一个 Screen “活跃显示”。
显示设备(Display):硬件的抽象载体
- 作用:代表实际显示硬件(如 TFT/LCD 屏),负责 “缓冲区→物理屏幕” 的数据推送。
- 多设备支持:LVGL 可同时管理多个 Display(如双屏显示场景),每个 Display 独立配置分辨率、刷新回调等。
- 关键 API:
// 创建 Display(指定分辨率) lv_display_t *disp = lv_display_create(480, 320); // 绑定“缓冲区→硬件”的刷新回调(需用户实现硬件驱动逻辑) lv_display_set_flush_cb(disp, my_display_flush); // 获取默认 Display(单屏场景可直接用) lv_display_t *default_disp = lv_display_get_default();
屏幕(Screen):UI 页面的 “根节点”
1.创建
Screen 是控件树的根节点(本质是特殊控件),代表一个 “独立 UI 页面”,核心特点:调用控件创建函数时,父对象传 NULL 即可创建 Screen(可基于 lv_obj、lv_image 等控件实现):
// 示例1:用基础控件创建“空白页面”
lv_obj_t *scr_main = lv_obj_create(NULL);
// 示例2:用图像控件创建“带背景图的页面”
lv_obj_t *scr_bg = lv_image_create(NULL);
lv_image_set_src(scr_bg, "S:/bg_img.bin"); // 设置背景图像
2. 活跃与切换
同一时刻,Display 的「活跃 Screen 层」仅能显示 一个活跃 Screen,切换需用专用 API:
- 带动画切换:
// 淡入动画切换,时长500ms,无延迟,不自动删除旧 Screen lv_screen_load_anim(scr_new, LV_SCREEN_LOAD_ANIM_FADE, 500, 0, false); - 自动删除旧 Screen:
// 切换后自动删除原活跃 Screen(节省内存) lv_screen_load_anim(scr_new, LV_SCREEN_LOAD_ANIM_SLIDE_LEFT, 500, 0, true);
3. 限制与删除
- Screen 会自动铺满对应 Display,无法手动修改尺寸(
lv_obj_set_size)或位置(lv_obj_set_pos)。 - 不能直接删除活跃中的 Screen,需先切换到其他 Screen,再用
lv_obj_delete(scr_old)删除。
层(Layers):分层渲染
每个 Display 内置 4 个逻辑层(优先级从低到高),上层可覆盖下层,适合不同场景:
| 层级 | 优先级 | 典型场景 |
|---|---|---|
| 底层(Bottom) | 最低 | 显示背景级内容(如视频、底图) |
| 活跃 Screen 层 | 中 | 显示当前活跃 Screen 的 UI 内容 |
| 顶层(Top) | 次高 | 显示临时弹窗(如提示框、半透菜单) |
| 系统层(System) | 最高 | 显示系统级覆盖(如状态栏、紧急提示) |
获取层的 API
lv_display_t *disp = lv_display_get_default();
lv_obj_t *layer_bottom = lv_display_get_layer_bottom(disp); // 底层
lv_obj_t *layer_screen = lv_display_get_screen_active(disp); // 活跃Screen所在层
lv_obj_t *layer_top = lv_display_get_layer_top(disp); // 顶层
lv_obj_t *layer_sys = lv_display_get_layer_sys(disp); // 系统层
应用
-
多 Screen 切换(空间换时间):若需频繁切换 UI 页面(如 “主界面→设置→关于”),可提前创建所有 Screen 并保存在 RAM 中,切换时用
lv_screen_load快速切换 —— 避免重复创建控件树的开销,用内存换性能。 -
分层叠加(场景化显示):
- 视频播放:底层显示视频,活跃 Screen 层显示 “播放控制条”,顶层备用 “暂停弹窗”;
- 车载 UI:底层显示地图,活跃 Screen 层显示 “导航控件”,系统层显示 “车速状态栏”。
控件(Widget)
控件是图形界面的核心,APP使用控件构建静态和动态显示以及人机交互。包括进度条,按钮,标签,复选框。APP创建控件树,lvgl就会渲染并显示出来这些控件。
基础控件(Base Widget)
基础控件:是拥有基本特性的控件,其他所有控件都基于基础控件又添加了一些特性。对了这里补充一点,基础控件不仅被当做根节点使用,它还被当做容器使用,把几个控件进行组合。
//创建水平容器
lv_obj_t * cont_row = lv_obj_create(parent);
lv_obj_set_size(cont_row, 210, 25);
lv_obj_align(cont_row, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_flex_flow(cont_row, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(cont_row, LV_FLEX_ALIGN_SPACE_AROUND, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
//创建文本标签
lv_obj_t *label = lv_label_create(cont_row);
lv_label_set_text(label, txt);
lv_obj_set_style_text_font(label, &lv_font_montserrat_12, 0);
//创建滑块
lv_obj_t* slider = lv_slider_create(cont_row);
lv_obj_set_size(slider, 100, 5);
lv_slider_set_range(slider, min, max);
lv_slider_set_value(slider, val, LV_ANIM_OFF);
如上面代码所示,使用基础对象最为容器,把标签和滑块组合成一个整体。
基础属性 VS 特有属性
基础属性:每个控件都有的属性Position,Size,Parent,Styles,Events it emits,Flags like Clickable, Scollable, etc.,Etc.
lv_obj_set_size(btn1, 100, 50);
lv_obj_set_pos(btn1, 20,30);
如上代码,使用lv_obj_set可以设置这些基本属性,使用lv_obj_get可以获得这些属性,这些函数可以作用于所有的控件。
控件所独有的属性:比如滚动条(slider)拥有maxvalue,minvalue,current value。
lv_slider_set_range(slider1, 0, 100);
lv_slider_set_value(slider1, 40, LV_ANIM_ON);
上面的函数可以进行这些属性的设置,这些函数是滚动条独有的函数,只能作用于滚动条。
控件的创建和删除
在lvgl运行过程中,所有的控件对象都可以被动态地创建和删除。这使得APP可以在按钮按下时,可以动态地创建一个Screen,然后并加载这个Screen到显示设备上。在不需要的时候这个Screen删除掉,然后并创建其他Screen,以节省内存。
lv_obj_t * lv_<widget>_create(lv_obj_t * parent, <other parameters if any>);
如上,每一个控件都有其独特的创建函数,传入父对象,以及其他属性参数。
void lv_obj_delete(lv_obj_t * widget);//立即删除
void lv_obj_delete_async(lv_obj_t *obj);//异步删除
void lv_obj_delete_delayed(lv_obj_t *obj, uint32_t delay_ms);//延迟删除
删除的时候都用同一函数删除,分别为立即删除,异步删除和延迟删除函数。异步删除是在lvgl的下一个处理周期再进行删除,应用场景:比如说,要在一个控件的回调函数里删除父控件,则不能立即删除(这里我也不理解是什么意思)。延时删除就是等一个时间再删除。void lv_obj_clean(lv_obj_t *obj)可以清除一个父控件的所有子对象控件。注意在删除一个控件之前将其指针指向空。
父控件 VS 子控件
除了Screen以外,我们创建其他所有的控件必须有父对象,通过创建函数传入。① 使用 lv_obj_get_parent(widget)可以获取一个控件的父对象;②使用 lv_obj_set_parent(widget)(widget, new_parent) 可以设置一个控件的父对象;③ 使用 lv_obj_get_child(parent,idx) 可以获得一个控件的子对象。idx传入0获得第一个创建的子对象,传入1获得第二个创建的子对象。传入-1获得最后一次创建的子对象。
uint32_t i;
for(i = 0; i < lv_obj_get_child_count(parent); i++) {
lv_obj_t * child = lv_obj_get_child(parent, i);
/* Do something with child. */
}
可以使用上述代码遍历一个控件的所有子对象。④ lv_obi_get_index(widget) 可以返回一个控件在它父控件中的索引,也就是说我们 可以知道这个控件是第几个创建的。⑤ lv_obi_move_foreground(widget) 和 lv_obi_move_background(widget) 可以将控件分别放到前景或者背景。⑥ 使用 lv_obj_move_index(widget,index) 可以移动一个控件在其父控件中的索引位置。⑦使用lv_obj_swap(widgte1,widget2)可以交换两个控件的位置。⑧使用lv_obj_get_screen(widget) 可以获取根节点控件即SCreen。
父对象可以被看做子对象的一个容器,主要表现在3个方面:① 子对象的尺寸超过了父对象将会被裁剪。② 父对象移动,子对象会跟着移动。③ 子对象被删除父对象还存在,父对象被删除其所有子对象必然会被删除。任何的控件都可以当做子对象也可以当做父对象,但是有些常用的父子控件搭配:
lv_obj_t * btn1 = lv_button_create(lv_screen_active());
lv_obj_t * label = lv_label_create(btn1);
lv_label_set_text(label, "按钮");
lv_obj_align(btn1, LV_ALIGN_CENTER,0,0);
lv_obj_center(label);

如上图就是标签常常用作按钮的子控件,以标识按钮的名字。
此小结只讲基础控件的特性,即阐述所有控件所通用的特性和概念。
按钮,滚动条,标签啦等各种控件的创建函数不同,但都返回一个 lv_obj_t,利用这个指针可以完成对控件属性的设置,比如风格,事件回调函数等。基础控件通俗第来说就是一个矩形,拥有所有控件的基本特性。用面向对象的观点看:基本控件是所有控件的父类。所有用于基础控件的函数都可用于其他控件,例如 lv_obj_set_width(slider,100)。
部件(Parts)
一个控件由一个部件或者多个部件组成,比如:一个按钮只有一个部件,叫做LV_PART_MAIN。一个滑动条有三个部件:LV_PART_MAIN,LV_PART_INDICATOR,LV_PART_KNOB。使用部件可以对一个控件的子元素风格进行单独设置,或使用特定的子元素触发回调函数。常见部件如下:
状态(States)
指的是一下单一状态的组合
选中状态与聚焦状态的区别:聚焦是针对整个控件来说的,比如使用鼠标滑过不同的按钮,这几个按钮就会依次被聚焦,聚焦到哪个按钮哪个按钮就可以被点击。而选中指的是控件子元素的选中,比如选中复选框里面的某个选项。
lv_obj_has_state(widget, LV_STATE_...)
以上API用于判断按钮处于哪个状态。
lv_obj_add_state(widget, LV_STATE_...);
lv_obj_remove_state(widget, LV_STATE_...);
以上API用于给控件添加控件或者移除控件的某个状态。
这里一定要搞清楚状态与事件的区别,他们不是一个东西,控件只有在某些状态下才会发送事件,调用回调函数。比如按钮按下状态的一瞬间会发送事件,然后滚动条滚动状态也会发送事件。
风格(Styles)
风格服务GUI系统的静态和动态显示。前面的事件和状态是为了人机交互,那么风格就是为了美观。我们都知道,控件有各种属性:背景,前景,边界宽度,字体等。风格就是这些属性值的集合,用来设置这些属性。风格以风格对象(lv_style_t)的形式在MCU内存中存在,方便我们快速设置不同控件的属性。
static lv_style_t style1;
lv_style_init(&style1);
lv_style_set_bg_color(&style1, lv_color_hex(0xa03080));
lv_style_set_border_width(&style1, 2));
lv_obj_add_style(obj, &style, 0);
其使用流程为上:创建风格对象--->设置属性---->给控件添加风格! LVGL 风格的设置灵活且强大:
lv_obj_add_style(slider1, &style1, LV_PART_INDICATOR | LV_STATE_PRESSED);
lv_obj_add_style(slider1, &style1, LV_PART_INDICATOR);
lv_obj_add_style(btn1, &style1, 0);
① 为一个控件的某个部件的某个状态设置风格,|左边为部件右边为状态。如上代码,滑动条的指示器(INDICATOR)被按下使用style1(第一行)。如果不传入状态参数那么就是默认状态(LV_STATE_DEFAULT)(第二行)。如果传入0则表示主体LV_PART_MAIN部件的默认状态(第三行)。
② 风格可以级联,可以往一个控件的不同部件或状态分别添加风格。
static lv_style_t style1,style2;
lv_obj_t * slider = lv_slider_create(lv_screen_active());(lv_screen_active());
lv_style_init(&style1);
lv_style_set_border_color(&style1, lv_color_hex(0xFF0000));
lv_style_set_border_width(&style1, 4);
lv_style_init(&style2);
lv_style_set_border_color(&style2, lv_color_hex(0x00FF00));
lv_style_set_border_width(&style2, 4);
lv_obj_add_style(slider, &style1, LV_PART_MAIN|LV_STATE_DEFAULT);
lv_obj_add_style(slider, &style2,LV_PART_KNOB|LV_STATE_PRESSED);;
如上述代码,可以为slider的主体默认状态设置style1,为指示点的按下状态设置style2。
(9) 主题(thems)
主题是风格的集合,一种主题使用在审美上相容的风格去设置不同控件。以上就是lvgl一些核心的概念的简介,接下来将对基础控件进行详细讲解。
标志(Flags)
使用标志可以用于控制控件的某些特性。
/* Hide on Widget */
lv_obj_add_flag(widget, LV_OBJ_FLAG_HIDDEN);
/* Make a Widget non-clickable */
lv_obj_remove_flag(widget, LV_OBJ_FLAG_CLICKABLE);
使用上述API可以添加隐藏标志LV_OBJ_FLAG_HIDEN使得控件隐藏,删除点击标志位LV_OBJ_FLAG_CLICKABLE让控件变得单击无效。下面还有一些标志位:
输入设备VS事件
输入事件
事件是一种机制用来服务GUI系统的人机交互,事件用来通知APP 控件发生了什么(比如控件的移动,点击,释放,删除),然后APP使用回调函数来写事件处理函数。如下所示为事件-回调函数编程模型,跟中断-服务函数编程模型类似。
//按键回调函数
void event_handler(lv_event_t* event)
{
int code = lv_event_get_code(event);//获取事件类型的代码
lv_obj_t* obj=lv_event_get_target(event);//获取事件的对象的地址
lv_obj_t* data=lv_event_get_user_data(event);//获取传输的数据
printf("data:%s\n",data);
if(code == LV_EVENT_CLICKED)
{
printf("this is clicked event\n");//判断是否是点击事件
}
}
//按键Demo
void demo_button(){
char *data = "abcdefg";//要传入的数据
lv_obj_t* screen=lv_scr_act();
lv_obj_t* button=lv_btn_create(screen);
lv_obj_t* label=lv_label_create(button);//创建一个文本对象并将按键对象添加进去
lv_label_set_text(label,"Hello");//添加一个文本
lv_obj_center(button);
//1,按钮控件名 2,回调函数 3,监听什么事件 4,传入什么数据
lv_obj_add_event_cb(button,event_handler,LV_EVENT_CLICKED,data);
}
如上代码 ,lv_obj_add_event_cb(widget,evnthandler,event_type,data)用于给控件添的事件,添加回调函数。其可以传入4个参数,前两个分别为控件和其对应的回调函数。后面是事件类型和要往回调函数内传输的数据,在回调函数内:① 使用 lv_event_get_code(event) 获取事件类型,同一控件的不同事件可以绑定同一个回调函数。② 使用lv_event_get_target(event);来获取调用此回调函数的控件对象,不同控件可以绑定同一个回调函数(call_back);③ 使用lv_event_get_user_data(event);来获取要传递给回调函数的数据(以地址的方式传送)。那么具体都有哪些事件呢?
顾名思义即输入设备触发的事件,比如用手指点击触摸屏,滑动触摸屏,使用鼠标点击,滚动鼠标滚轮等输入设备所触发的事件。支持的事件很多,牛逼的是居然支持触摸屏手势检查。 绘图事件和其他事件这个我不大理解就不往上写了。
事件发送
使用 lv_obj_send_event(obj, <EVENT_CODE>, &some_data) 手动发送事件到对象。例如,这可以用于通过模拟按钮按下来手动关闭消息框。
/*模拟第一个按钮的按下(索引从零开始)*/
uint32_t btn_id = 0;
lv_obj_send_event(mbox, LV_EVENT_VALUE_CHANGED, &btn_id);
对于显示器和输入设备也同样适用: lv_display_send_event(obj, <EVENT_CODE>, &some_data) 和 lv_indev_send_event(obj, <EVENT_CODE>, &some_data)。
刷新事件
LV_EVENT_REFRESH 是一个特殊事件,用户可以使用这个事件通知控件刷新自身。例如,通知标签根据一个或多个变量(例如当前时间)刷新其文本。一般都是LVGL内部自动周期调用。
事件的字段
lv_event_t * e 是传递给事件回调函数的唯一参数,它包含了该事件的所有数据。可以从中获取以下值:
事件冒泡
如果启用了 lv_obj_add_flag(widget, LV_OBJ_FLAG_EVENT_BUBBLE),则所有事件也将发送给Widget的父级。如果父级也启用了 LV_OBJ_FLAG_EVENT_BUBBLE,那么事件将被发送给它的父级,依此类推。使用 lv_event_get_current_target_obj(e)获取的是当前控件,即触发此回调函数的的控件。要获取最初的触发控件,可以在事件处理程序中调用lv_event_get_target_obj(e)。
布局
弹性布局
术语

flex_flow
使用以下函数设置和控制任何父控件上的Flex布局,使用以下函数进行布局设置:设置接口 lv_obj_set_flex_flow(obj, flex_flow),其中 flex_flow 的值可以是:
flex_align
使用 lv_obj_set_flex_align(obj, main_place, cross_place, track_cross_place),来管理子对象的对齐。
main_place: 定义子元素在主轴方向上的对齐方式。 例如。 LV_FLEX_FLOW_ROW_WRAP 上的元素向右刷新。(它在 CSS 中称为 justify-content )
cross_place:定义子元素在交叉轴的对齐方式。 例如。 如果元素具有不同的高度,则将它们放置在轨道的底部。(在 CSS 中称为 align-items )
track_cross_place: 定义多行元素在交叉轴的对齐方式(在 CSS 中称为 align-content )
取值为:

示例:
Flex_grow
Flex grow(弹性增长)使得子对象增长,以填充满轨道上的可用控件。当很多个子对象都有生长参数时,可用空间将按比例分配给生长值。可以使用 lv_obj_set_flex_grow(child, value) 在子节点上设置 Flex 增长值。
(1) 要修改对象之间的间距,可以在 flex 容器上设置以下样式属性:
-
pad_row设置行之间的内边距。 -
pad_column设置列之间的内边距。
使用 lv_style_set_pad_column(&row_container_style, 0)来修改对象之间的间距,可以在 flex 容器上设置以下样式属性。
(2) 可以使用接口 lv_obj_add_flag(child, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK) 强制 Flex 将元素放入新行。
网格布局
术语

网络描述符
要在父级上设置描述符,使用 lv_obj_set_grid_dsc_array (widget, col_dsc, row_dsc)。
使用两个数组来描述网络,一个描述行的个数以及每行的大小,一个描述列的个数以及每列的大小。 数组的最后一个元素必须为:LV_GRID_TEMPLATE_LAST。如下:
static int32_t column_dsc[] = {100, 400, LV_GRID_TEMPLATE_LAST};/* 2 列,宽度分别为 100 像素和 400 像素 */
static int32_t row_dsc[] = {100, 100, 100, LV_GRID_TEMPLATE_LAST};/* 3 行,高度分别为 100 像素 */
除了设置像素大小外,还可以使用两个特殊值:
LV_GRID_CONTENT 设置大小以适应轨道;
LV_GRID_FR(X) 确定使用剩余空间的大小。值越大,占用的空间越大;
网络项
默认情况下,子对象不会添加到网格中。需要手动将它们添加到单元格中,使用
lv_obj_set_grid_cell(child, column_align, column_pos, column_span, row_align, row_pos, row_span) 进行添加。
column_align 和 row_align 决定了子小部件在其单元格中的对齐方式。可能的值有:


column_span 和 row_span 表示从起始单元格开始应该占据多少轨道。必须是 >= 1。
Grid align(对齐方式)
使用 lv_obj_set_grid_align (widget, column_align, row_align) 设置轨道的对齐方式,
如果有一些空余空间,Grid 轨道中的项(Widgets)可以通过以下几种方式对齐:

Sub grid(子网格)
如果您将小部件的列或行网格描述符设置为NULL,它将使用其父级的网格描述符。
lv_obj_t * cont_child = lv_obj_create(cont);
lv_obj_set_style_grid_column_dsc_array(cont_child, NULL, 0);
lv_obj_set_style_grid_row_dsc_array(cont_child, NULL, 0);
滚动
如果一个控件超过了其父对象的范围,其父对象就变得可滚动。子控价可以在一次滑动中水平或垂直滚动。
滚动模式
使用lv_obj_set_scrollbar_mode(widget, LV_SCROLLBAR_MODE_...)可以为Widget设置滚动条模式。

滚动样式
滚动条是控件的一个特殊部件,LV_PART_SCROLLBAR。可以通过以下代码将滚动条设置为红色:
static lv_style_t style_red;
lv_style_init(&style_red);
lv_style_set_bg_color(&style_red, lv_color_red());
lv_obj_add_style(widget, &style_red, LV_PART_SCROLLBAR);
当控件正在被滚动时,会进入LV_STATE_SCROLLED状态。我们可以在滚动期间,为其设置不同样式。例如,以下代码会在Widget滚动时将滚动条设置为蓝色:
static lv_style_t style_blue;
lv_style_init(&style_blue);
lv_style_set_bg_color(&style_blue, lv_color_blue());
lv_obj_add_style(widget, &style_blue, LV_STATE_SCROLLED | LV_PART_SCROLLBAR);
滚动事件
以下事件与滚动相关:

滚动效果
可以使用lv_obj_remove_flag(widget, LV_OBJ_FLAG_SCROLLABLE)使控件不可滚动。滚动发生的方向可以通过lv_obj_set_scroll_dir(widget, LV_DIR_...)进行控制。以下是可用的方向值:

滚动链&滚动惯性
如果一个对象无法进一步滚动(例如已经到达最底部位置),额外的滚动将传递给其父对象。如果在该方向上可以滚动父对象,则父对象将被滚动。它会继续传递给祖父和曾祖父对象。滚动传播被称为“滚动链”,可以使用 LV_OBJ_FLAG_SCROLL_ELASTIC 标志来启用/禁用它。如果禁用了链式滚动,传播将在该对象处停止,并且父对象(们)将不会滚动。
当用户滚动一个Widget并释放时,LVGL可以模拟滚动的惯性动量。就像Widget被“抛出”一样,滚动会平滑地减速。可以通过LV_OBJ_FLAG_SCROLL_MOMENTUM`标志启用或禁用滚动动量。
对齐(snap)
当滚动结束时,Widget的子对象可以根据特定规则对齐(snap)。子对象可以通过设置LV_OBJ_FLAG_SNAPPABLE标志单独启用snap功能。控件可以以以下四种方式对齐其子对象:

可以通过以下方法设置snap对齐方式:lv_obj_set_scroll_snap_x(widget, LV_SCROLL_SNAP_...):设置水平方向的snap。 lv_obj_set_scroll_snap_y(widget, LV_SCROLL_SNAP_...)设置垂直方向的snap。
更多推荐



所有评论(0)