前言
LVGL对硬件的要求非常低,使用其自带的组件能够搭建出精美的界面,动效也很棒。但是如过移植到Linux平台下,开发稍微复杂的应用项目,那些组件就远远不够用了。为此需要自己自定义一些组件,以方便实用。
效果
为此,尝试开发了一个页面指示器,先看效果:
代码
Talk is cheap, show me your code.
circles.h
#include "lvgl.h"
#define MAX_INDEX 10
typedef struct circles_ {
int max_index;
int active_index;
lv_style_t *active_style;
lv_style_t *inactive_style;
lv_obj_t *circle_list[MAX_INDEX];
lv_obj_t *parent;
int (*click_callback)(void);
const char * name;
void (*init)(void);
} circles_t;
typedef struct callback_user_data_{
circles_t *circles;
int index;
}callback_user_data_t;
// set the active index
int lv_circles_set_active_index(circles_t *circles, int index);
// draw the circles on the screen
int lv_draw_circles(circles_t *circles);
//demo function
void custom_components_circles_demo();
circles.c
#include "circles.h"
// usage:
// 1. define the callback function
void test_cb(lv_event_t *e){
printf("hello world\n");
}
// 2.init the circles like this:
void custom_components_circles_demo(){
static lv_style_t inactive_style;
lv_style_init(&inactive_style);
lv_style_set_radius(&inactive_style,5);
lv_style_set_size(&inactive_style, 10);
lv_style_set_bg_color(&inactive_style,lv_palette_main(LV_PALETTE_GREY));
lv_style_set_bg_opa(&inactive_style, 255);
lv_style_set_text_opa(&inactive_style, 0);
static lv_style_t active_style;
lv_style_init(&active_style);
lv_style_set_radius(&active_style,5);
// lv_style_set_size(&active_style, 10);
lv_style_set_width(&active_style, 20);
lv_style_set_height(&active_style, 10);
lv_style_set_bg_color(&active_style,lv_palette_main(LV_PALETTE_BLUE));
lv_style_set_bg_opa(&active_style, 255);
lv_style_set_text_opa(&active_style, 0);
circles_t *circles;
circles = (circles_t *)malloc(sizeof(circles_t));
circles->active_style = &active_style;
circles->inactive_style = &inactive_style;
circles->max_index = 3;
circles->active_index = 0;
circles->name = "circles";
circles->parent = lv_obj_create(lv_scr_act());
lv_obj_set_size(circles->parent, 300, 75);
lv_obj_set_flex_flow(circles->parent, LV_FLEX_FLOW_ROW);
lv_obj_align(circles->parent, LV_ALIGN_TOP_MID, 0, 5);
circles->click_callback = test_cb;
lv_draw_circles(circles);
}
int lv_circles_set_active_index(circles_t *circles, int index){
if(index < 0 || index > circles->max_index) return -1;
lv_obj_remove_style_all(circles->circle_list[circles->active_index]);
lv_obj_remove_style_all(circles->circle_list[index]);
lv_obj_add_style(circles->circle_list[circles->active_index], circles->inactive_style,0);
lv_obj_add_style(circles->circle_list[index], circles->active_style,0);
circles->active_index = index;
return 0;
}
void lv_circles_event_cb(lv_event_t *e){
callback_user_data_t *user_data = lv_event_get_user_data(e);
lv_obj_t * btn = lv_event_get_target(e);
lv_event_code_t code = lv_event_get_code(e);
if(code == LV_EVENT_CLICKED){
lv_circles_set_active_index(user_data->circles, user_data->index);
if(user_data->circles->click_callback != NULL){
user_data->circles->click_callback();
}
}
}
int lv_draw_circles(circles_t *circles){
int i = 0;
for(i =0;i<circles->max_index;i++){
circles->circle_list[i] = lv_btn_create(circles->parent);
lv_obj_remove_style_all(circles->circle_list[i]);
callback_user_data_t *data = malloc(sizeof(callback_user_data_t));
data->circles = circles;
data->index = i;
lv_obj_add_event_cb(circles->circle_list[i], lv_circles_event_cb, LV_EVENT_ALL, data);
if(i==circles->active_index){
lv_obj_add_style(circles->circle_list[i], circles->active_style,0);
}
else{
lv_obj_add_style(circles->circle_list[i], circles->inactive_style,0);
}
}
}
使用方法
- 项目根目录下,新建文件夹
components
,把上面的两个文件放进去 - 修改
makefile
:
INC := -I./ui/simulator/inc/ -I./ -I./lvgl/ -I ./components
- 要使用时引入头文件
#include "circles.h"
- 可以使用自带的Demo快速预览,具体使用方法可以参考Demo函数
custom_components_circles_demo();
配置
参考demo函数初始化配置即可:
- 建立点击回调函数,并注册到组件中,在指示器被点击后翻页使用
- 初始化
active_style,inactive_style
,设置自己需要的指示器样式 - 创建
circles
对象,初始化页面总个数和默认激活哪个页面 - 画到界面上
总结
由于刚刚上手lvgl,所以这个组件并没有完全基于lvgl中的基础对象lv_obj
类型进行编写。感兴趣的同学可以参考官方组件的写法改写哦。