目录
前言
一、数据类型
二、页面调度
三、页面显示
四、视频展示
前言
最近在用LVGL写一个简单的UI界面,需要进行几个页面的切换,所以就自己写了一个简单页面切换代码,方便进行页面切换,同时使UI代码结构更加清晰。这个结构主要用于嵌入式MCU上使用,所以结构比较简单。
一、数据类型
typedef struct ui_show_t
{struct ui_show_t *last;uint32_t *ui;
}ui_show_t;
这个页面切换代码会用到一个类似链表的结构,每个界面都会定义一个这样的数据数据结构,用来保存上一个页面的指针。如下图所示:
这样每切换到下一页面的时候都可以根据需要来切换到上一页面。
同时我定义了页面的函数类型:
typedef struct ui_show_t * (*ui_show_fun)(ui_show_t* ui_show,ui_opera_t ui_opera)
除了上面提到ui_show_t类型,还有一个ui_opera_t,这个类型定义了页面的操作设备,例如触摸屏、实体按键、旋转按钮等等,我的设备是旋转按钮,所以就定义了如下的类型:
typedef struct
{int8_t dir_cnt; //旋转方向计数btn_sta_t btn_sta; //按键状态
}ui_opera_t;
这样就可以操作我的屏幕进行页面切换了。
二、页面调度
对于页面的调用是单独创建了一个任务,在这个任务的循环里面获取旋转按钮的状态以及进行页面的显示。可以看到最终显示的是 my_show_ui->ui 这个页面,这个页面在初始化的时候被赋值了ln_lvgl_mainwindow这个函数指针,这个函数就是用来显示主页面的函数。
#include "ln_lvgl_ui.h"
lv_ui guider_ui;static ui_show_t my_start_ui;
static ui_show_t *my_show_ui = NULL;
ui_opera_t my_ui_opera;static OS_Thread_t g_lvgl_ui_thread;
#define LVGL_UI_TASK_STACK_SIZE 4*40*256 //Bytevoid ui_show_scheduler(void *params);
ui_show_t* ln_lvgl_mainwindow(ui_show_t* ui_show,ui_opera_t ui_opera);
ui_show_t* ln_lvgl_lightwindow(ui_show_t* ui_show,ui_opera_t ui_opera);int ln_lvgl_ui_init()
{ln_drv_rotate_btn_init(); //旋转按钮初始化lv_init(); //LVGL初始化lv_port_disp_init(); //显示设备初始化setup_ui(&guider_ui); //第一个页面初始化//创建页面显示调度任务if(OS_OK != OS_ThreadCreate(&g_lvgl_ui_thread, "LVGL Task", ui_show_scheduler, NULL, OS_PRIORITY_BELOW_NORMAL, LVGL_UI_TASK_STACK_SIZE)) {return HAL_ERROR;}return HAL_OK;
}void ui_show_scheduler(void *params)
{//对第一个页面的链表进行数据初始化my_start_ui.last = NULL;my_start_ui.ui = (uint32_t*)ln_lvgl_mainwindow;my_show_ui = &my_start_ui;while(1){//获取旋转按钮的旋转方向计数以及按键状态my_ui_opera.dir_cnt = ln_drv_rotate_btn_get_dir();my_ui_opera.btn_sta = (btn_sta_t)ln_drv_rotate_btn_get_press();if(my_ui_opera.dir_cnt != 0){LOG(LOG_LVL_ERROR, "cnt :%d \r\n", my_ui_opera.dir_cnt);}//显示对应UImy_show_ui = (ui_show_t*)(*((ui_show_fun)(my_show_ui->ui)))((ui_show_t*)my_show_ui,my_ui_opera);//LVGL函数lv_timer_handler();//延时1msOS_MsDelay(1);}
}
三、页面显示
#include "ln_lvgl_mainwindow.h"//在这里定义了一个这个页面的链表方便存储上一个页面的指针
static ui_show_t my_mainwindow_ui;ui_show_t* ln_lvgl_mainwindow(ui_show_t* ui_show,ui_opera_t ui_opera)
{static uint8_t show_flag = 0;static int8_t cur_show_item = 0;static int8_t last_show_item = -1;if(show_flag == 0){//显示页面,只需要显示一次就可以show_flag = 1;}//根据旋转编码器不同的值,来执行不同的操作cur_show_item += 0 - ui_opera.dir_cnt;if(cur_show_item != last_show_item){switch(cur_show_item){case 0:{break;}case 1:{break;}}}last_show_item = cur_show_item;//按键长按和短按也都可以执行不同的操作,例如长按返回上一个页面,短按进入下一页面if(ui_opera.btn_sta == SHORT_PRESS){//短按进入下一个页面,下一个页面自行定义,直接赋值就好switch(cur_show_item){case 0:{my_mainwindow_ui.last = ui_show;my_mainwindow_ui.ui = (uint32_t*)ln_lvgl_lightwindow;//例如此处显示灯光页面ui_show = &my_mainwindow_ui;show_flag = 0;break;}case 3:{my_mainwindow_ui.last = ui_show;my_mainwindow_ui.ui = (uint32_t*)ln_lvgl_timewindow;//例如此处显示时间页面ui_show = &my_mainwindow_ui;show_flag = 0;break;}}}if(ui_opera.btn_sta == LONG_PRESS){//长按进入上一个页面(如果有的话)if(ui_show->last != NULL){//直接赋值ui_show = ui_show->last;}}//返回赋值后的指针地址return ui_show;
}