我们在实际使用 LVGL 完成一些项目时,通常需要展示不止一个页面,此时这些页面要如何更好的进行管理成为了一个需要解决的问题,如果处理不当,在资源短缺的嵌入式设备中很可能会因为过多页面的加载但却没有及时释放造成系统的崩溃。 现在就为大家展示一下我所构建的页面管理框架,如果设计上有存在什么问题,欢迎留言讨论。

1、前期准备

在开始之前需要了解一下几个核心函数。

/* 屏幕(页面)是没有父对象的特殊对象。所以它们可以像这样创建 */

lv_obj_t *page = lv_obj_create(NULL);

/* 加载想要显示的屏幕(页面) */

lv_scr_load(page);

/* 删除对象的所有子项(但不是对象本身) */

lv_obj_clean(page);

/* 动画加载屏幕(页面)

transition_type:LV_SCR_LOAD_ANIM_NONE:在 delay 毫秒后立即切换

LV_SCR_LOAD_ANIM_OVER_LEFT/RIGHT/TOP/BOTTOM:将新屏幕移动到当前的指定方向

LV_SCR_LOAD_ANIM_MOVE_LEFT/RIGHT/TOP/BOTTOM:将当前屏幕和新屏幕都向给定方向移动

LV_SCR_LOAD_ANIM_FADE_ON:在旧屏幕上淡出新屏幕 */

lv_scr_load_anim(page, transition_type, time, delay, false);

2、页面管理结构体(struct page)

struct page {

char name[32]; // 页面名

int page_level; // 页面等级,依靠这个来实现对上一页面的切换,该值越小,等级越高

lv_obj_t *body_obj; // 页面结构体

void *private_data; // 私有数据

void (*onInit) (struct page *page); // 创建页面函数

void (*onExit) (struct page *old_page, struct page *new_page); // 销毁页面函数

};

3、其他相关变量

static struct page page_admin[10]; // 存储所有创建好的页面

static int page_num = 0; // 记录 page_admin[] 数组中存在多少个页面

struct page *cur_page; // 记录当前显示的页面

4、页面管理相关函数

/* 设计页面的样式 */

void style_init(void) {

lv_style_init(&page_style);

lv_style_set_bg_color(&page_style, lv_color_hex(0x000000));

lv_style_set_radius(&page_style, 0);

lv_style_set_pad_all(&page_style, 0);

lv_style_set_border_side(&page_style, LV_BORDER_SIDE_NONE);

}

/* 创建一个指定样式的空白屏幕 */

lv_obj_t * create_new_screen(void) {

lv_obj_t *main_obj = lv_obj_create(NULL);

lv_obj_clean(main_obj);

lv_obj_set_size(main_obj, 240, 240); // 根据个人屏幕大小修改

lv_obj_add_style(main_obj, &page_style, 0);

return main_obj;

}

/* 初始化所有的页面 */

void all_page_init(void) {

style_init();

// 主页面

strcpy(page_admin[page_num++].name, "main_page");

page_admin[page_num - 1].body_obj = create_new_screen();

page_admin[page_num - 1].page_level = 0;

page_admin[page_num - 1].onInit = main_page_init;

page_admin[page_num - 1].onExit = main_page_exit;

cur_page = &page_admin[page_num - 1];

lv_scr_load(page_admin[page_num - 1].body_obj); // 设置该页面为第一个显示在屏幕上面的页面

// 菜单页面

strcpy(page_admin[page_num++].name, "menu_page");

page_admin[page_num - 1].body_obj = create_new_screen();

page_admin[page_num - 1].page_level = 1;

page_admin[page_num - 1].onInit = menu_page_init;

page_admin[page_num - 1].onExit = menu_page_exit;

// 默认展示主页面

cur_page->onInit(cur_page);

}

static struct page *page_search(char *name) {

for(int i = 0; i < page_num; i++) {

if(strcmp(page_admin[i].name, name) == 0)

return &page_admin[i];

}

return NULL;

}

/**

* @brief 页面切换函数

*

* @param new_page_name 新页面名

* @return 0 成功 -1 新页面不存在

*/

int page_transition(char *new_page_name) {

Serial.printf("transition page = %s\n", new_page_name);

if(strcmp(new_page_name, "") == 0 || new_page_name == NULL)

return -1;

struct page *new_page = page_search(new_page_name);

if(new_page != NULL) {

cur_page->onExit(cur_page, new_page);

new_page->onInit(new_page);

cur_page = new_page;

return 0;

} else {

return -1;

}

}

/**

* @brief 返回上一页面

*

* @param page 当前页面

* @return struct page 指针 上一页面 NULL 失败

*/

struct page *return_prev_page(struct page *page) {

if(page == NULL)

return NULL;

int cur_page_level = page->page_level;

for(int i = page_num - 1; i >= 0; i--) {

if(page_admin[i].page_level < cur_page_level) {

return &page_admin[i];

}

}

return NULL;

}

5、实际例子

static void event_btn1_handler(lv_event_t* e)

{

lv_event_code_t code = lv_event_get_code(e); //获取回调事件

if (code == LV_EVENT_CLICKED) { //点击事件

struct page *new_page = &page_admin[1];

cur_page->onExit(cur_page, new_page);

new_page->onInit(new_page);

cur_page = new_page;

}

}

static void event_btn2_handler(lv_event_t* e)

{

lv_event_code_t code = lv_event_get_code(e); //获取回调事件

if (code == LV_EVENT_CLICKED) { //点击事件

struct page *new_page = &page_admin[0];

cur_page->onExit(cur_page, new_page);

new_page->onInit(new_page);

cur_page = new_page;

}

}

void main_page_init(struct page *page) {

lv_obj_t *body_obj = page->body_obj;

lv_obj_t *block_obj = lv_obj_create(body_obj);

lv_obj_set_style_bg_color(block_obj, lv_color_hex(0xafafaf), LV_STATE_DEFAULT);

lv_obj_set_align(block_obj, LV_ALIGN_CENTER);

lv_obj_set_size(block_obj, 50, 50);

lv_obj_t * btn1 = lv_btn_create(body_obj);/*创建btn1*/

lv_obj_add_event_cb(btn1, event_btn1_handler, LV_EVENT_ALL, NULL);/*设置btn1回调函数*/

lv_obj_set_pos(btn1, 20, 40);

lv_obj_t * label = lv_label_create(btn1);/*btn1内创建label*/

lv_label_set_text(label, "jump button");

}

void main_page_exit(struct page *old_page, struct page *new_page) {

lv_obj_clean(old_page->body_obj);

lv_scr_load_anim(new_page->body_obj, LV_SCR_LOAD_ANIM_MOVE_TOP, 500, 0, false);

}

void menu_page_init(struct page *page) {

lv_obj_t *body_obj = page->body_obj;

lv_obj_t *block_obj = lv_obj_create(body_obj);

lv_obj_set_style_bg_color(block_obj, lv_color_hex(0xffe604), LV_STATE_DEFAULT);

lv_obj_set_align(block_obj, LV_ALIGN_CENTER);

lv_obj_set_size(block_obj, 50, 50);

lv_obj_t * btn1 = lv_btn_create(body_obj);/*创建btn1*/

lv_obj_add_event_cb(btn1, event_btn2_handler, LV_EVENT_ALL, NULL);/*设置btn1回调函数*/

lv_obj_set_pos(btn1, 20, 40);

lv_obj_t * label = lv_label_create(btn1);/*btn1内创建label*/

lv_label_set_text(label, "jump button");

}

void menu_page_exit(struct page *old_page, struct page *new_page) {

lv_obj_clean(old_page->body_obj);

lv_scr_load_anim(new_page->body_obj, LV_SCR_LOAD_ANIM_MOVE_BOTTOM, 500, 0, false);

}

参考链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: