[LVGL] Page Management Framework

When we actually use LVGL to complete some projects, we usually need to display more than one page. At this time, how to better manage these pages has become a problem that needs to be solved. If it is not handled properly, it is likely to It will cause the system to crash because too many pages are loaded but not released in time.
Now I will show you the page management framework I built. If there are any problems in the design, please leave a message to discuss.

1. Preliminary preparation

Before starting, you need to understand a few core functions.

/* 屏幕(页面)是没有父对象的特殊对象。所以它们可以像这样创建 */
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. Page management structure (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. Other related variables

static struct page page_admin[10];	// 存储所有创建好的页面
static int page_num = 0;			// 记录 page_admin[] 数组中存在多少个页面
struct page *cur_page;				// 记录当前显示的页面

4. Functions related to page management

/* 设计页面的样式 */
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. Practical examples

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);
}

insert image description here

Guess you like

Origin blog.csdn.net/weixin_48896613/article/details/129244716