LittleVGL

目录

1、视频快速入门 

2、普中开发板移植LVGL

3、lvgl移植正点原子视频

4、各个控件的学习

5、GUI-GURDER

5.1简单计算机的实现逻辑

6、多屏幕切换、动画

6.1多屏幕切换

6.2动画

6.3事件冒泡

6.4GUI-Guider编写事件回调

​编辑6.5GUI-Guider生成的代码移植CodeBlocks

7、页面逻辑实现

8、mune菜单控件

8.1 content容器铺满问题

8.2 menu相关

8.3编码器

9、主题模式

10、conf文件

11、布局

 12、滚动条

 13、动画

 14、常用函数

14.1 获取控件长宽高

 15、参考博文


1、视频快速入门 

快速入门LVGL(基于STM32,LVGL 8.2.0)_mucherry的博客-CSDN博客_lvgl

十几分钟学会如何使用lvgl设计器gui guider和模拟器编写一个简单计算器应用_哔哩哔哩_bilibili

SquareLine Studio

STM32移植LVGL8.0.2超详细的保姆级教程附移植好的工程文件_保哥在江湖的博客-CSDN博客_stm32移植lvgl

图表 (Chart) - 5寸金牛座开发板

Tips:按住Ctrl快速一起重命名

2、普中开发板移植LVGL

移植过程按1中的视频移植,但未能成功显示数Demo,怀疑是disp_flush需要调用底层lcd操作接口不对与视频中调用的函数不一样,再度查找分析果然是,要替换成另外一个函数。

LittleVGL_第1张图片

typedef union {
    struct {
        uint16_t blue  : 5;
        uint16_t green : 6;
        uint16_t red   : 5;
    } ch;
    uint16_t full;
} lv_color16_t;
typedef lv_color16_t lv_color_t;

LittleVGL_第2张图片

参考文章:https://www.eefocus.com/article/484678.html

 EmbedSummary: 嵌入式大杂烩资源汇总

Data:22.12.25

LVGL学习笔记:恩智浦gui guider+Platformio+ESP32 示例 - 哔哩哔哩

LVGL学习笔记_William_Zhang_csdn的博客-CSDN博客_lvgl

3、lvgl移植正点原子视频

Codeblocks快捷键 | Ctrl

第7讲 基础篇-LVGL移植(无操作系统4)_哔哩哔哩_bilibili

LVGL 8.2 菜单-pudn.com

Free Icons, Clipart Illustrations, Photos, and Music

LVGL+SMT32的项目练习(多图) - 个人小站

4、各个控件的学习

事件回调函数的 lv_event_t * e参数 

获取触发的事件代码:lv_event_code_t code = lv_event_get_code(e);

获取触发事件的对象:lv_obj_t * target = lv_event_get_target(e);

设置背景颜色:lv_obj_set_style_bg_color( label, lv_color_hex(0xffe1d4), LV_STATE_DEFAULT );

设置字体大小:lv_obj_set_style_text_font( label, &lv_font_montserrat_30, LV_STATE_DEFAULT );
 设置文本颜色:lv_obj_set_style_text_color( label, lv_color_hex(0xf7b37b),LV_STATE_DEFAULT );

开启重新着色功能 :lv_label_set_recolor( label, true );

 单独设置颜色:lv_label_set_text( label, "hallo #ff0000 lvgl# " );

设置长文本模式:lv_label_set_long_mode(label, LV_LABEL_LONG_...);

 开启状态切换 :lv_obj_add_flag( btn, LV_OBJ_FLAG_CHECKABLE ); 

添加状态:默认打开且不可修改:lv_obj_add_state(switch1, LV_STATE_CHECKED | LV_STATE_DISABLED);

清除开关的状态:lv_obj_clear_state(switch1, LV_STATE_CHECKED | LV_STATE_DISABLED);   

获取(判断)开关状态:lv_obj_has_state(switch1, LV_STATE_CHECKED) /* 返回值:1,选中; 0,非选中 */

设置文本和勾选框的间距:lv_obj_set_style_pad_column( checkbox, 20, LV_STATE_DEFAULT );

checkbox和btn 用的是 LV_EVENT_VALUE_CHANGED

可以设置的有应用的状态、应用的部分

------------------------------------------------------label--------------------------------------------------------- LittleVGL_第3张图片

直接设置文本:lv_label_set_text( label, "hallo \n lvgl");
文本不存储在动态内存,而是在指定的缓冲区中(慎用):lv_label_set_text_static( label,"hallo" );
格式化显示文本,类似printf :lv_label_set_text_fmt( label, “Value: %d”, 50 ) ;
背景颜色:lv_obj_set_style_bg_color( label, lv_color_hex(0xffe1d4), LV_STATE_DEFAULT );
字体大小:lv_obj_set_style_text_font( label, &lv_font_montserrat_30, LV_STATE_DEFAULT );
文本颜色:lv_obj_set_style_text_color( label, lv_color_hex(0xf7b37b), LV_STATE_DEFAULT );
开启重新着色功能 :lv_label_set_recolor( label, true ); 
单独设置颜色 :lv_label_set_text( label, "hallo #ff0000 lvgl# " );
长文本模式:lv_label_set_long_mode(label, LV_LABEL_LONG_...);


enum {
    LV_LABEL_LONG_WRAP,                     /* 默认模式, 如果部件大小已固定,超出的文本将被剪切 */
    LV_LABEL_LONG_DOT,                      /* 将 label 右下角的最后 3 个字符替换为点… */
    LV_LABEL_LONG_SCROLL,                   /* 来回滚动 */
    LV_LABEL_LONG_SCROLL_CIRCULAR,      /* 循环滚动 */
    LV_LABEL_LONG_CLIP,                     /* 直接剪切掉部件外面的文本部分 */
}

------------------------------------------------------btn--------------------------------------------------------- LittleVGL_第4张图片LittleVGL_第5张图片 

 开启状态切换 :lv_obj_add_flag( btn, LV_OBJ_FLAG_CHECKABLE );

------------------------------------------------------switch--------------------------------------------------------- 

LittleVGL_第6张图片

添加状态:默认打开且不可修改 :lv_obj_add_state(switch1, LV_STATE_CHECKED | LV_STATE_DISABLED);
清除开关的状态 :lv_obj_clear_state(switch1, LV_STATE_CHECKED | LV_STATE_DISABLED);
获取(判断)开关状态:lv_obj_has_state(switch1, LV_STATE_CHECKED)      /* 返回值:bool类型,开 :1;关: 0 */

 ------------------------------------------------------checkbox--------------------------------------------------------- 

LittleVGL_第7张图片

设置文本内容 :lv_checkbox_set_text( checkbox, "remember the password" );
设置文本和勾选框的间距 :lv_obj_set_style_pad_column( checkbox, 20, LV_STATE_DEFAULT ); 添加、清除复选框状态:
lv_obj_add_state(checkbox, LV_STATE_CHECKED | LV_STATE_DISABLED);    /* 添加状态:默认选中且不可修改 */
lv_obj_clear_state(checkbox, LV_STATE_CHECKED | LV_STATE_DISABLED);    /* 清除复选框的状态 */
获取(判断)复选框状态:lv_obj_has_state(checkbox, LV_STATE_CHECKED);    /* 返回值:1,选中; 0,非选中 */

------------------------------------------------------bar---------------------------------------------------------LittleVGL_第8张图片

设置当前值:lv_bar_set_value( bar, 50, LV_ANIM_ON );   /*LV_ANIM_ON : 动画开*/
设置范围值: lv_bar_set_range( bar, -100, 100 );
设置动画时间:lv_obj_set_style_anim_time( bar, 500, LV_STATE_DEFAULT ); /* 动画设置必须放在当前值设置之前 */
设置模式 :lv_bar_set_mode( bar, LV_BAR_MODE_RANGE );
设置起始值 :lv_bar_set_start_value( bar, -50, LV_ANIM_OFF );                                                设置定时器lv_timer_create(progress_bar_cb,100,NULL);


enum {
    LV_BAR_MODE_NORMAL,            /* 默认模式 */
    LV_BAR_MODE_SYMMETRICAL,        /* 从零值绘制到当前值(当前值可以小于0) */
    LV_BAR_MODE_RANGE            /* 允许设置起始值,但起始值必须小于当前值 */
};
注意:在V8.2版本的LVGL中,默认模式也允许设置起始值,但是后续的版本可能会修改。                动画时间指的是旧值刷新到新值的绘图时间,并不是现实中当前值变化所需的时间

------------------------------------------------------spinner---------------------------------------------------------LittleVGL_第9张图片

主体:LV_PART_MAIN
指示器:LV_PART_INDICATOR
手柄:LV_PART_KNOB
创建加载器部件:lv_obj_t   *spinner  = lv_spinner_create( parent, spin_time, arc_length );
设置圆弧颜色:lv_obj_set_style_arc_color( spinner, lv_color_hex(0x4a9f00), LV_PART_MAIN ); 
设置圆弧宽度:lv_obj_set_style_arc_width( spinner, 30, LV_PART_MAIN );    
------------------------------------------------------LED---------------------------------------------------------  LittleVGL_第10张图片

创建LED部件 :lv_obj_t   *led = lv_led_create( parent );
设置LED颜色 :lv_led_set_color( led, lv_color_hex(0xff0000) );
设置LED亮度,范围0~255:lv_led_set_brightness( led, 0 );    
打开LED(设置亮度为255):lv_led_on( led );
关闭LED :lv_led_off( led );
翻转LED状态 :lv_led_toggle( led );
快速居中:lv_obj_center();

------------------------------------------------------list---------------------------------------------------------  

LittleVGL_第11张图片

LittleVGL_第12张图片

创建列表部件 :lv_obj_t   *list = lv_list_create( parent );
添加列表文本:lv_list_add_text( list, “Settings" );
添加列表按钮:lv_obj_t  *btn= lv_list_add_btn( list, LV_SYMBOL_WIFI, “WLAN"); 
获取列表按钮文本:lv_list_get_btn_text( list, list_btn );
手动更新物体的参数:lv_obj_update_layout(obj_1);
添加按下的选中聚焦状态:lv_obj_add_state(btn,LV_STATE_FOCUS_KEY);

------------------------------------------------------dropdown---------------------------------------------------  

LittleVGL_第13张图片

设置选项:lv_dropdown_set_options( dd, "a\nb\nc\nd");
设置选项 (静态):lv_dropdown_set_options_static( dd, "a\nb\nc\nd ");
添加选项,索引从0开始 :lv_dropdown_add_option( dd, "e", 4);    /*不能使用lv_dropdown_set_options_static设置的*/
设置当前所选项:lv_dropdown_set_selected( dd, 1);
获取索引:lv_dropdown_get_selected( dd);
获取选项文本:lv_dropdown_get_selected_str( dd, buf, sizeof(buf));     char buf[10];
设置列表展开方向 :lv_dropdown_set_dir(dd, LV_DIR_RIGHT);
设置图标 :lv_dropdown_set_symbol(dd, LV_SYMBOL_RIGHT);

------------------------------------------------------roller---------------------------------------------------LittleVGL_第14张图片

设置选项间隔:lv_obj_set_style_text_line_space(roller, 30, LV_STATE_DEFAULT);    
设置选项内容、滚动模式:lv_roller_set_options(roller, “a\nb\nc\nd”, LV_ROLLER_MODE_NORMAL);         /* 正常模式 */
设置当前所选项:lv_roller_set_selected(roller, 3, LV_ANIM_ON);
设置可见行数:lv_roller_set_visible_row_count(roller, 2);
获取索引 :lv_roller_get_selected(roller);    
获取选项文本 :lv_roller_get_selected_str(roller, buf, sizeof(buf));   char buf[10];

------------------------------------------------------slider--------------------------------------------------- LittleVGL_第15张图片

 设置当前值 :lv_slider_set_value(slider, 50, LV_ANIM_OFF);
设置范围值 :lv_slider_set_range(slider, -100, 100);  
获取当前值:lv_slider_get_value(slider);
模式设置:lv_slider_set_mode(slider, LV_SLIDER_MODE_...);   NORMAL、SYMMETRICAL、RANGE
设置左值:lv_slider_set_left_value(slider, 20, LV_ANIM_OFF);
获取左值:lv_slider_get_left_value(slider); 

------------------------------------------------------arc--------------------------------------------------- LittleVGL_第16张图片

LittleVGL_第17张图片

设置当前值(需要在范围值之内):lv_arc_set_value(arc, 80);    
设置范围值 :lv_arc_set_range(arc, 0, 200);  
设置前景弧角度 :lv_arc_set_angles(arc, 135, 270);   //在此之前应该先设置背景弧 、且不要与设置当前值混用,他并不会改变数值,这是改变样式
设置背景弧角度 :lv_arc_set_bg_angles(arc, 135, 45);  
设置旋转角度:lv_arc_set_rotation(arc, 180);
获取当前值:lv_arc_get_value(arc);
设置模式:lv_arc_set_mode(arc, LV_ARC_MODE_REVERSE);
绘制速率,90°/秒 :lv_arc_set_change_rate(arc, 90);
设置背景弧宽度:lv_obj_set_style_arc_width(arc_1,20,LV_PART_MAIN);
设置前景弧宽度:lv_obj_set_style_arc_width(arc_1,20,LV_PART_INDICATOR);
去掉旋钮:lv_obj_remove_style(arc_2,NULL,LV_PART_KNOB);
去掉可点击属性:lv_obj_clear_flag(arc_2,LV_OBJ_FLAG_CLICKABLE);

------------------------------------------------------line--------------------------------------------------- 

LittleVGL_第18张图片

设置线条坐标点:static lv_point_t  line_points[] = { {15, 5}, {25, 20}, {5, 20}, {15, 5} };
lv_line_set_points(line, line_points, 4);    
设置宽度 :lv_obj_set_style_line_width(line, 8, LV_PART_MAIN); 
设置圆角 :lv_obj_set_style_line_rounded(line, true, LV_PART_MAIN);
设置y轴反转:lv_line_set_y_invert(line, true);

------------------------------------------------------img--------------------------------------------------- 

LittleVGL_第19张图片

声明图片 :LV_IMG_DECLARE(img_bird);
设置图片源 :lv_img_set_src(img, &img_bird);   // 在此前要先声明图片
设置图片偏移:lv_img_set_offset_x(img, 100);
           lv_img_set_offset_y(img, 20); 
图片重新着色:lv_obj_set_style_img_recolor(img, lv_color_hex(0xffe1d2), LV_PART_MAIN); 
           lv_obj_set_style_img_recolor_opa(img, 150, LV_PART_MAIN);
设置图片缩放:lv_img_set_zoom(img, 512);    /* 放大2倍 */
设置图片旋转:lv_img_set_angle(img, 900);    /* 顺时针方向旋转90° */
设置中心点:
    lv_obj_update_layout(img);        /* 更新图片布局信息 */
    lv_img_set_pivot(img, 0, 0);        /* 设置中心点 */
设置滑块主体颜色、透明度:lv_obj_set_style_bg_color(slider,lv_color_darken(color, 100),LV_PART_MAIN);   
更新图片参数:lv_obj_update_layout(img);   

------------------------------------------------------colorwheel--------------------------------------------------- 

LittleVGL_第20张图片

LittleVGL_第21张图片

设置当前选中颜色:lv_colorwheel_set_rgb(cw, lv_color_hex(0xff0000));
获取当前选中颜色:lv_colorwheel_get_rgb(cw);
设置色环模式:
    色相、饱和度、明度: lv_colorwheel_set_mode(cw, LV_COLORWHEEL_MODE_HUE/SATURATION/VALUE);
    固定色环模式 :lv_colorwheel_set_mode_fixed(cw, true);
 ------------------------------------------------------btnmatrix--------------------------------------------------- 

LittleVGL_第22张图片

LittleVGL_第23张图片

定义按钮数组,最后一个元素必须为空 :static const char *map[] = { "btn1", "\n", "btn2", "btn3", "" };
设置按钮 :lv_btnmatrix_set_map(btnm, map);
设置按钮相对宽度:lv_btnmatrix_set_btn_width(btnm, id, width);        /* 索引 (id) 从0开始,宽度1~7 ( 默认为1 ) */
获取索引 :lv_btnmatrix_get_selected_btn(btnm);    
获取文本 :lv_btnmatrix_get_btn_text(btnm, id);
设置单个按钮属性 :lv_btnmatrix_set_btn_ctrl(btnm, id, LV_BTNMATRIX_CTRL_...);
清除单个按钮属性 :lv_btnmatrix_clear_btn_ctrl(btnm, id, LV_BTNMATRIX_CTRL_...);    
设置所有按钮属性 :lv_btnmatrix_set_btn_ctrl_all(btnm, LV_BTNMATRIX_CTRL_...);

enum {
    LV_BTNMATRIX_CTRL_HIDDEN,                     /* 隐藏 */
    LV_BTNMATRIX_CTRL_DISABLED,                    /* 失能 */
    LV_BTNMATRIX_CTRL_CHECKABLE,                     /* 允许状态切换 */
    LV_BTNMATRIX_CTRL_RECOLOR,                     /* 允许文本重新着色 */
};
设置单次选中属性:lv_btnmatrix_set_one_checked(btnm, true);         /* 注意:需要先设置允许状态切换属性 */

* 按钮矩阵(优化界面) */
    lv_obj_set_style_border_width(btnm, 0, LV_PART_MAIN);                                       /* 去除主体边框 */
    lv_obj_set_style_bg_opa(btnm, 0, LV_PART_MAIN);                                             /* 设置主体背景透明度 */
    lv_obj_set_style_bg_opa(btnm, 0, LV_PART_ITEMS);                                            /* 设置按钮背景透明度 */
    lv_obj_set_style_shadow_width(btnm, 0, LV_PART_ITEMS);                                      /* 去除按钮阴影 */
    lv_obj_add_event_cb(btnm, b

 ------------------------------------------------------textarea--------------------------------------------------- 

LittleVGL_第24张图片

 添加一个字符到当前光标处 :lv_textarea_add_char(ta, 'A');
添加字符串到当前光标处 :lv_textarea_add_text(ta, "BCDEF"); 
创建键盘部件 :lv_obj_t *keyboard = lv_keyboard_create(lv_scr_act());
关联键盘和文本区域部件 :lv_keyboard_set_textarea(keyboard, ta);
设置光标位置:lv_textarea_set_cursor_pos(ta, 0);          /* 0:最左侧, LV_TEXTAREA_CURSOR_LAST:最右侧 */
删除文本:
    lv_textarea_del_char(ta);            /* 删除光标左侧的一个字符 */
    lv_textarea_del_char_forward(ta);        /* 删除光标右侧的一个字符 */
设置模式:
    lv_textarea_set_one_line(ta, true);        /* 单行模式 */
    lv_textarea_set_password_mode(ta, true);        /* 密码模式(隐藏输入的内容) */
    lv_textarea_set_password_show_time(ta, 100);    /* 密码显示时间 */
限制字符输入:
    lv_textarea_set_accepted_chars(ta,"0123456789");     /* 限制接收的字符 */
    lv_textarea_set_max_length(ta,6);        /* 限制字符长度 */
设置占位符:lv_textarea_set_placeholder_text(ta, "password");     /* 提示输入密码 */
获取文本:const char *txt = lv_textarea_get_text(ta);        /* 获取文本框文本 */ 
比对文本内容:strcmp(const char *s1,const char *s2);        /* 当s1=s2时,返回0 */
创建键盘:keyboard = lv_keyboard_create(lv_scr_act());
关联用户名文本框和键盘:lv_keyboard_set_textarea(keyboard, target);

 ------------------------------------------------------keyboard---------------------------------------------------  

LittleVGL_第25张图片创建文本区域部件 :lv_obj_t *ta = lv_textarea_create(lv_scr_act());
关联键盘和文本区域部件 :lv_keyboard_set_textarea(kb, ta);
允许按键弹窗提示 :lv_keyboard_set_popovers(kb, true);
数字键盘模式 :lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_NUMBER);
获取模式:lv_keyboard_get_mode(target); 

 ------------------------------------------------------imgbtn--------------------------------------------------- 

LittleVGL_第26张图片

LittleVGL_第27张图片

设置某个状态的图片源 :lv_imgbtn_set_src(imgbtn, LV_IMGBTN_STATE_..., src_left, src_mid, src_right);  //可以同时设置三张
设置图片按钮大小 :lv_obj_set_size(imgbtn, 64 * 3, 64);    
设置按下状态 :lv_imgbtn_set_state(imgbtn, LV_IMGBTN_STATE_PRESSED);
如何显示带有透明度通道的图片:准备一张带有透明度通道的图片,然后重新着色并设置透明度为255。
设置图片重新着色透明度: lv_obj_set_style_img_recolor_opa(target, 255, 0); 
设置图片重新着色 :lv_obj_set_style_img_recolor(target, lv_color_hex(0x00a9ff), 0); 

 ------------------------------------------------------tabview--------------------------------------------------- 

LittleVGL_第28张图片

LittleVGL_第29张图片

创建选项卡部件 :lv_obj_t  *tabview =  lv_tabview_create(parent, LV_DIR_..., tab_size);
添加选项卡:lv_obj_t *tab1 = lv_tabview_add_tab(tabview, "Tab 1"); 
设置当前选中的选项卡:lv_tabview_set_act(tabview, 1, LV_ANIM_OFF);      /* 索引从0开始 */
未选中部分:LV_STATE_DEFAULT例如将一个字体应用到全部的部分
选中部分:LV_STATE_CHECKED
设置按钮边框宽度为0:lv_obj_set_style_border_width(btn, 0, LV_PART_ITEMS| LV_STATE_CHECKED);
获取按钮部分:lv_obj_t *btn = lv_tabview_get_tab_btns(tabview); 
获取主体部分:lv_obj_t *obj = lv_tabview_get_content(tabview); 
清除滑动:lv_obj_clear_flag(lv_tabview_get_content(tabview), LV_OBJ_FLAG_SCROLLABLE);
LV_PART_ITEMS:按键 

------------------------------------------------------tileview--------------------------------------------------- 

LittleVGL_第30张图片创建平铺视图部件 :lv_obj_t  *tileview = lv_tileview_create( parent );
添加页面:lv_obj_t *tile1 = lv_tileview_add_tile( tileview, 0, 0, LV_DIR_RIGHT );
更新参数 :lv_obj_update_layout( tileview );
根据页面对象设置 :lv_obj_set_tile( tileview, tile2, LV_ANIM_OFF );
根据页面行列设置 :lv_obj_set_tile_id( tileview, 1, 0, LV_ANIM_OFF );
同时设置多少文字:lv_label_set_text(label_left,LV_SYMBOL_WIFI "  80%" LV_SYMBOL_BATTERY_3); 

------------------------------------------------------win---------------------------------------------------  

LittleVGL_第31张图片

LittleVGL_第32张图片

创建窗口部件 :lv_obj_t *win = lv_win_create(parent, header_height);
添加标题:lv_obj_t *title = lv_win_add_title(win, "Setting");
添加按钮:lv_obj_t *btn = lv_win_add_btn(win, LV_SYMBOL_CLOSE, 20);
添加主体内容:
      获取主体 :lv_obj_t *content = lv_win_get_content(win); 
      添加内容 :lv_obj_t *label = lv_label_create(content);    
隐藏窗口:lv_obj_add_flag(win, LV_OBJ_FLAG_HIDDEN);
清除显示:lv_obj_clear_flag(win,LV_OBJ_FLAG_HIDDEN);
设置按键符号的颜色要用设置文本:lv_obj_set_style_text_color(btn_setting, lv_color_hex(0x000000), LV_STATE_DEFAULT);         /* 设置文本颜色 */ 

------------------------------------------------------msgbox---------------------------------------------------  

LittleVGL_第33张图片

 LittleVGL_第34张图片

 创建消息框部件 :
    static const char *btns[] = { "Continue", "Close", "" };
    lv_obj_t *msgbox = lv_msgbox_create( lv_scr_act(), "Notice", "Do you want to continue?", btns, true );
关闭消息框:lv_msgbox_close(msgbox);
获取按钮索引、文本:
    lv_obj_t *target = lv_event_get_current_target(e);    /* 获取当前触发源  用的是current_target 用_target会错误*/
    lv_msgbox_get_active_btn(target);/* 获取按钮索引 */
    lv_msgbox_get_active_btn_text(target);    /* 获取按钮文本 */
获取两个之中最小的:LV_MIN(lv_obj_get_width(obj);
记得更新,否则加载不出:lv_obj_update_layout(msgbox_obj); 
       lv_style_set_radius(&style_bullet, LV_RADIUS_CIRCLE);        //设置半径,传入'LV_RADIUS_CIRCLE'智能判断绘制为圆形
或者回调函数传入的用户数据:lv_obj_ * obj_color = (lv_obj_t *)e->user_data;
消息部件隐藏不用的按键:
      lv_obj_set_style_bg_opa(btn,0,LV_PART_ITEMS);
      lv_obj_set_style_shadow_width(btn,0,LV_PART_ITEMS);

------------------------------------------------------spinbox---------------------------------------------------  

LittleVGL_第35张图片

 LittleVGL_第36张图片

创建微调器部件 :lv_obj_t *spinbox = lv_spinbox_create(parent);
数值递增:lv_spinbox_increment(spinbox);    
数值递减:lv_spinbox_decrement(spinbox);
设置步进值:lv_spinbox_set_step(spinbox, 200);/* 设置步进值,默认为1*/
设置范围值:lv_spinbox_set_range(spinbox, -1000, 1000);/* 设置范围值,默认±99999*/
设置当前值:lv_spinbox_set_value(spinbox, 400);
设置数字格式:lv_spinbox_set_digit_format(spinbox, 4, 2); /* 设置数字位数、小数点位置 */
设置光标位置:lv_spinbox_set_pos(spinbox, 3);   //使用该函数就不要使用设置步进值函数
获取当前值:lv_spinbox_get_value(spinbox);/* 返回值为整数,而非小数 */    
在按键上添加图片:lv_obj_set_style_bg_img_src(spinbox_btn1,LV_SYMBOL_PLUS,LV_PART_MAIN);
整数化成小数形式: lv_label_set_text_fmt(parameter,"%s%d.%d",
                          spinbox_value < 0 ? "-":"+",
                          spinbox_value / 10 < 0 ? -spinbox_value /10 : spinbox_value/10,
                          spinbox_value % 10 < 0 ? -spinbox_value % 10 : spinbox_value % 10);

------------------------------------------------------table---------------------------------------------------   

LittleVGL_第37张图片

LittleVGL_第38张图片

创建表格部件 :lv_obj_t *table = lv_table_create(parent);
设置行数:lv_table_set_row_cnt(table,2); 
设置列数:lv_table_set_col_cnt(table,2); 
设置列的宽度 :lv_table_set_col_width(table, 1, 200); 
设置单元格的内容:lv_table_set_cell_value(table, 0, 0, "123");
格式化输入,类似printf :lv_table_set_cell_value_fmt(table, 1, 0, "%d", 100 );

#if 的用法:
#if (1 != LV_FONT_MONTSERRAT_38 || 1 != LV_FONT_MONTSERRAT_18 || 1 != LV_FONT_MONTSERRAT_20)
#error Please Make Sure Enable LV_FONT_MONTSERRAT_14 & LV_FONT_MONTSERRAT_18 & LV_FONT_MONTSERRAT_20
#endif

第一次见的算法:
 for (uint8_t i = 1; i < (10 >> 1) + 1; i++)
        lv_table_set_cell_value_fmt(table, 2 * i, 1, "Value %d", i - 1);
 for (uint8_t i = 1; i < (10 >> 1) + 2; i++)
        lv_table_set_cell_value_fmt(table, 2 * i - 1, 1, "Hide %d", i - 1);

Data:23.1.10

5、GUI-GURDER

 GUI GUIDER 应用笔记_MR_普罗米修斯的博客-CSDN博客_gui guider

LVGL-GUI Guider初始体验_云海无语的博客-CSDN博客_gui-guider

LVGL | GUI-Guider的使用分享_嵌入式大杂烩的博客-CSDN博客_gui-guider

十几分钟学会如何使用lvgl设计器gui guider和模拟器编写一个简单计算器应用_哔哩哔哩_bilibili

快速入门入LVGL第四期--Gui-Guuder使用_哔哩哔哩_bilibili

南山府嵌入式的博客_CSDN博客-玩转STM32基础篇,FreeRTOS基础知识篇,分享领域博主

TIP:使用VScode编译并运行时因为系统环境变量有mingw 的编译器导致编译失败

LittleVGL_第39张图片

 LittleVGL_第40张图片

 去掉之前即可,但用VScode编译运行速度不如GUI-guider,故此后面不要VScode编译运行。

5.1简单计算机的实现逻辑

LittleVGL_第41张图片

/**
 * @file custom.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include 
#include "lvgl.h"
#include "custom.h"

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/

/**********************
 *  STATIC VARIABLES
 **********************/

/**
 * Create a demo application
 */

static int get_result(int old,int oper,int value)
{
    int result = 0;
    switch (oper)
    {
    case 0:
        result = value;
        break;
    case 3:
        result = old + value;
        break;
    case 7:
        result = old - value;
        break;
    case 11:
        result = old*value;
        break;
    case 15:
        result = old/value;
        break;
    default:
        break;
    }
    return result;
}
void text_cb(lv_event_t* e)
{
    lv_ui * ui = lv_event_get_user_data(e);
    uint8_t id = lv_btnmatrix_get_selected_btn(ui->screen_btnm_1);
    const char * txt = lv_btnmatrix_get_btn_text(ui->screen_btnm_1,id);

    static int old = 0;
    static int oper = 0;
    int value = 0;
    static char num[10] = {0};


    switch (id)
    {
    case 3:
        printf("+\n");
        
    case 7:
        printf("-\n");
    case 11:
        printf("x\n");
    case 15:
        printf("/\n");
        sscanf(num,"%d",&value);                                //将现在显示的数字提取出来
        old = get_result(old,oper,value);                       //之前的内容运算出结果并保存
        lv_label_set_text_fmt(ui->screen_label_1,"%d",old);     //把之前的运算结果显示出
        oper = id ;                                             //保存当前的运算符
        memset(num,0,sizeof(num));                              //清空之前记录的显示缓存
        break;
    case 14:
        printf("=\n");
        sscanf(num,"%d",&value);                     //将现在显示的数字提取出来
        old = get_result(old,oper,value);            //之前的内容运算出结果并保存
        lv_label_set_text_fmt(ui->screen_label_1,"%d",old);   //把之前的运算结果显示出
        oper = 0 ;                                   //清空运算符
        old = 0;                                     //清空历史记录
        memset(num,0,sizeof(num));                   //清空之前记录的显示缓存
        break;
    case 12:
        printf("clean\n");
        lv_label_set_text(ui->screen_label_1,"");   //清除显示
        oper = 0 ;                                  //清空运算符
        old = 0;                                    //清空历史记录
        memset(num,0,sizeof(num));                  //清空之前记录的显示缓存
        break;
    default:
        printf("%s\n",txt);
        if (strlen(num)screen_label_1,num);
        }
        
        break;
    }
}

void custom_init(lv_ui *ui)
{
    /* Add your codes here */
    lv_obj_add_event_cb(ui->screen_btnm_1,text_cb,LV_EVENT_PRESSED,ui);
}

23.1.5

6、多屏幕切换、动画

lvgl-多页面

6.1多屏幕切换

LittleVGL_第42张图片

   /********tow_scr*************/
lv_obj_t * Scr_mainMenu;
lv_obj_t * Scr_wifi;
void Scr_1_cb(lv_event_t * e)
{
     lv_event_code_t code = lv_event_get_code(e);
     if(code == LV_EVENT_CLICKED)
     {
         /*设置页面加载动画*/
         lv_scr_load_anim(Scr_wifi, LV_SCR_LOAD_ANIM_NONE, 100, 0, false);
         lv_scr_load(Scr_wifi);
     }
}

void my_gui()
{
#if 1
    /********tow_scr*************/
    /*创建页面*/
    Scr_mainMenu = lv_obj_create(NULL);
    lv_obj_clean(Scr_mainMenu);
    lv_obj_remove_style_all(Scr_mainMenu);
    lv_obj_set_style_bg_opa(Scr_mainMenu, LV_OPA_COVER, 0);//0不透明
    lv_obj_set_style_bg_color(Scr_mainMenu, lv_color_hex(0xDaDaDa), 0);
    lv_obj_set_size(Scr_mainMenu, LV_HOR_RES, LV_VER_RES);
    lv_obj_t * Scr_1_btn = lv_btn_create(Scr_mainMenu);
    lv_obj_t * Scr_1_labl = lv_label_create(Scr_1_btn);
    lv_label_set_text(Scr_1_labl,"next page");
    lv_obj_add_event_cb(Scr_1_btn,Scr_1_cb,LV_EVENT_CLICKED,NULL);

    Scr_wifi = lv_obj_create(NULL);
    lv_obj_clean(Scr_wifi);
    lv_obj_remove_style_all(Scr_wifi);
    lv_obj_set_style_bg_opa(Scr_wifi, LV_OPA_COVER, 0);//0不透明
    lv_obj_set_style_bg_color(Scr_wifi, lv_color_hex(0x8a8a8a), 0);
    lv_obj_set_size(Scr_wifi, LV_HOR_RES, LV_VER_RES);
    lv_obj_t * Scr_2_btn = lv_btn_create(Scr_wifi);
    lv_obj_t * Scr_2_labl = lv_label_create(Scr_2_btn);
    lv_label_set_text(Scr_2_labl,"before page");
    lv_obj_add_event_cb(Scr_2_btn,Scr_2_cb,LV_EVENT_CLICKED,NULL);

    /*加载一个页面*/
    lv_scr_load(Scr_wifi);

#endif
}

6.2动画

LittleVGL_第43张图片LittleVGL_第44张图片

/*******animation********/
static void anim_x_cb(void* var, int32_t v)
{
    lv_obj_set_x(var, v);
}

void my_gui()
{

#if 1
 /*******animation********/
/* 第一步:创建标签 */
 lv_obj_t* lv_obj = lv_label_create(lv_scr_act());
 lv_label_set_text(lv_obj,"ALIENTEK");
 lv_obj_set_pos(lv_obj, 400, 10);
 lv_obj_update_layout(lv_obj);
 /* 第二步:动画初始化 */
 lv_anim_t a;
 lv_anim_init(&a);
 /* 第三步:设置动画目标为标签对象 */
 lv_anim_set_var(&a, lv_obj);
 /* 第四步:设置动画起点和终点 */
 lv_anim_set_values(&a, lv_obj_get_x(lv_obj), 0);
 /* 第五步:设置动画时间 */
 lv_anim_set_time(&a, 5000);
 /* 第六步:设置动画回调函数 */
 lv_anim_set_exec_cb(&a, anim_x_cb);
 /* 第七步:设置动画轨道 */
 lv_anim_set_path_cb(&a, lv_anim_path_bounce);
 /* 第八步:设置动画轨道 */
 lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
 /* 第九步:开启动画 */
 lv_anim_start(&a);
}

LVGL库入门教程 - 动画 - 冰封残烛 - 博客园

6.3事件冒泡

https://blog.csdn.net/qq_41650023/article/details/125260000

6.4GUI-Guider编写事件回调

LittleVGL_第45张图片6.5GUI-Guider生成的代码移植CodeBlocks

1. 新建lvgl_app将GUI-Guider生成的custom、generated文件复制粘贴。

LittleVGL_第46张图片

2.在CodeBlocks中递归添加lvgl_app文件

LittleVGL_第47张图片

3.编译并修改新添加文件头文件问题

LittleVGL_第48张图片

4.添加 guider_ui的相关代码到main

LittleVGL_第49张图片

参考文章:LVGL-GUI Guider生成工程移植Keil_gui guider移植_云海无语的博客-CSDN博客

codeblocks添加头文件路径包含_codeblocks头文件路径_dzdesigned的博客-CSDN博客

ESP32+LVGL笔记(2):学习B站的计算器例程_lvgl设计计算器_hwd00001的博客-CSDN博客

GUI Guider与lvgl联合仿真(结合stm32实验进行演示,含触摸屏实验计数器与计算器)_古道小七的博客-CSDN博客_lv_obj_set_scrollbar_mode

23.1.31 

codeblock编译问题找了快一周的原因,GUI_Guider生成代码移植到codeblock,时不时出现编译最后 No such file or directory 有时不会出现有时会。网上找寻答案试过各种方法都无效。最后修改文件名解决了?????我怀疑是文件名与gui_guider.h冲突导致。

LittleVGL_第50张图片 

 LittleVGL_第51张图片

 LittleVGL_第52张图片

修改后正常运行 

LittleVGL_第53张图片

头文件名可以不分大小写

LittleVGL_第54张图片

 LittleVGL_第55张图片

23.2.28

上述问题是编译器找不到生成的图片源文件导致,吧image文件夹放到工作文件的外外层就不报错,在eclipse下就不存在上述问题(22.3.8)

23.4.19

上述问题为头文件路径问题

正确添加头文件设置

(85条消息) codeblocks添加头文件路径包含-CSDN博客

7、页面逻辑实现

7.1:设置页面的前端实现,页面要求,lvgl弹出对话框,只允许触摸对话框,其他地方不许触摸,例如电脑和手机弹出对话框,必须触摸关闭当前对话框,才能触摸其他地方。

方法一:

1:首先将设置页面创建并将页面隐藏: lv_obj_add_flag(win,LV_OBJ_FLAG_HIDDEN): 

2:通关点击设置按键在事件中将设置页面显示出lv_obj_clear_flag(win,LV_OBJ_FLAG_HIDDEN);

3:将设置页面置于前景:lv_obj_move_foreground(win);

4:关掉后面对象的点击事件:lv_obj_clear_flag(btn_win,LV_OBJ_FLAG_CLICKABLE);

/********win*************/
lv_obj_t * win;
lv_obj_t * btn_win;
void win_cb(lv_event_t * e)
{
    lv_obj_t * target = lv_event_get_target(e);
    lv_event_code_t event = lv_event_get_code(e);
    if(event == LV_EVENT_CLICKED)
    {
        lv_obj_add_flag(btn_win,LV_OBJ_FLAG_CLICKABLE);
        lv_obj_add_flag(win,LV_OBJ_FLAG_HIDDEN);
    }
}

void btn_cb(lv_event_t * e)
{
    lv_obj_t * target = lv_event_get_target(e);
    lv_event_code_t event = lv_event_get_code(e);
    if(event == LV_EVENT_CLICKED)
    {
        lv_obj_clear_flag(btn_win,LV_OBJ_FLAG_CLICKABLE);
        lv_obj_clear_flag(win,LV_OBJ_FLAG_HIDDEN);
        lv_obj_move_foreground(win);
    }
}

lv_obj_t * my_slider_creat(lv_obj_t * content,const char* symbol,lv_coord_t x_ofs,lv_coord_t y_ofs)
{
    lv_obj_t * slider = lv_slider_create(content);
    lv_obj_set_size(slider,scr_width/3,scr_hight/30);
    lv_slider_set_value(slider,50,LV_ANIM_OFF);
    lv_obj_align(slider, LV_ALIGN_CENTER,x_ofs,y_ofs);
    lv_obj_set_style_bg_color(slider,lv_color_hex(0x787c78), LV_PART_MAIN);
    lv_obj_set_style_bg_color(slider,lv_color_hex(0xc3c3c3), LV_PART_INDICATOR);
    lv_obj_remove_style(slider,NULL,LV_PART_KNOB);

    lv_obj_t * label = lv_label_create(content);
    lv_label_set_text(label,symbol);
    lv_obj_align_to(label,slider,LV_ALIGN_OUT_LEFT_MID,-10,0);

    return slider;

}

/********win*************/
void my_gui()
{

    win = lv_win_create(lv_scr_act(),scr_hight/12);
    lv_obj_set_size(win,scr_width*5/8,scr_hight*4/7);
    lv_obj_set_style_border_width(win,1,LV_STATE_DEFAULT);
    lv_obj_set_style_border_color(win,lv_color_hex(0x8a8a8a),LV_STATE_DEFAULT);
    lv_obj_set_style_border_opa(win,100,LV_STATE_DEFAULT);
    lv_obj_set_style_radius(win,10,LV_STATE_DEFAULT);
    lv_obj_center(win);

    lv_obj_t * btn_left = lv_win_add_btn(win,LV_SYMBOL_SETTINGS,20);
    lv_obj_set_style_bg_opa(btn_left,0,LV_STATE_DEFAULT);
    lv_obj_set_style_shadow_width(btn_left,0,LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(btn_left,lv_color_hex(0x000000),LV_STATE_DEFAULT);
    lv_obj_t * title = lv_win_add_title(win,"Setting");
    lv_obj_set_style_text_font(title,&lv_font_montserrat_18,LV_STATE_DEFAULT);
    lv_obj_add_flag(win,LV_OBJ_FLAG_HIDDEN);

    lv_obj_t * btn_right = lv_win_add_btn(win,LV_SYMBOL_CLOSE,20);
    lv_obj_set_style_bg_opa(btn_right,0,LV_STATE_DEFAULT);
    lv_obj_set_style_shadow_width(btn_right,0,LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(btn_right,lv_color_hex(0x000000),LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(btn_right,lv_color_hex(0xff0000),LV_STATE_PRESSED);
    lv_obj_add_event_cb(btn_right,win_cb,LV_EVENT_CLICKED,NULL);

    lv_obj_t * content = lv_win_get_content(win);
    lv_obj_t * slider_1 = my_slider_creat(content,LV_SYMBOL_AUDIO,15, -scr_hight/14);
    lv_obj_t * slider_2 = my_slider_creat(content,LV_SYMBOL_BELL,15, scr_hight/14);

    /*SET按键*/
    lv_obj_t * btn = lv_btn_create(lv_scr_act());
    lv_obj_align(btn,LV_ALIGN_BOTTOM_MID,0,0);
    lv_obj_t* label;
    label = lv_label_create(btn);
    lv_label_set_text(label, "Set");
    lv_obj_center(label);
    lv_obj_update_layout(label);
    lv_obj_add_event_cb(btn,btn_cb,LV_EVENT_CLICKED,NULL);


    lv_obj_t * obj_win = lv_obj_create(lv_scr_act());
    lv_obj_set_size(obj_win,400,300);
    btn_win = lv_btn_create(obj_win);
    lv_obj_align(btn_win,LV_ALIGN_OUT_LEFT_MID,0,0);

}

方法二:

使用模态对话框,他设置按键回调事件中在layer_top层创建设置界面,并启用了click属性,layer_top将吸收所有用户点击并充当模态 。设置页面关闭后删除设置界面。

/**********模态对话框***********/
void close_btn_cb(lv_event_t * e)
{
    lv_obj_t * target = lv_event_get_target(e);
    lv_event_code_t event = lv_event_get_code(e);
    if(event == LV_EVENT_CLICKED)
    {
        lv_obj_del(win);           // 删除对象及其所有子对象
        win = NULL;
        lv_obj_clear_flag(lv_layer_top(), LV_OBJ_FLAG_CLICKABLE);   // 清除标志
        lv_obj_set_style_bg_opa(lv_layer_top(), LV_OPA_TRANSP, 0);  // 设置透明度
    }
}

static void ste_btn_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * ta = lv_event_get_target(e);

    if(code == LV_EVENT_CLICKED) {
            if(win == NULL) {
    //设置弹窗
    lv_obj_add_flag(lv_layer_top(), LV_OBJ_FLAG_CLICKABLE);                         // 使能 lv_layer_top 点击
    win = lv_win_create(lv_layer_top(),scr_hight/12);                               // 在 lv_layer_top 层上创建日历对象
    lv_obj_set_style_bg_opa(lv_layer_top(), LV_OPA_50, 0);                          // 设置对象透明度
    lv_obj_set_style_bg_color(lv_layer_top(), lv_palette_main(LV_PALETTE_GREY), 0); // 设置对象颜色
    lv_obj_set_size(win,scr_width*5/8,scr_hight*4/7);
    lv_obj_set_style_border_width(win,1,LV_STATE_DEFAULT);
    lv_obj_set_style_border_color(win,lv_color_hex(0x8a8a8a),LV_STATE_DEFAULT);
    lv_obj_set_style_border_opa(win,100,LV_STATE_DEFAULT);
    lv_obj_set_style_radius(win,10,LV_STATE_DEFAULT);
    lv_obj_center(win);

    //顶部左边设置logo
    lv_obj_t * btn_left = lv_win_add_btn(win,LV_SYMBOL_SETTINGS,20);
    lv_obj_set_style_bg_opa(btn_left,0,LV_STATE_DEFAULT);
    lv_obj_set_style_shadow_width(btn_left,0,LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(btn_left,lv_color_hex(0x000000),LV_STATE_DEFAULT);
    lv_obj_t * title = lv_win_add_title(win,"Setting");
    lv_obj_set_style_text_font(title,&lv_font_montserrat_18,LV_STATE_DEFAULT);

    //顶部右边关闭logo
    lv_obj_t * btn_right = lv_win_add_btn(win,LV_SYMBOL_CLOSE,20);
    lv_obj_set_style_bg_opa(btn_right,0,LV_STATE_DEFAULT);
    lv_obj_set_style_shadow_width(btn_right,0,LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(btn_right,lv_color_hex(0x000000),LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(btn_right,lv_color_hex(0xff0000),LV_STATE_PRESSED);
    lv_obj_add_event_cb(btn_right,close_btn_cb,LV_EVENT_CLICKED,NULL);

    //滑块
    lv_obj_t * content = lv_win_get_content(win);
    lv_obj_t * slider_1 = my_slider_creat(content,LV_SYMBOL_AUDIO,15, -scr_hight/14);
    lv_obj_t * slider_2 = my_slider_creat(content,LV_SYMBOL_BELL,15, scr_hight/14);

        }
    }
}
/**********模态对话框***********/
void my_gui()
{

    lv_obj_t * btn = lv_btn_create(lv_scr_act());
    lv_obj_align(btn,LV_ALIGN_BOTTOM_MID,0,0);
    lv_obj_t* label;
    label = lv_label_create(btn);
    lv_label_set_text(label, "Set");
    lv_obj_center(label);
    lv_obj_update_layout(label);
    lv_obj_add_event_cb(btn,ste_btn_cb,LV_EVENT_CLICKED,NULL);

    lv_obj_t * bg_obj_win = lv_obj_create(lv_scr_act());
    lv_obj_set_size(bg_obj_win,400,300);
    btn_win = lv_btn_create(bg_obj_win);
    lv_obj_align(btn_win,LV_ALIGN_OUT_LEFT_MID,0,0);
}

LittleVGL_第56张图片

 23.2.2

参考文章:icore4tlvgl_9 []

LVGL|lvgl教程之巧用图层(layer)编写模态对话框_挨踢民工biubiu的博客-CSDN博客_lv_layer_sys

8、mune菜单控件

这个控件各个视频教程都没有提及到,偶然控看见有这个控件,在V8.2版本中,才发现正点原子的CodeBlock是8.0的版本,并无munu控件,改用百问网的8.2工程

LVGL 8.2 菜单_lvgl 菜单_仙剑情缘的博客-CSDN博客

8.1 content容器铺满问题

默认情况下在content下添加组件是不铺满有边距的

LittleVGL_第57张图片

解决办法:lv_style_set_pad_all 

    static lv_style_t cont_style;   // 容器的样式
	lv_style_init(&cont_style);
	lv_style_set_pad_all(&cont_style, 0);  // 铺满(新添加的一行代码)
	lv_obj_add_style(ui->screen_select_prescription_win_content, &cont_style, 0);
	lv_obj_set_size(ui->screen_select_prescription_list_1, 200,400*4/7);

LittleVGL_第58张图片

参考文章:LVGL|lvgl教程之flex布局铺满整个容器(弹性布局铺满整个容器)_挨踢民工biubiu的博客-CSDN博客_flex布局高度铺满

23.2.9 

lvgl 增加自定义SYMBOL_徐满华的博客-CSDN博客_lvgl自定义图标仙剑情缘的博客_CSDN博客-C/C++,little VGL,NRF52832个人学习笔记领域博主

8.2 menu相关

LittleVGL_第59张图片

8.3编码器

LVGL如何使用编码器 - 知乎 (zhihu.com)

(71条消息) lvgl使用旋转编码器做为外部输入设备_lvgl 编码器_我来过了.的博客-CSDN博客

(71条消息) STM32移植LVGL+旋转编码器接口对接_lvgl 编码器_IMSHYANNE的博客-CSDN博客

【开源】ESP32 Arduino LVGL8 编码器EC11输入 演示demo_哔哩哔哩_bilibili

(86条消息) LVGL V8应用——通过按键切换页面_lvgl 页面切换_临界msp的博客-CSDN博客

(86条消息) 【LVGL】学习笔记--(3)界面切换以及显示优化_lvgl界面切换_公子无缘的博客-CSDN博客

9、主题模式

LittleVGL_第60张图片

 0:为明亮

LittleVGL_第61张图片

 1:为暗色

LittleVGL_第62张图片

设置主题:粉色

static const lv_font_t * font_normal;
lv_theme_default_init(NULL, lv_palette_main(LV_PALETTE_PINK), lv_palette_main(LV_PALETTE_BLUE), LV_THEME_DEFAULT_DARK, font_normal);

LittleVGL_第63张图片

默认为蓝色:

 LittleVGL_第64张图片

 (85条消息) LVGL学习笔记4 - 主题Themes_lvgl主题-CSDN博客

static lv_style_t gThemeRectStyle;
static void new_theme_apply_cb(lv_theme_t* th, lv_obj_t* obj)
{
    if (lv_obj_check_type(obj, &lv_obj_class))
    {
        lv_obj_add_style(obj, &gThemeRectStyle, LV_STATE_DEFAULT);
    }
}
void set(){

    lv_obj_t* rect = lv_obj_create(lv_scr_act());
    lv_obj_set_size(rect, LV_PCT(20), LV_PCT(20));
    lv_obj_align(rect, LV_ALIGN_TOP_LEFT, 20, 20);

    /*Set a background color and a radius*/
    lv_style_init(&gThemeRectStyle);
    lv_style_set_radius(&gThemeRectStyle, 10);
    lv_style_set_bg_opa(&gThemeRectStyle, LV_OPA_COVER);
    lv_style_set_bg_color(&gThemeRectStyle, lv_palette_lighten(LV_PALETTE_RED, 1));

    /*Add a shadow*/
    lv_style_set_shadow_width(&gThemeRectStyle, 55);
    lv_style_set_shadow_color(&gThemeRectStyle, lv_palette_main(LV_PALETTE_BLUE));

    lv_obj_add_style(rect, &gThemeRectStyle, LV_PART_MAIN|LV_STATE_DEFAULT);

    /*通过当前主题初始化新主题*/
    lv_theme_t* th_active = lv_theme_get_from_obj(NULL);
    static lv_theme_t th_new;
    th_new = *th_active;

    /*设置父主题和新主题的样式适播放回调函数*/
    lv_theme_set_parent(&th_new, th_active);
    lv_theme_set_apply_cb(&th_new, new_theme_apply_cb);

    /*设置新主题*/
    lv_disp_set_theme(NULL, &th_new);

    lv_obj_t* rect2 = lv_obj_create(lv_scr_act());
    lv_obj_set_size(rect2, LV_PCT(20), LV_PCT(20));
    lv_obj_align(rect2, LV_ALIGN_TOP_LEFT, 220, 20);

    lv_obj_t* rect3 = lv_obj_create(lv_scr_act());
    lv_obj_set_size(rect3, LV_PCT(20), LV_PCT(20));
    lv_obj_align(rect3, LV_ALIGN_TOP_LEFT, 420, 20);
}

LittleVGL_第65张图片

10、conf文件

LittleVGL_第66张图片

①:创建屏幕

lv_obj_t * scr1 = lv_obj_create(NULL)

②:获取活动的屏幕lv_scr_act()

③:加载屏幕

lv_scr_load(scr1)

④:动画加载屏幕

lv_scr_load_anim(scr,transition_type,time,delay,aotu_del)

LittleVGL_第67张图片

⑤:取消滚动条

 lv_obj_clear_flag(cont, LV_OBJ_FLAG_SCROLLABLE);

⑥:设置对象容器使用基于行的流失弹性布局flex,设置超出部分换行模式

lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_ROW_WRAP);

⑦:lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_ROW_WRAP);

 /**
   * 设置容器弹性模式
   * 1. 容器指针
   * 2. LV_FLEX_ALIGN_SPACE_EVENLY 均匀分部子元素之间的间距
   * 3. LV_FLEX_ALIGN_END 容器中所有的子元素底部对齐
   * 4. 默认0
*/

LittleVGL_第68张图片

LittleVGL_第69张图片

11、布局

弹性布局 

【LVGL】弹性布局(Flex)学习_lvgl flex_小石头有大内涵的博客-CSDN博客

网格布局

Grid布局        网格布局

LittleVGL_第70张图片

 12、滚动条

  • lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE); 禁用滚动条
  • lv_obj_set_scroll_dir(obj, LV_DIR_VER); 设置滚动方向,LV_DIR_HOR水平滚动LV_DIR_VER垂直滚动
  • lv_obj_set_style_bg_opa(obj, LV_OPA_0, LV_PART_SCROLLBAR | LV_STATE_DEFAULT),设置样式将obj滚动条的颜色默认为透明
  • lv_obj_set_style_bg_opa(obj, LV_OPA_0, LV_PART_SCROLLBAR | LV_STATE_SCROLLED),设置样式将obj滚动条滚动时的颜色也设置为透明
  • 滚动条以及禁用滚动条

 13、动画

需求:要完成多个容器的切换,没头绪,后面参考Futuristic_Ebike页面

LittleVGL_第71张图片

查看源码后发现他是通创建多个count然后只留一个其他都隐藏起来,再通过动画的方式显示出来

测试代码

/*******页面切换动画************/
lv_obj_t* Page_switching_cont1;
lv_obj_t* Page_switching_cont2;
lv_obj_t* Page_switching_cont3;

static void _ui_anim_callback_set_opacity(lv_anim_t * a, int32_t v)
{
    lv_obj_set_style_opa((lv_obj_t *)a->user_data, v, 0);
}

static void _ui_anim_callback_set_x(lv_anim_t * a, int32_t v)
{
    lv_obj_set_x((lv_obj_t *)a->user_data, v);
}

static int32_t _ui_anim_callback_get_x(lv_anim_t * a)
{
    return lv_obj_get_x_aligned((lv_obj_t *)a->user_data);
}

static void On_Animation(lv_obj_t * TargetObject, int delay)
{
//渐变动画
    lv_anim_t PropertyAnimation_0;                                                      //定义一个动画数据结构
    lv_anim_init(&PropertyAnimation_0);                                                 //初始化
    lv_anim_set_time(&PropertyAnimation_0,1000);                                        //设置动画执行时间
    lv_anim_set_user_data(&PropertyAnimation_0, TargetObject);                          //设置动画执行的对象
    lv_anim_set_custom_exec_cb(&PropertyAnimation_0, _ui_anim_callback_set_opacity);    //执行动画回调函数,这里是设置透明度
    lv_anim_set_values(&PropertyAnimation_0, 0, 255);                                   //设置动执行动画开始和结束的值,即透明到不透明
    lv_anim_set_path_cb(&PropertyAnimation_0, lv_anim_path_ease_out);                   //设置路径算法,这里是不透明度设置开头很快,后面变化速度逐渐减小
    lv_anim_set_delay(&PropertyAnimation_0, delay + 0);                                 //设置动画开始的延时时间
    lv_anim_set_playback_time(&PropertyAnimation_0, 0);                                 //设置动画正放与回放之间的时间间隔
    lv_anim_set_playback_delay(&PropertyAnimation_0, 0);                                //设置回放之间的延时
    lv_anim_set_repeat_count(&PropertyAnimation_0, 0);                                  //动画重复的次数
    lv_anim_set_repeat_delay(&PropertyAnimation_0, 0);                                  //动画重复的间隔时间
    lv_anim_set_early_apply(&PropertyAnimation_0, true);                               //动画是否马上执行
    lv_anim_start(&PropertyAnimation_0);                                                //开始动画

//平移动画
    lv_anim_t PropertyAnimation_1;
    lv_anim_init(&PropertyAnimation_1);
    lv_anim_set_time(&PropertyAnimation_1, 600);
    lv_anim_set_user_data(&PropertyAnimation_1, TargetObject);
    lv_anim_set_custom_exec_cb(&PropertyAnimation_1, _ui_anim_callback_set_x);
    lv_anim_set_values(&PropertyAnimation_1,-100,0);                                   //执行动画回调函数,这里x轴的路径。-100是从左往右移要从又往左移改成100即可
    lv_anim_set_path_cb(&PropertyAnimation_1, lv_anim_path_ease_out);
    lv_anim_set_delay(&PropertyAnimation_1, delay + 0);
    lv_anim_set_playback_time(&PropertyAnimation_1, 0);
    lv_anim_set_playback_delay(&PropertyAnimation_1, 0);
    lv_anim_set_repeat_count(&PropertyAnimation_1, 0);
    lv_anim_set_repeat_delay(&PropertyAnimation_1, 0);
    lv_anim_set_early_apply(&PropertyAnimation_1, false);
    lv_anim_set_get_value_cb(&PropertyAnimation_1, &_ui_anim_callback_get_x);
    lv_anim_start(&PropertyAnimation_1);
}
static void btn_event_cb(lv_event_t *e)
{
	lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * cont = lv_event_get_user_data(e);

	switch (code)
	{
	case LV_EVENT_CLICKED:
	{
        LV_LOG_USER("btn_event_cb");
        On_Animation(Page_switching_cont2, 0);
        lv_obj_clear_flag(Page_switching_cont2, LV_OBJ_FLAG_HIDDEN);     /// Flags
        lv_obj_add_flag(Page_switching_cont1, LV_OBJ_FLAG_HIDDEN);     /// Flags
	}
		break;
	default:
		break;
	}
}

static void btn1_event_cb(lv_event_t *e)
{
	lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * cont = lv_event_get_user_data(e);

	switch (code)
	{
	case LV_EVENT_CLICKED:
	{
        LV_LOG_USER("btn_event_cb");
        On_Animation(Page_switching_cont1, 0);
        lv_obj_clear_flag(Page_switching_cont1, LV_OBJ_FLAG_HIDDEN);     /// Flags
        lv_obj_add_flag(Page_switching_cont2, LV_OBJ_FLAG_HIDDEN);     /// Flags
	}
		break;
	default:
		break;
	}
}



void test(void)
{
    lv_obj_t* main = lv_obj_create(lv_scr_act());               // 创建一个对象容器 cont
    lv_obj_set_size(main,800,480);

    Page_switching_cont1 = lv_obj_create(main);
    lv_obj_set_size(Page_switching_cont1, 300, 420);
    lv_obj_set_style_bg_color(Page_switching_cont1, lv_color_hex(0x0E7CC5), 0);
    lv_obj_center(Page_switching_cont1);

    Page_switching_cont2 = lv_obj_create(main);
    lv_obj_set_size(Page_switching_cont2, 300, 420);
    lv_obj_set_style_bg_color(Page_switching_cont2, lv_color_hex(0xC72D1F), 0);
    lv_obj_center(Page_switching_cont2);
    lv_obj_add_flag(Page_switching_cont2, LV_OBJ_FLAG_HIDDEN);     /// Flags

    lv_obj_t * btnm = lv_btn_create(lv_scr_act());
    lv_obj_align(btnm, LV_ALIGN_TOP_RIGHT, -20, 10);
    lv_obj_add_event_cb(btnm,btn_event_cb, LV_EVENT_CLICKED,NULL);

    lv_obj_t * btnm1 = lv_btn_create(lv_scr_act());
    lv_obj_add_event_cb(btnm1,btn1_event_cb, LV_EVENT_CLICKED,NULL);
}

LittleVGL_第72张图片

LVGL动画_动画的数据结构_直接写数据结构

LVGL动画_库函数

LVGL动画例程记录_lvgl 例程

 14、常用函数

14.1 获取控件长宽高

lv_obj_update_layout(ui->screen_ch1_control_cont);  //实现要更新布局信息
LV_LOG_USER("height:%d",lv_obj_get_height(ui->screen_ch1_control_cont));
LV_LOG_USER("width:%d",lv_obj_get_width(ui->screen_ch1_control_cont));

 15、参考博文

LVGL 8.2 Sorting a List using up and down buttons_风雨依依的博客-CSDN博客

little VGL_风雨依依的博客-CSDN博客

tilblackout的博客_CSDN博客-嵌入式,ARM,FOC领域博主

ESP32 开发笔记(四)LVGL控件学习 ObjectMask 对象蒙版控件_lvgl mask_路过人间本尊的博客-CSDN博客

【LVGL布局】网格布局_lv_obj_set_grid_cell_喜暖知寒的博客-CSDN博客

你可能感兴趣的:(单片机,stm32,嵌入式硬件)