0


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

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];voidinit_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);}voidnav_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);}}voidinit_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);}// 入口函数voidmain_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:

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

staticlv_style_t style_btn;/*Will be called when the styles of the base theme are already added
  to add new styles*/staticvoidnew_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);}}staticvoidnew_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);staticlv_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);}voiddemo_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

#ifLV_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 学习

本文转载自: https://blog.csdn.net/bbdxf/article/details/127753605
版权归原作者 笨笨D幸福 所有, 如有侵权,请联系我们删除。

“嵌入式UI框架 LVGL 学习笔记 02 页面管理和主题定制”的评论:

还没有评论