LVGL -窗口操作
1 窗口背景介绍
在 LVGL 中,screen 是一个顶层对象,代表你设备上当前显示的整个画面。它相当于一个“全屏容器”,你可以在上面添加按钮、标签、图像、容器等各种界面控件。它的本质就是一个特殊的 lv_obj_t,但它没有父对象(parent == NULL),所以它是显示层级的根节点。
可以创建多个 screen,然后根据需要来进行切换。每个 screen 是独立的,互不影响。只会有一个 screen 是“当前可见的”,通过 lv_scr_load() 或 lv_scr_load_anim() 来切换
2 窗口应用
一切可视内容都是 lv_obj_t 对象,包括按钮、标签、容器、图像等。所有界面元素都以树状结构组织:parent → child → child …
lv_scr_act() 是当前正在显示的“屏幕 screen”对象,你可以创建多个 screen 并进行切换
Screen(屏幕):本质是 lv_obj_create(NULL) 创建的一个顶层对象,代表一整块显示区域。
2.1 基础窗口创建
lv_obj_t *scr = lv_obj_create(NULL); // NULL 表示没有父对象,就是顶层 screen
lv_obj_t *label = lv_label_create(scr);
lv_label_set_text(label, "这是一个新窗口");
2.2 窗口大小
lv_obj_set_size(obj, width, height); // 设置宽度和高度
lv_obj_set_width(obj, width); // 单独设置宽度
lv_obj_set_height(obj, height); // 单独设置高度
2.3 颜色控制
颜色控制:
lv_color_hex() 自定义颜色值 将你指定的 16 进制 RGB 色值(0xRRGGBB)转换为 lv_color_t 类型
lv_palette_main() LVGL 预置了一套 Material Design 风格的调色板(Palette)lv_palette_main() 或 lv_palette_lighten()、lv_palette_darken() 来取常用主题色。lv_palette_main(LV_PALETTE_BLUE);
2.3.1 创建风格
lv_style_t style;
lv_style_init(&style);
lv_style_set_bg_color(&style, lv_color_hex(0x3498db)); // 设置背景颜色为蓝色
lv_style_set_bg_opa(&style, LV_OPA_COVER); // 设置不透明度lv_obj_add_style(win, &style, 0); // 应用样式到窗口对象
2.3.2 内部风格
lv_obj_set_style_bg_color(win, lv_color_hex(0x2ecc71), 0); // 设置背景颜色为绿色
lv_obj_set_style_bg_opa(win, LV_OPA_COVER, 0); // 设置不透明度
2.4 窗口切换
2.4.1 直接切换
lv_scr_load(scr); // 立即切换
2.4.2 动画切换
lv_scr_load_anim(scr2, LV_SCR_LOAD_ANIM_FADE_ON, 300, 0, false);
函数解释:
动画动作:
2.4.3 切换动作
LVGL 支持通过滑动手势(左右滑动等)来自定义“滑动切换 screen”的功能,但它不是默认开启的,你需要手动监听触摸事件并根据滑动方向调用 lv_scr_load_anim() 来实现滑动切屏的效果。
通过触摸事件识别滑动方向 + 切换 screen
- 记录触摸起点和终点(手势识别)
- 判断滑动方向(左 / 右 / 上 / 下)
- 使用 lv_scr_load_anim() 切换 screen 并附加动画
static lv_point_t touch_start;
static lv_obj_t *screens[2];
static int current_screen = 0;void gesture_event_cb(lv_event_t *e) {lv_indev_t *indev = lv_indev_get_act();lv_point_t point;lv_indev_get_point(indev, &point);if (lv_indev_get_state(indev) == LV_INDEV_STATE_PR) {// 手指按下,记录起点touch_start = point;} else if (lv_indev_get_state(indev) == LV_INDEV_STATE_REL) {// 手指抬起,判断滑动方向int dx = point.x - touch_start.x;int dy = point.y - touch_start.y;if (abs(dx) > 50 && abs(dx) > abs(dy)) {if (dx < 0 && current_screen == 0) {lv_scr_load_anim(screens[1], LV_SCR_LOAD_ANIM_MOVE_LEFT, 300, 0, false);current_screen = 1;} else if (dx > 0 && current_screen == 1) {lv_scr_load_anim(screens[0], LV_SCR_LOAD_ANIM_MOVE_RIGHT, 300, 0, false);current_screen = 0;}}}
}void create_screens() {screens[0] = lv_obj_create(NULL);screens[1] = lv_obj_create(NULL);lv_obj_t *label1 = lv_label_create(screens[0]);lv_label_set_text(label1, "Screen 1");lv_obj_align(label1, LV_ALIGN_CENTER, 0, 0);lv_obj_t *label2 = lv_label_create(screens[1]);lv_label_set_text(label2, "Screen 2");lv_obj_align(label2, LV_ALIGN_CENTER, 0, 0);lv_obj_add_event_cb(screens[0], gesture_event_cb, LV_EVENT_ALL, NULL);lv_obj_add_event_cb(screens[1], gesture_event_cb, LV_EVENT_ALL, NULL);lv_scr_load(screens[0]);
}