第六章 LVGL基础知识(6.5~6.8)
6.5 LVGL 滚动属性
在 LVGL 中,任何对象都是支持滚动的。如果一个对象在其父对象的区域之外,则该父对象将变为可滚动的,并且在其内部出现滚动条,如下图所示:

图6.5.1 滚动条的显示
6.5.1 滚动的类型
支持水平滚动和垂直滚动。
6.5.2 滚动条模式
默认情况下,子对象超出父对象的范围区域,则该父对象会自动开启滚动条。如果用户不想开启滚动条,则可以使用lv_obj_set_scrollbar_mode函数设置滚动条的模式,其函数原型如下所示:
void lv_obj_set_scrollbar_mode(lv_obj_t *obj, lv_scrollbar_mode_t mode);
该函数的形参,如下表所示:
表6.5.2.1 lv_obj_set_scrollbar_mode函数形参描述
6.5.3 滚动的事件类型
① LV_EVENT_SCROLL_BEGIN:滚动开始。
② LV_EVENT_SCROLL_END:滚动结束。
③ LV_EVENT_SCROLL:位置变化时触发。
这些滚动事件可以在对象回调函数中获取,相关的使用方法在后文的LVGL事件中有介绍。
6.5.4 设置滚动方向
用户可以调用lv_obj_set_scroll_dir函数设置对象的滚动方向,其函数原型如下所示:
void lv_obj_set_scroll_dir(lv_obj_t *obj, lv_dir_t dir);
该函数的形参,如下表所示:
表6.5.4.1 lv_obj_set_scroll_dir函数形参描述
注意:这些滚动方向允许以组合的形式设置。
6.5.5 滚动的其他特性
1. 滚动传递:
子对象滚动时,如果它的内容已经到达了父对象的最边缘位置,此时,子对象多余的滚动(力量)将被传递到父对象中,而父对象则会发生相应的滚动(假设允许滚动),从而形成滚动链。用户可以使用LV_OBJ_FLAG_SCROLL_CHAIN_HOR/VER标志启用和禁用滚动传递。
2. 滚动惯性:
当用户滚动一个对象并释放它时,LVGL 可模拟滚动的惯性动量,这就像物体被抛出并平稳地减慢滚动速度。用户可以使用LV_OBJ_FLAG_SCROLL_MOMENTUM标志启用和禁用滚动惯性。
3. 弹性滚动:
一般情况下,对象或部件组成部分发生滚动时,其滚动范围不能超过父对象或部件主体的区域。用户可以手动控制内容的位置,让其超出区域限制,而当用户释放内容之后,其将会以动画的形式,回弹到正常的区域范围之内。
6.6 LVGL 动画属性
优秀的过渡动画可以让用户的GUI变得更具高级感。在LVGL中,用户可指定动画的开始值和结束值,该动画将通过回调函数来处理。
6.6.1 创建动画
1. 动画创建流程
这里结合源码给大家介绍LVGL动画的创建流程,源码如下所示:
/* ① 定义动画变量 */ lv_anim_t a; /* ② 初始化一个动画 */ lv_anim_init(&a); /* ③设置动画回调函数 */ lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) lv_obj_set_x); /* ④ 设置动画的目标 */ lv_anim_set_var(&a, obj); /* ⑤ 动画长度[ms] */ lv_anim_set_time(&a, duration); /* ⑥ 设置起始值和结束值。例如0,150 */ lv_anim_set_values(&a, start, end); /* ⑦ 开始动画 */ lv_anim_start(&a);
由上述源码可知, LVGL动画的创建流程共分为七步,如下所示:
① 定义一个lv_anim_t变量。
② 调用函数lv_anim_init初始化动画。
③ 调用函数lv_anim_set_exec_cb设置动画回调函数。
④ 调用函数lv_anim_set_var设置动画执行的目标。
⑤ 调用函数lv_anim_set_time设置动画时间长度。
⑥ 调用函数lv_anim_set_values设置起始值和结束值。
⑦ 调用函数lv_anim_start开始动画。
2. 可选设置:
在创建好动画之后,用户可以选择一些额外的配置,具体可选配置如下源码所示:
/* 可选设置 */ /* 启动动画前的等待时间[ms] */ lv_anim_set_delay(&a, delay); /* 设置路径(曲线)。默认是线性的 */ lv_anim_set_path(&a, lv_anim_path_ease_in); /* 设置一个回调函数来指示动画何时准备好(空闲) */ lv_anim_set_ready_cb(&a, ready_cb); /* 设置一个回调函数来指示动画何时启动(延迟之后) */ lv_anim_set_start_cb(&a, start_cb); /* 准备好后,按此持续时间倒放动画。默认为0(禁用)[ms] */ lv_anim_set_playback_time(&a, time); /* 延迟在回放。默认为0(禁用)[ms] */ lv_anim_set_playback_delay(&a, delay); /* 重复的数量。默认值为1。LV_ANIM_REPEAT_INFINITE用于无限重复 */ lv_anim_set_repeat_count(&a, cnt); /* 重复前延迟。默认为0(禁用)[ms] */ lv_anim_set_repeat_delay(&a, delay); /* True(默认):立即应用起始值,false:延迟后应用起始值。真正的开始 */ lv_anim_set_early_apply(&a, true/false);
注意:在配置可选项之前,必须先创建动画。
6.6.2 设置动画路径
在LVGL中,用户可以控制动画的路径,其中最简单的就是线性变化,这意味着整个动画的过程都是以固定的步长发生变化,目前,LVGL有以下设置动画路径的函数:
① lv_anim_path_linear:线性动画。
② lv_anim_path_step:最后一步改变。
③ lv_anim_path_ease_in:一开始很慢。
④ lv_anim_path_ease_out:最后慢。
⑤ lv_anim_path_ease_in_out:开始和结束都很慢。
⑥ lv_anim_path_overshoot:超出最终值。
⑦ lv_anim_path_bounce:从最终值反弹一点。
上述的动画路径设置函数通常都是以回调的形式传入lv_anim_set_path函数中,该函数原型如下所示:
static inline void lv_anim_set_path_cb(lv_anim_t *a, lv_anim_path_cb_t path_cb);
该函数的形参,如下表所示:

表6.6.2.1 lv_anim_set_path_cb函数形参描述
返回值:无。
6.6.3 设置动画速度
在LVGL中,动画速度指的是开始值到结束值所需的时间。用户需要设置动画速度,可调用lv_anim_speed_to_time函数,该函数原型如下所示:
uint32_t lv_anim_speed_to_time(uint32_t speed, int32_t start, int32_t end);
该函数的形参,如下表所示:

表6.6.3.1 lv_anim_set_path_cb函数形参描述
返回值:给定参数的动画所需的时间[ms]。
在上述的函数中,动画速度以单位/秒来表示,这里的“单位”指的是某个物理量,例如:当用户让对象往 x轴偏移时,上述的“单位”指的就是像素,而入口参数speed的速度就是像素/秒。
注意:该函数的返回值 = (结束值-起始值)/动画速度。
6.6.4 删除动画
如果用户在LVGL运行当中,不需要某个动画了,可使用lv_anim_del函数删除这个动画,其函数原型如下所示:
bool lv_anim_del(void *var, lv_anim_exec_xcb_t exec_cb);
该函数的形参,如下表所示:

表6.6.4.1 lv_anim_set_path_cb函数形参描述
返回值:true:至少删除1个动画;false:不删除动画。
6.6.5 动画实例
下面我们以一个简单的实例来讲解LVGL动画使用流程,示例如下:

图6.6.5.1 动画功能示例
上图中,标签部件(ALIENTEK)从(100,10)坐标开始向左边移动,并在(0,0)坐标上停止,整个过程的时间为5000ms。示例的实现如下源码所示:
/**
* @brief 动画回调函数
* @param var:对象
* @param v:数值
* @retval 无
*/
static void anim_x_cb(void* var, int32_t v)
{
lv_obj_set_x(var, v); /* 在回调函数中更新x轴的值 */
}
void lv_example(void)
{
/* 第一步:创建标签 */
lv_obj_t* lv_obj = lv_label_create(lv_scr_act());
lv_label_set_text(lv_obj,"ALIENTEK");
lv_obj_set_pos(lv_obj, 100, 10);
/* 第二步:动画初始化 */
lv_anim_t a;
lv_anim_init(&a);
/* 第三步:设置动画目标为标签对象 */
lv_anim_set_var(&a, lv_obj);
/* 第四步:设置动画起点和终点 */
lv_anim_set_values(&a, 100, 0);
/* 第五步:设置动画时间 */
lv_anim_set_time(&a, 5000);
/* 第六步:设置动画回调函数 */
lv_anim_set_exec_cb(&a, anim_x_cb);
/* 第七步:设置动画轨道 */
lv_anim_set_path_cb(&a, lv_anim_path_overshoot);
/* 第八步:开启动画 */
lv_anim_start(&a);
}
在上述代码中,动画的回调函数非常重要,它可以适时地更新x轴的像素值,这样才能实现优秀的动画效果。
6.6.6 动画时间线
在LVGL中,动画时间线的设置可以进一步优化动画效果,实现非线性动画。用户可以指定动画时间线的长度、开始时间、重复次数和时间快慢等属性。为了更加方便地实现非线性动画,LVGL将动画时间线分为了多个动画的集合,这样可以较为轻松地创建复杂的动画,示意图如下:

图6.6.6.1 非线性动画示意图
接下来,我们根据上述的示意图,编写动画时间线的实例,如下源码所示:
static lv_anim_timeline_t *anim_timeline = NULL;
static lv_obj_t *obj1 = NULL;
static const lv_coord_t obj_width = 90;
static const lv_coord_t obj_height = 70;
/**
* @brief a1动画回调函数
* @param var:对象
* @param v:数值
* @retval 无
*/
static void set_width(void* var, int32_t v)
{
/* 设置obj1对象宽度 */
lv_obj_set_width((lv_obj_t*)var, v);
}
/**
* @brief a2动画回调函数
* @param var:对象
* @param v:数值
* @retval 无
*/
static void set_height(void* var, int32_t v)
{
/* 设置obj1对象高度 */
lv_obj_set_height((lv_obj_t*)var, v);
}
/**
* @brief 创建时间线
* @param 无
* @retval 无
*/
static void anim_timeline_create(void)
{
/* obj1对象增宽动画 */
lv_anim_t a1;
lv_anim_init(&a1);
lv_anim_set_var(&a1, obj1);
lv_anim_set_values(&a1, obj_width, obj_width + 10 );
lv_anim_set_early_apply(&a1, false);
lv_anim_set_exec_cb(&a1, (lv_anim_exec_xcb_t)set_width);
lv_anim_set_path_cb(&a1, lv_anim_path_overshoot);
lv_anim_set_time(&a1, 300);
/* obj1对象增高动画 */
lv_anim_t a2;
lv_anim_init(&a2);
lv_anim_set_var(&a2, obj1);
lv_anim_set_values(&a2, obj_height, obj_height + 20 );
lv_anim_set_early_apply(&a2, false);
lv_anim_set_exec_cb(&a2, (lv_anim_exec_xcb_t)set_height);
lv_anim_set_path_cb(&a2, lv_anim_path_ease_out);
lv_anim_set_time(&a2, 300);
/* 创建动画时间线 */
anim_timeline = lv_anim_timeline_create();
/* 把a1动画添加到时间线中 */
lv_anim_timeline_add(anim_timeline, 0, &a1);
/* 把a2动画添加到时间线中 */
lv_anim_timeline_add(anim_timeline, 300, &a2);
}
/**
* @brief 按键回调函数
* @param e:事件
* @retval 无
*/
static void btn_start_event_handler(lv_event_t *e)
{
lv_obj_t *btn = lv_event_get_target(e);
if (!anim_timeline) {
anim_timeline_create();
}
/* 获取按下的点击状态 */
bool reverse = lv_obj_has_state(btn, LV_STATE_CHECKED);
/* 支持整个动画组的向前和向后播放 */
lv_anim_timeline_set_reverse(anim_timeline, reverse);
/* 启动动画时间轴 */
lv_anim_timeline_start(anim_timeline);
}
/**
* @brief LVGL入口
* @param 无
* @retval 无
*/
void lv_main(void)
{
lv_obj_t *par = lv_scr_act();
/* 创建按键部件 */
lv_obj_t *btn_start = lv_btn_create(par);
/* 设置回调函数 */
lv_obj_add_event_cb(btn_start, btn_start_event_handler,
LV_EVENT_VALUE_CHANGED, NULL);
lv_obj_align(btn_start, LV_ALIGN_TOP_MID, -100, 20);
/* 按键文本 */
lv_obj_t *label_start = lv_label_create(btn_start);
lv_label_set_text(label_start, "Start");
lv_obj_center(label_start);
/* 创建动画操作对象 */
obj1 = lv_obj_create(par);
lv_obj_set_size(obj1, obj_width, obj_height);
}
上述源码的实现逻辑如下:
① 当按下btn_start按键时,创建a1和a2动画,这两个动画的动画时间都是300ms;
② 在a1和a2的动画回调函数中,分别为obj1增宽和obj1增高;
③ 调用lv_anim_timeline_create函数,创建动画时间线;
④ 调用lv_anim_timeline_add函数把a1和a2动画挂载到动画时间线上;
⑤ 调用lv_anim_timeline_start函数开启动画时间线。
6.6.6.1 动画时间线相关API函数
1. lv_anim_timeline_create函数
创建动画时间线,其函数原型如下所示:
lv_anim_timeline_t *lv_anim_timeline_create(void);
返回值:动画时间线指针。
2. lv_anim_timeline_add函数
把动画挂载到时间线上,其函数原型如下所示:
void lv_anim_timeline_add(lv_anim_timeline_t *at, uint32_t start_time, lv_anim_t *a);
该函数的形参,如下表所示:

表6.6.6.1.1 lv_anim_timeline_add函数形参描述
返回值:无。
3. lv_anim_timeline_start函数
开启动画时间线,其函数原型如下所示:
uint32_t lv_anim_timeline_start(lv_anim_timeline_t *at);
该函数的形参,如下表所示:

表6.6.6.1.2 lv_anim_timeline_start函数形参描述
返回值:活动时间。
4. lv_anim_timeline_set_reverse函数
设置动画时间线的播放方向,其函数原型如下所示:
void lv_anim_timeline_set_reverse(lv_anim_timeline_t *at, bool reverse);
该函数的形参,如下表所示:

表6.6.6.1.3 lv_anim_timeline_set_reverse函数形参描述
返回值:无。
5. lv_anim_timeline_stop函数
停止动画时间线,其函数原型如下所示:
void lv_anim_timeline_stop(lv_anim_timeline_t *at);
该函数的形参,如下表所示:

表6.6.6.1.4 lv_anim_timeline_stop函数形参描述
返回值:无。
6. lv_anim_timeline_set_progress函数
设置动画时间线的进度,其函数原型如下所示:
void lv_anim_timeline_set_progress(lv_anim_timeline_t *at, uint16_t progress);
该函数的形参,如下表所示:

表6.6.6.1.5 lv_anim_timeline_set_progress函数形参描述
返回值:无。
7. lv_anim_timeline_get_playtime函数
获取动画时间线的总时长,其函数原型如下所示:
uint32_t lv_anim_timeline_get_playtime(lv_anim_timeline_t *at);
该函数的形参,如下表所示:

表6.6.6.1.6 lv_anim_timeline_get_playtime函数形参描述
返回值:时间线的总时长。
8. lv_anim_timeline_get_reverse函数
获取动画时间线是否反向播放,其函数原型如下所示:
bool lv_anim_timeline_get_reverse(lv_anim_timeline_t *at);
该函数的形参,如下表所示:

表6.6.6.1.7 lv_anim_timeline_get_reverse函数形参描述
返回值:ture:反向播放,false:非反向播放。
9. lv_anim_timeline_del函数
删除动画时间线,其函数原型如下所示:
void lv_anim_timeline_del(lv_anim_timeline_t *at);
该函数的形参,如下表所示:

表6.6.6.1.8 lv_anim_timeline_del函数形参描述
返回值:无。
6.6.7 动画相关API函数
LVGL官方提供了很多动画相关的API函数,如下表所示:

表6.6.7.1 动画相关API函数描述
6.7 LVGL 定时器
LVGL 有一个内置的软件定时器,它构建在硬件定时器基础之上,使系统能够提供不受硬件定时器资源限制的定时服务,其实现的功能与硬件定时器也是类似的。值得注意的是,因为lv_timer_handler函数并不是准时调用的,所以导致了软件定时器有一定的误差。
6.7.1 创建定时器
用户可调用lv_timer_create函数或者lv_timer_create_basic函数来创建LVGL软件定时器。
1. lv_timer_create函数
创建一个定时器,其函数原型如下所示:
lv_timer_t *lv_timer_create(timer_cb, period_ms, user_data);
该函数的形参,如下表所示:

表6.7.1.1函数lv_timer_create()形参描述
返回值:定时器指针。
当用户调用lv_timer_create函数创建定时器时,可以指定回调函数,该回调函数将被定时调用,定时器回调函数原型如下所示:
void (*lv_timer_cb_t)(lv_timer_t *);
2. lv_timer_create_basic函数
创建一个定时器,其函数原型如下所示:
lv_timer_t *lv_timer_create_basic(void)
{
return lv_timer_create(NULL, DEF_PERIOD, NULL);
}
返回值:定时器指针。
注意:使用该函数创建LVGL定时器时,必须调用lv_timer_set_cb函数,自定义定时回调函数,默认定时周期为DEF_PERIOD。
6.7.2 定时器配置
1. 定时器就绪、重置
用户可以手动设置定时器的就绪状态以及重置定时器,相关的函数如下:
lv_timer_ready函数
定时器已就绪,其函数原型如下所示:
void lv_timer_ready(lv_timer_t *timer);
该函数的形参,如下表所示:

表6.7.2.1 lv_timer_ready函数形参描述
定时器就绪后,系统将在下一次调用lv_timer_handler时运行这个定时器。
lv_timer_reset函数
重置定时器,其函数原型如下所示:
void lv_timer_reset(lv_timer_t *timer);
该函数的形参,如下表所示:

表6.7.2.2 lv_timer_reset函数形参描述
2. 设置定时器参数
在LVGL软件定时器的配置中,回调函数和定时周期是非常关键的,它们相关的函数如下:
lv_timer_set_cb函数
设置定时器的回调函数,其函数原型如下所示:
void lv_timer_set_cb(lv_timer_t *timer, lv_timer_cb_t timer_cb);
该函数的形参,如下表所示:

表6.7.2.3 lv_timer_set_cb函数形参描述
返回值:无。
lv_timer_set_period函数
设置定时周期,其函数原型如下所示:
void lv_timer_set_period(lv_timer_t *timer, uint32_t period);
该函数的形参,如下表所示:

表6.7.2.4 lv_timer_set_period函数形参描述
返回值:无。
3. 重复计数
用户可以使用lv_timer_set_repeat_count函数设置定时器重复计数的次数。当计数次数达到指定值后,计时器将自动删除。注意:当计数次数设置为-1时,以无限期地重复计数。
lv_timer_set_repeat_count函数
设置定时器重复计数的次数,其函数原型如下所示:
void lv_timer_set_repeat_count(lv_timer_t *timer, int32_t repeat_count );
该函数的形参,如下表所示:

表6.7.2.5 lv_timer_set_repeat_count函数形参描述
返回值:无。
4. 测量空闲时间
用户可通过lv_timer_get_idle函数获得lv_timer_handler(定时器任务)的空闲时间百分比,以此测量出LVGL的空闲时间。注意:该函数仅测量lv_timer_handler的空闲时间,而不会测量整个系统的空闲时间,因此,当用户使用操作系统并在定时器中调用lv_timer_handler时,可能会产生误差,因为它不会实际测量操作系统在空闲线程中花费的时间。
lv_timer_get_idle函数
获得lv_timer_handler的空闲时间百分比,其函数原型如下所示:
uint8_t lv_timer_get_idle(void);
返回值:返回空闲时间百分比。
6.7.3 定时器API函数
LVGL官方提供一些与定时器相关的API函数,如下表所示:

表6.7.3.1 定时器相关的API函数描述
1. lv_timer_del函数
删除一个定时器,其函数原型如下所示:
void lv_timer_del(lv_timer_t *timer);
该函数的形参,如下表所示:

表6.7.3.2 lv_timer_del函数形参描述
返回值:无。
2. lv_timer_pause函数
暂停定时器,其函数原型如下所示:
void lv_timer_pause(lv_timer_t *timer);
该函数的形参,如下表所示:

表6.7.3.3 lv_timer_pause函数形参描述
返回值:无。
3. lv_timer_resume函数
恢复定时器,其函数原型如下所示:
void lv_timer_resume(lv_timer_t *timer);
该函数的形参,如下表所示:

表6.7.3.4 lv_timer_resume函数形参描述
返回值:无。
4. lv_timer_enable函数
启用或禁用定时器,其函数原型如下所示:
void lv_timer_enable(bool en);
该函数的形参,如下表所示:

表6.7.3.5 lv_timer_enable函数形参描述
返回值:无。
5. lv_timer_get_next函数
获取下一个定时器,其函数原型如下所示:
lv_timer_t *lv_timer_get_next(lv_timer_t *timer);
该函数的形参,如下表所示:

表6.7.3.6 lv_timer_get_next函数形参描述
返回值:返回下一个定时器指针。
6.8 LVGL 事件
6.8.1 事件简介
事件(Event)在LVGL中非常重要,它是连接用户GUI界面和硬件设备(例如LED)之间的桥梁,我们可以将其理解为某种同类型操作动作的集合,例如,短按、长按、按下并释放、聚焦,等等。下面我们以一个LED控制的示例,帮助大家理解事件的作用:

图6.8.1.1 LED控制示例
在上图的示例中,当用户短按按钮部件(发生事件),将会触发相应的事件回调函数,在该回调函数中,我们可以调用底层的LED驱动,从而实现LED的控制。
接下来,我们介绍LVGL的事件处理机制,该机制非常完善,它能够监听事件,识别事件源,并完成事件处理,处理机制的示意图如下:

图6.8.1.2 LVGL事件处理机制
由上图可知,LVGL的事件处理机制分为三部分:
① 事件源,能够产生事件的部件,在LVGL中,每一个部件都可以触发事件。
② 事件,用户对部件的操作动作,例如:短按、长按等。
③ 事件监听器,接收事件、解释事件并处理用户代码。
6.8.2 添加事件(回调)
在LVGL中,用户可以调用lv_obj_add_event_cb函数来添加事件,其函数原型如下所示:
struct _lv_event_dsc_t *lv_obj_add_event_cb(lv_obj_t *obj, lv_event_cb_t event_cb, lv_event_code_t filter, void *user_data);
该函数的形参,如下表所示:

表6.8.2.1 lv_obj_add_event_cb函数形参描述
返回值:返回事件描述符。
接下来,我们结合源码,为大家介绍事件的添加步骤,示例源码如下:
/* 第一步 创建按钮部件 */
lv_obj_t *btn = lv_btn_create(lv_scr_act());
/* 第二步 添加事件并设置回调函数 */
lv_obj_add_event_cb(btn, my_event_cb, LV_EVENT_CLICKED, NULL);
static void my_event_cb(lv_event_t *event)
{
printf("Clicked\n"); /* 第三步 在回调函数中处理用户逻辑代码 */
}
由上述源码可知,部件的事件添加共分为三步:
① 创建部件;
② 添加事件到部件中,并设置回调函数和事件类型;
③ 在回调函数中处理用户逻辑代码。
注意:事件类型可以理解为某种同类型操作动作的集合,例如短按、长按等,其相关的内容将在6.8.4小节介绍。
6.8.3 删除事件
用户可以通过lv_obj_remove_event_cb函数删除事件,其函数原型如下所示:
bool lv_obj_remove_event_cb(struct _lv_obj_t *obj, lv_event_cb_t event_cb);
该函数的形参,如下表所示:

表6.8.3.1 lv_obj_remove_event_cb函数形参描述
返回值:true:有事件被移除;false:没有事件被移除。
6.8.4 事件类型
事件类型可以理解为某种同类型操作动作的集合,例如短按、长按等,其可分为以下几类:
① 输入设备事件;
② 绘图事件;
③ 其他事件;
④ 特别事件;
⑤ 自定义事件;
在LVGL中,所有对象都可以接收输入设备事件、绘图事件和其他事件。注意:自定义事件由用户添加,LVGL 从不发送自定义事件。
接下来,我们详细介绍这几种事件类型:
1. 输入设备事件:主要描述触摸、按键等输入设备所触发的事件,如下表所示:

表6.8.4.1 输入设备事件类型
2. 绘图事件:主要描述部件绘画时的事件,如下表所示:

表6.8.4.2 部件的绘画事件描述
注意:在部件绘画事件中,不能设置大小等属性,可以获取部件的属性。
3. 其他事件:主要描述删除、大小、样式等事件,如下表所示:

表6.8.4.3 其他事件描述
4. 特别事件:主要描述对象数值被修改时触发的事件,如下表所示:

表6.8.4.4 特别事件描述
注意:关于上述事件类型的使用方法,请回顾6.8.2小节的示例代码。
5. 自定义事件:
任何自定义事件代码都可通过以下方式注册:
uint32_t MY_EVENT_1 = lv_event_register_id();
上述函数可将事件等级表的ID获取回来,然后调用lv_event_send函数,发送事件到回调函数当中。
lv_event_send函数
发送一个事件,其函数原型如下所示:
lv_res_t lv_event_send(lv_obj_t *obj, lv_event_code_t event_code, void *param);
该函数的形参,如下表所示:

表6.8.4.5 lv_event_send函数形参描述
返回值:LV_RES_OK:发送成功,否则失败。
6.8.5 获取事件字段
在LVGL中,允许多个事件共用同一个回调函数,这可以大大减少回调函数的数量,但随之而来的问题是:用户如何去判断事件的信息?例如事件的触发源、事件类型和自定义参数等。为了解决这个问题,LVGL提供了事件字段函数,用于获取事件相关的信息,如下表所示:

表6.8.5.1 获取事件字段函数
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70040860/viewspace-3171769/ ,如需转载,请注明出处,否则将追究法律责任。