《lvgl基础学习 —— 页面切换》
1.页面切换
Screen(屏幕)是 LVGL 中的“页面根节点”
-
每个 screen 是一个 独立的 UI 树
-
同一时间 只有一个 screen 是激活显示的
Screen A (Home)
Screen B (Settings)
Screen C (Info)
页面切换 = 切换当前激活的screen
Screen的本质:
lv_obj_t *screen = lv_obj_create(NULL);
注意这点:
-
parent = NULL
-
说明它是“顶级对象”
screen 不是普通 container
页面切换的基础API
创建screen:
lv_obj_t *scr = lv_obj_create(NULL);
加载screen(切换页面):
lv_scr_load(scr);
瞬间切换,无动画。
demo:两个页面 + 按钮切换
定义两个screen(全局或static)
static lv_obj_t *scr_home; static lv_obj_t *scr_settings;
创建Home界面
static void goto_settings_cb(lv_event_t *e) { lv_scr_load(scr_settings); } void create_home_screen(void) { scr_home = lv_obj_create(NULL); lv_obj_t *label = lv_label_create(scr_home); lv_label_set_text(label, "Home Screen"); lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 20); lv_obj_t *btn = lv_btn_create(scr_home); lv_obj_center(btn); lv_obj_add_event_cb(btn, goto_settings_cb, LV_EVENT_CLICKED, NULL); lv_obj_t *btn_label = lv_label_create(btn); lv_label_set_text(btn_label, "Go Settings"); lv_obj_center(btn_label); }
创建setting界面
static void goto_home_cb(lv_event_t *e) { lv_scr_load(scr_home); } void create_settings_screen(void) { scr_settings = lv_obj_create(NULL); lv_obj_t *label = lv_label_create(scr_settings); lv_label_set_text(label, "Settings Screen"); lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 20); lv_obj_t *btn = lv_btn_create(scr_settings); lv_obj_center(btn); lv_obj_add_event_cb(btn, goto_home_cb, LV_EVENT_CLICKED, NULL); lv_obj_t *btn_label = lv_label_create(btn); lv_label_set_text(btn_label, "Back Home"); lv_obj_center(btn_label); }
在 main() 里初始化并加载首页
create_home_screen();
create_settings_screen();
lv_scr_load(scr_home);
带动画的切换:
lv_scr_load_anim(scr, LV_SCR_LOAD_ANIM_MOVE_LEFT, 300, // 动画时间 ms 0, // 延迟 false // 是否自动删除旧 screen );
常用动画类型:
| 动画 | 说明 | | ------------- | --- | | `MOVE_LEFT` | 向左滑 | | `MOVE_RIGHT` | 向右滑 | | `MOVE_TOP` | 向上 | | `MOVE_BOTTOM` | 向下 | | `FADE_ON` | 渐显 |
从Home->Settings(左滑)
lv_scr_load_anim(scr_settings, LV_SCR_LOAD_ANIM_MOVE_LEFT, 300, 0, false);
从Settings->Home(右滑)
lv_scr_load_anim(scr_home, LV_SCR_LOAD_ANIM_MOVE_RIGHT, 300, 0, false);
是否要“删除旧页面“:
参数解释(第 5 个参数):auto_del
-
true:切换后 自动删除旧 screen -
false:保留旧 screen
推荐策略:
页面类型 建议 Home / 主页面 false 设置页 false 临时页面(弹窗型) true
常驻页面不要频繁创建/销毁。
demo:主页 -> 设置,带动画
static lv_obj_t *scr_home; static lv_obj_t *scr_settings; static void goto_settings_cb(lv_event_t *e) { lv_scr_load_anim(scr_settings, LV_SCR_LOAD_ANIM_MOVE_LEFT, 300, 0, false); } static void goto_home_cb(lv_event_t *e) { lv_scr_load_anim(scr_home, LV_SCR_LOAD_ANIM_MOVE_RIGHT, 300, 0, false); } void ui_screens_init(void) { /* Home */ scr_home = lv_obj_create(NULL); lv_obj_t *h_label = lv_label_create(scr_home); lv_label_set_text(h_label, "Home"); lv_obj_align(h_label, LV_ALIGN_TOP_MID, 0, 20); lv_obj_t *h_btn = lv_btn_create(scr_home); lv_obj_center(h_btn); lv_obj_add_event_cb(h_btn, goto_settings_cb, LV_EVENT_CLICKED, NULL); lv_obj_t *h_btn_label = lv_label_create(h_btn); lv_label_set_text(h_btn_label, "Settings"); lv_obj_center(h_btn_label); /* Settings */ scr_settings = lv_obj_create(NULL); lv_obj_t *s_label = lv_label_create(scr_settings); lv_label_set_text(s_label, "Settings"); lv_obj_align(s_label, LV_ALIGN_TOP_MID, 0, 20); lv_obj_t *s_btn = lv_btn_create(scr_settings); lv_obj_center(s_btn); lv_obj_add_event_cb(s_btn, goto_home_cb, LV_EVENT_CLICKED, NULL); lv_obj_t *s_btn_label = lv_label_create(s_btn); lv_label_set_text(s_btn_label, "Back"); lv_obj_center(s_btn_label); lv_scr_load(scr_home); }
工程级页面管理建议:
ui/
├── ui_home.c
├── ui_settings.c
├── ui_about.c
└── ui_screens.c ← 统一管理 screen
不推荐
❌ 在回调里 lv_obj_create(NULL)
❌ 页面切换时频繁 malloc/free
❌ 把所有页面写在一个 .c 里
常见坑(一定要看)
❌ 1️⃣ 把 screen 当 container 用
→ parent 必须是 NULL
❌ 2️⃣ 切换后再创建 UI
→ 会看到白屏闪烁
❌ 3️⃣ auto_del 用错
→ 页面丢失 / 崩溃
❌ 4️⃣ 在非 LVGL 线程切换 screen
→ 必炸(LVGL 非线程安全)
浙公网安备 33010602011771号