目录
一、前言
我是 Hello_Embed
在上一篇笔记中,我们通过结构体封装界面接口,实现了规范化的多界面管理。但代码中还存在判断逻辑繁琐 、按钮创建代码重复的问题,同时我们也可以为界面增加定时器功能,完善交互体验。本篇将对界面接口进行全面优化,简化判断逻辑、消除冗余代码,并为界面集成定时器功能。
二、判断逻辑优化
原始的界面切换判断通过字符串对比实现,代码冗余且不简洁:
c
if(strcmp(lv_label_get_text(label), "Page[1]") == 0)
{
lv_my_ui_page1_t.open();
}
if(strcmp(lv_label_get_text(label), "Page[2]") == 0)
{
lv_my_ui_page2_t.open();
}
优化思路
利用 LVGL 对象的用户数据功能,将界面结构体直接绑定到按钮上,无需字符串判断,直接调用接口。
- 创建按钮时,绑定对应的界面结构体:
c
//界面1
btn = lv_btn_create(g_page_cont);
lv_obj_align(btn, LV_ALIGN_CENTER, 0, 20);
lv_obj_set_user_data(btn, &lv_my_ui_page1_t);
label = lv_label_create(btn);
lv_label_set_text(label, "Page[1]");
lv_obj_center(label);
lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, label);
//界面2
btn = lv_btn_create(g_page_cont);
lv_obj_align(btn, LV_ALIGN_CENTER, 0, 60);
lv_obj_set_user_data(btn, &lv_my_ui_page2_t);
label = lv_label_create(btn);
lv_label_set_text(label, "Page[2]");
lv_obj_center(label);
- 事件回调中直接获取结构体并打开界面:
c
static void event_handler(lv_event_t * e)
{
lv_obj_t * btn = lv_event_get_target(e);
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * label = lv_event_get_user_data(e);
lv_obj_t * page_cont = lv_obj_get_parent(btn);
lv_my_ui_page_data_t * page_data = lv_obj_get_user_data(btn);
if(code == LV_EVENT_CLICKED) {
LV_LOG_USER("%s", lv_label_get_text(label));
page_data->open();
lv_obj_add_flag(page_cont, LV_OBJ_FLAG_HIDDEN);
}
}
三、重复代码优化
主界面中两个按钮的创建代码高度重复,进一步优化:
使用结构体数组 存储界面数据,通过for循环批量创建按钮,配合宏定义防止数组越界。
优化后代码:
c
#define LIST_NUM 2
void my_ui_main_init(void)
{
g_page_cont = lv_button_create(lv_screen_active());
lv_obj_set_size(g_page_cont, lv_pct(100), lv_pct(100));
lv_obj_set_style_bg_color(g_page_cont, lv_color_hex(0x00ff00), 0);
lv_obj_t * label;
lv_obj_t * btn;
for(uint16_t index = 0; index < LIST_NUM; index++)
{
btn = lv_btn_create(g_page_cont);
lv_obj_set_user_data(btn, g_page_list[index]);
lv_obj_align(btn, LV_ALIGN_TOP_MID, index * 100, 20);
label = lv_label_create(btn);
lv_label_set_text_fmt(label, "Page[%d]", index + 1);
lv_obj_center(label);
lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, label);
}
}
四、界面定时器功能引入
为界面 1 添加定时器功能,实现实时计时显示 、后台日志打印,切换界面时正常管理定时器。
c
static uint16_t page_open(void)
{
lv_obj_t * page_cont = lv_obj_create(lv_screen_active());
lv_obj_set_size(page_cont, LV_PCT(100), LV_PCT(100));
lv_obj_set_style_bg_color(page_cont, lv_color_hex(0x00ff00), 0);
lv_obj_t * btn = lv_button_create(page_cont);
lv_obj_align(btn, LV_ALIGN_CENTER, 0, 0);
lv_obj_t * label = lv_label_create(btn);
lv_label_set_text(label, "Page[1]");
lv_obj_center(label);
lv_obj_add_event_cb(btn, page_close_event_handler, LV_EVENT_CLICKED, page_cont);
label = lv_label_create(page_cont);
lv_obj_set_style_text_font(label, &lv_font_montserrat_20, 0);
lv_label_set_text_fmt(label, "Timer: %d", 0);
lv_timer_t * timer = lv_timer_create(page_timer, 1000, label);
lv_obj_set_user_data(page_cont, timer);
lv_my_ui_page1_t.page_cont = page_cont;
return 0;
}
static void page_timer(lv_timer_t * timer)
{
lv_obj_t * label = lv_timer_get_user_data(timer);
static int count = 0;
count++;
lv_label_set_text_fmt(label, "Timer: %d", count);
LV_LOG_USER("%s %d", lv_label_get_text(label), count);
}
主界面运行效果:

界面 1 显示与后台日志效果:

五、总结
- 通过对象用户数据绑定结构体,消除字符串判断,简化界面切换逻辑;
- 采用循环 + 数组批量创建按钮,解决代码重复问题,提升可扩展性;
- 为界面集成定时器功能,实现计时显示与后台打印,完善功能交互。
六、结尾
本次优化让界面接口架构更简洁、扩展性更强,同时完成了定时器功能的集成。我是 Hello_Embed,下一篇我们将继续优化界面,为按钮和界面增加图标显示,让界面更美观,敬请关注!