LVGL页面切换

LVGL中没有明确的页面切换方案,参考(2.6 #lvgl-多页面(screen)设定/切换)根据实际可用API,可以考虑两种方案:

  • 通过FLAG(LV_OBJ_FLAG_HIDDEN)隐藏或者显示lv_obj_add_flag/lv_obj_clear_flag根UI控件
  • 通过管理child节点的对象来实现lv_obj_set_parent/lv_obj_get_child
  • 通过屏幕显示obj切换 lv_scr_load/lv_scr_load_anim

与参考文章不同的是,这里更建议使用1和2两种方式进行管理。具体场景如下:

  • 如果是简单页面,没有标题,页脚,侧边栏等复杂元素,建议使用3。
    优点:简单,可以自带动画。缺点:必须整个屏幕切换,重用性比较低。
  • 如果有复杂层次关系,即简单页面之外的需求,有两种选择:
    1 将所有同类别页面添加在同一个root点下,然后使用FLAG隐藏所有子页面,只显示需要的页面。优点:快速,层次关系明确。缺点:内存占用略高。(推荐这种)
    2 将所有同类别页面放在同一个数组下,每次设置子页面的parent为null,将需要显示的页面parent设置为root。优点:tree关系简单,内容占用可以优化。缺点:使用、管理节点麻烦。

lv_win实现了一个上下结构的基础windows框架,可以在此基础上进行扩充使用。(存在全局参数限制,参考使用)

一个页面切换的Demo实例(布局参考lv_win):

#include "demo1.h"
#include "lvgl/lvgl.h"lv_obj_t* gApp = NULL;
lv_style_t btnRectStyle;lv_obj_t* nav_btns[3];
lv_obj_t* nav_contents[3];void init_style() {lv_style_init(&btnRectStyle);lv_style_set_radius(&btnRectStyle, 0); // LV_RADIUS_CIRCLElv_style_set_border_width(&btnRectStyle, 0);lv_style_set_shadow_width(&btnRectStyle, 0);lv_style_set_pad_all(&btnRectStyle, 0);lv_style_set_outline_width(&btnRectStyle, 0);
}void nav_btns_cb(lv_event_t* e) {int idx = (int)lv_event_get_user_data(e);if ( idx>=0 && idx<3 ) {for (int i = 0; i < 3; i++) {lv_obj_add_flag(nav_contents[i], LV_OBJ_FLAG_HIDDEN);}// 显示对应的contentlv_obj_clear_flag(nav_contents[idx], LV_OBJ_FLAG_HIDDEN);}
}void init_app_home(lv_obj_t* pRoot) {    lv_obj_set_flex_flow(pRoot, LV_FLEX_FLOW_COLUMN);lv_obj_t* pUIHeader = lv_obj_create(pRoot);lv_obj_add_style(pUIHeader, &btnRectStyle, 0);lv_obj_set_size(pUIHeader, LV_PCT(100), 28);lv_obj_set_style_bg_color(pUIHeader, lv_color_hex(0x0D24F2), 0);lv_obj_t* pUIContent = lv_obj_create(pRoot);lv_obj_add_style(pUIContent, &btnRectStyle, 0);lv_obj_set_width(pUIContent, LV_PCT(100));lv_obj_set_flex_grow(pUIContent, 1);//lv_obj_set_style_bg_color(pUIContent, lv_color_hex(0xCCCCCC), 0);lv_obj_set_flex_flow(pUIContent, LV_FLEX_FLOW_ROW);// switch pageslv_obj_t* home_left = lv_obj_create(pUIContent);    lv_obj_set_size(home_left, 120, LV_PCT(100));lv_obj_t* home_right = lv_obj_create(pUIContent);lv_obj_add_style(home_left, &btnRectStyle, 0);lv_obj_set_size(home_right, 600, LV_PCT(100));lv_obj_set_flex_grow(home_right, 1);// 1. nav btnsfor (int i = 0; i < 3; i++) {nav_btns[i] = lv_btn_create(home_left);//lv_obj_set_style_bg_color(nav_btns[i], lv_color_make(0,0,200), 0);lv_label_set_text_fmt(lv_label_create(nav_btns[i]), "Btn-%d", i);lv_obj_set_size(nav_btns[i], 70, 30);lv_obj_set_pos(nav_btns[i], 5, 40*i+10);lv_obj_add_event_cb(nav_btns[i], nav_btns_cb, LV_EVENT_PRESSED, (void*)i);}// 2. contentfor (int i = 0; i < 3; i++) {nav_contents[i] = lv_label_create(home_right);lv_obj_set_size(nav_contents[i], 600, 400);lv_obj_set_pos(nav_contents[i], 0, 0);lv_label_set_text_fmt(nav_contents[i], "nav content: %d", i);lv_obj_add_flag(nav_contents[i], LV_OBJ_FLAG_HIDDEN);}// triger btn-0lv_event_send(nav_btns[0], LV_EVENT_PRESSED, 0);
}// 入口函数
void main_loop(void) {init_style();lv_obj_t* pScreen = lv_scr_act();gApp = lv_obj_create(pScreen);lv_obj_remove_style_all(gApp);lv_obj_set_size(gApp, LV_PCT(100), LV_PCT(100));init_app_home(gApp);}

全局主题定制

LVGL全局默认主题虽然很不错,但是带有太多的圆角等元素,为了使用方便,尝试定义一个自己的主题。

参考link:

  • https://forum.lvgl.io/t/how-to-create-custom-themes-in-lvgl-v8/7591
  • https://docs.lvgl.io/master/overview/style.html#extending-themes
  • https://docs.lvgl.io/master/overview/style.html#extending-the-current-theme

下面是定制theme的demo。它相当于hook了原来的主题,对所有button添加了新的style_btn。
V8版本没有一个办法能从头完全定制一个theme,需要在原来的theme上进行扩展/修改。
不同的screen可以有不同的theme。

static lv_style_t style_btn;/*Will be called when the styles of the base theme are already addedto add new styles*/
static void new_theme_apply_cb(lv_theme_t* th, lv_obj_t* obj)
{LV_UNUSED(th);if (lv_obj_check_type(obj, &lv_btn_class)) {lv_obj_add_style(obj, &style_btn, 0);}
}static void new_theme_init_and_set(void)
{/*Initialize the styles*/lv_style_init(&style_btn);lv_style_set_bg_color(&style_btn, lv_palette_main(LV_PALETTE_GREEN));lv_style_set_border_color(&style_btn, lv_palette_darken(LV_PALETTE_GREEN, 3));lv_style_set_border_width(&style_btn, 3);/*Initialize the new theme from the current theme*/lv_theme_t* th_act = lv_disp_get_theme(NULL);static lv_theme_t th_new;th_new = *th_act;/*Set the parent theme and the style apply callback for the new theme*/lv_theme_set_parent(&th_new, th_act);lv_theme_set_apply_cb(&th_new, new_theme_apply_cb);/*Assign the new theme the the current display*/lv_disp_set_theme(NULL, &th_new);
}void demo_my_test_1018(void)
{lv_obj_t* btn;lv_obj_t* label;btn = lv_btn_create(lv_scr_act());lv_obj_align(btn, LV_ALIGN_TOP_MID, 0, 20);label = lv_label_create(btn);lv_label_set_text(label, "Original theme");new_theme_init_and_set();btn = lv_btn_create(lv_scr_act());lv_obj_align(btn, LV_ALIGN_BOTTOM_MID, 0, -20);label = lv_label_create(btn);lv_label_set_text(label, "New theme");
}

默认的主题加载位置lv_disp_drv_register

#if LV_USE_THEME_DEFAULTif(lv_theme_default_is_inited() == false) {disp->theme = lv_theme_default_init(disp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED),LV_THEME_DEFAULT_DARK, LV_FONT_DEFAULT);}else {disp->theme = lv_theme_default_get();}
#endif

总结:

  • 主题定制走的是hook的路子,通过add style进行修改。
  • 修改默认使用的主题,参考lv_disp_drv_register函数,通过disp的theme修改。
  • 官方建议在basic的基础上修改,default内容太多。lvgl/src/extra/themes/basic,default,mono

心得总结

  • LVGL只适用页面不太多的场合,复杂UI项目尽可能考虑Linux下QT/GTK开发。
  • 页面管理,风格美化,字体图片资源,中文输入法等在正式项目中需要慎重设计和考虑。
  • UI初版可借助GUI工具 GUI Guider 或者 SquareLine Studio
  • LVGL代码缺少很多注释,文档也比较简略,论坛能解决问题有限。建议遇到问题时,多翻翻src文件夹,参看类似UI的实现。

有一个比较火的开源项目参考: 开源GPS自行车码表 X-TRACK

PS: 后续有机会了做一个基于STM32F4的综合Demo。

嵌入式UI框架 LVGL 学习笔记 02 页面管理和主题定制相关推荐

  1. 2021年3月8日:MyBatis框架学习笔记02:利用MyBatis实现CRUD操作

    MyBatis框架学习笔记02:利用MyBatis实现CRUD操作 在第一节课中我们在UserMapper.xml里定义了两个查询语句:findById和findAll,对应的在UserMapper接 ...

  2. 大数据Hadoop教程-学习笔记02【Apache Hadoop、HDFS】

    视频教程:哔哩哔哩网站:黑马大数据Hadoop入门视频教程 教程资源:https://pan.baidu.com/s/1WYgyI3KgbzKzFD639lA-_g 提取码: 6666 [P001-P ...

  3. JavaWeb黑马旅游网-学习笔记02【注册功能】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...

  4. JavaWeb-综合案例(用户信息)-学习笔记02【登录功能】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb-综合案例(用户信息)-学习笔记01[列表查询] JavaWeb-综合案例(用户信息)-学习笔记02[登录功能] JavaWeb-综合案 ...

  5. HTML/CSS学习笔记02【表单标签】

    w3cschool菜鸟教程.CHM(腾讯微云):https://share.weiyun.com/c1FaX6ZD HTML/CSS学习笔记01[概念介绍.基本标签.表单标签][day01] HTML ...

  6. MySQL技术内幕-InnoDB存储引擎第2版-学习笔记-02

    MySQL技术内幕-InnoDB存储引擎第2版-学习笔记-02 6. 锁 ​ 人们认为行级锁总会增加开销.实际上,只有当实现本身会增加开销时,行级锁才会增加开销.InnoDB 存储引擎不需要锁升级,因 ...

  7. Servlet和HTTP请求协议-学习笔记02【Servlet_体系结构与urlpartten配置、HTTP请求协议】

    Java后端 学习路线 笔记汇总表[黑马程序员] Servlet和HTTP请求协议-学习笔记01[Servlet_快速入门-生命周期方法.Servlet_3.0注解配置.IDEA与tomcat相关配置 ...

  8. Tomcat学习笔记02【Tomcat部署项目】

    Java后端 学习路线 笔记汇总表[黑马程序员] Tomcat学习笔记01[Web相关概念.Tomcat基本操作][day01] Tomcat学习笔记02[Tomcat部署项目][day01] 目录 ...

  9. XML学习笔记02【xml_解析】

    Java后端 学习路线 笔记汇总表[黑马程序员] XML学习笔记01[xml_基础.xml_约束][day01] XML学习笔记02[xml_解析][day01] 目录 03 xml_解析 xml_解 ...

  10. Bootstrap学习笔记02【全局CSS样式、组件和插件、案例_黑马旅游网_首页】

    Java后端 学习路线 笔记汇总表[黑马程序员] Bootstrap学习笔记01[快速入门.栅格布局][day01] Bootstrap学习笔记02[全局CSS样式.组件和插件.案例_黑马旅游网][d ...

最新文章

  1. c语言程序设计日历推后几天是星期几,C语言程序设计: 输入年月日 然后输出是星期几...
  2. Windows 10截屏动画失效怎么恢复?
  3. Java——容器(Set)
  4. Python Tricks —— 使用 pywinrm 远程控制 Windows 主机
  5. ES6学习笔记03:变量的解构赋值
  6. override和overload
  7. 妙啊,小米11保护壳先小米11一步上市了...
  8. python意外退出_有趣的Python上下文管理器
  9. electronjs设置宽度_electronjs 入门_2019年2月14日
  10. 自定义设置HTTP响应头
  11. mysql 等待函数,mysql 函数
  12. 【mud】call_out()函数
  13. .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态
  14. 企业数智化升级的四个“拦路虎”
  15. html直线箭头,HTML中利用div+CSS实现简单的箭头图标的代码
  16. ADI-SigmaDSP开发入门
  17. PLC SECS/GEM解决方案,设计与应用
  18. 想精通单片机开发,这些必备基础知识不可不掌握
  19. Unity打包自定义分辨率问题解决
  20. java与python之间的混合开发

热门文章

  1. 19 C++ 特殊工具与技术
  2. promise回顾和总结(温故知新)
  3. 2022年G3锅炉水处理考试练习题及模拟考试
  4. linux桌面版如何配置,技术|如何为 Linux 桌面配置 Openbox
  5. R语言 R包:mFD 计算与分析功能多样性的一站式综合性
  6. CNN基础和进展(上)
  7. ZCMU--4981: Problem H. zbj的回家之路
  8. leetcode每日一题链表有环无环链表长度求解
  9. Valine一款快速、简洁且高效的无后端评论系统
  10. 人体检测 算法 python_Tensorflow——用openpose进行人体骨骼检测