LVGL (11) 更新 Layout 依据
·
LVGL 是以 obj 为基础衍生出来的一套绘制;每个 obj 都包含了 2 个字段:layout_inv / scr_layout_inv;
typedef struct _lv_obj_t {
......
uint16_t layout_inv : 1; // 改 obj 的 layout 是否需要更新
uint16_t scr_layout_inv : 1; // screen 的 layout 是否需要更新
......
} lv_obj_t;
可以看到,这里有 2 个字段,接下来我们来看下他们分别代表什么,以及如何使用;
- layout_inv 在 lv_obj_mark_layout_as_dirty 的时候标记为 1;
- 在 layout_update_core 的时候,判断如果为 0,那么直接返回;
- scr_layout_inv 在 lv_obj_mark_layout_as_dirty 的时候标记为 1;
- 在 lv_obj_update_layout 的时候判断为 0 的时候,停止更新;
所以,看起来只和几个函数相关:
void lv_obj_mark_layout_as_dirty(lv_obj_t * obj)
{
obj->layout_inv = 1;
/*Mark the screen as dirty too to mark that there is something to do on this screen*/
lv_obj_t * scr = lv_obj_get_screen(obj);
scr->scr_layout_inv = 1;
/*Make the display refreshing*/
lv_disp_t * disp = lv_obj_get_disp(scr);
if(disp->refr_timer) lv_timer_resume(disp->refr_timer);
}
void lv_obj_update_layout(const lv_obj_t * obj)
{
static bool mutex = false;
if(mutex) {
LV_LOG_TRACE("Already running, returning");
return;
}
mutex = true;
lv_obj_t * scr = lv_obj_get_screen(obj);
/*Repeat until there where layout invalidations*/
while(scr->scr_layout_inv) {
LV_LOG_INFO("Layout update begin");
scr->scr_layout_inv = 0;
layout_update_core(scr);
LV_LOG_TRACE("Layout update end");
}
mutex = false;
}
static void layout_update_core(lv_obj_t * obj)
{
uint32_t i;
uint32_t child_cnt = lv_obj_get_child_cnt(obj);
for(i = 0; i < child_cnt; i++) {
lv_obj_t * child = obj->spec_attr->children[i];
layout_update_core(child);
}
if(obj->layout_inv == 0) return;
obj->layout_inv = 0;
lv_obj_refr_size(obj);
lv_obj_refr_pos(obj);
if(child_cnt > 0) {
uint32_t layout_id = lv_obj_get_style_layout(obj, LV_PART_MAIN);
if(layout_id > 0 && layout_id <= layout_cnt) {
void * user_data = LV_GC_ROOT(_lv_layout_list)[layout_id - 1].user_data;
LV_GC_ROOT(_lv_layout_list)[layout_id - 1].cb(obj, user_data);
}
}
}
可以看到:
- 通过 lv_obj_mark_layout_as_dirty 来标记当前 obj 为 invalid,即 obj->layout_inv = 1;;
- 通过 lv_obj_mark_layout_as_dirty 来获取当前 obj 的 screen (循环获取父对象的方式),并且标记为 invalid,即 scr->scr_layout_inv = 1;;
也就是说,scr_layout_inv 只有 screen 的 obj 才使用,其他的 obj 并没有使用这个结构体中的变量;
在更新 layout 的时候,调用 lv_obj_update_layout:
- 首先获取 screen (循环获取父对象的方式),并判断是否 scr->scr_layout_inv 为 invalid;
- 如果 screen layout 需要被更新,那么调用 layout_update_core 来对 screen 上的子 obj 循环调用 layout_update_core,此刻需要判断 obj 的 layout_inv;
更多推荐
已为社区贡献17条内容
所有评论(0)