一、lvgl对象
1. 基础对象(lv_obj_t)
在lvgl中,任何控件都是一个对象。这些控件都继承自lvgl基础对象类,换句话说,lvgl基础类描述了所有控件共有的属性和方法,称之为lv_obj_t
。
lv_obj_t类定义在文件lvgl\src\core\lv_obj.h
文件中,定义如下:
typedef struct _lv_obj_t {
const lv_obj_class_t * class_p;
struct _lv_obj_t * parent;
_lv_obj_spec_attr_t * spec_attr;
_lv_obj_style_t * styles;
void * user_data;
lv_area_t coords;
lv_obj_flag_t flags;
lv_state_t state;
uint16_t layout_inv : 1;
uint16_t scr_layout_inv : 1;
uint16_t skip_trans : 1;
uint16_t style_cnt : 6;
uint16_t h_layout : 1;
uint16_t w_layout : 1;
} lv_obj_t;
一上来就抛源码是一种很不道德的行为,我只是想展示lvgl基础对象长什么样子~
2. 基础对象的属性
在lvgl中,一个控件对象具有两种属性,一种是继承自基础对象的属性,另一些是控件特有的一些属性。
基础对象的属性有:
- Position
- Size
- Parent
- Drag enable
- Click enable
- …
我们可以通过lv_obj_set_xxx
和lv_obj_get_xxx
API来设置或者获取这些属性。
2.1. 控件大小
只改变宽度:
/**
* Set the width of an object
* @param obj pointer to an object
* @param w the new width
* @note possible values are:
* pixel simple set the size accordingly
* LV_SIZE_CONTENT set the size to involve all children in the given direction
* lv_pct(x) to set size in percentage of the parent's content area size (the size without paddings).
* x should be in [0..1000]% range
*/
void lv_obj_set_width(struct _lv_obj_t * obj, lv_coord_t w);
只改变高度:
/**
* Set the height of an object
* @param obj pointer to an object
* @param h the new height
* @note possible values are:
* pixel simple set the size accordingly
* LV_SIZE_CONTENT set the size to involve all children in the given direction
* lv_pct(x) to set size in percentage of the parent's content area size (the size without paddings).
* x should be in [0..1000]% range
*/
void lv_obj_set_height(struct _lv_obj_t * obj, lv_coord_t h);
同时改变宽度和高度:
/**
* Set the size of an object.
* @param obj pointer to an object
* @param w the new width
* @param h the new height
* @note possible values are:
* pixel simple set the size accordingly
* LV_SIZE_CONTENT set the size to involve all children in the given direction
* LV_SIZE_PCT(x) to set size in percentage of the parent's content area size (the size without paddings).
* x should be in [0..1000]% range
*/
void lv_obj_set_size(struct _lv_obj_t * obj, lv_coord_t w, lv_coord_t h);
这里的大小参数有点意思,有三种值可以设置:
- pixel:直接设置像素点的值
- LV_SIZE_CONTENT:设置为包含给定方向上的所有子控件的大小
- LV_SIZE_PCT(x):按照父控件大小的百分比来设置
2.2. 控件位置
同样,设置控件的API也提供了三个:
/**
* Set the x coordinate of an object
* @param obj pointer to an object
* @param x new x coordinate
* @note With default alignment it's the distance from the top left corner
* @note E.g. LV_ALIGN_CENTER alignment it's the offset from the center of the parent
* @note The position is interpreted on the content area of the parent
* @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)`
*/
void lv_obj_set_x(struct _lv_obj_t * obj, lv_coord_t x);
/**
* Set the y coordinate of an object
* @param obj pointer to an object
* @param y new y coordinate
* @note With default alignment it's the distance from the top left corner
* @note E.g. LV_ALIGN_CENTER alignment it's the offset from the center of the parent
* @note The position is interpreted on the content area of the parent
* @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)`
*/
void lv_obj_set_y(struct _lv_obj_t * obj, lv_coord_t y);
/**
* Set the position of an object relative to the set alignment.
* @param obj pointer to an object
* @param x new x coordinate
* @param y new y coordinate
* @note With default alignment it's the distance from the top left corner
* @note E.g. LV_ALIGN_CENTER alignment it's the offset from the center of the parent
* @note The position is interpreted on the content area of the parent
* @note The values can be set in pixel or in percentage of parent size with `lv_pct(v)`
*/
void lv_obj_set_pos(struct _lv_obj_t * obj, lv_coord_t x, lv_coord_t y);
x,y参数的值默认对齐到左上角,而且该位置是在父控件的区域上解释,同样,有两种设置方法:
- pixel:直接设置像素点的值
- lv_pct(v):根据父控件区域的百分比来设置
eg1. 设置控件大小为,宽度是父控件的50%,高度是父控件的50%。
void lv_study_object1(void)
{
lv_obj_t *obj = lv_obj_create(lv_scr_act());
// 设置控件大小
lv_obj_set_size(obj, lv_pct(50), lv_pct(50));
// 设置控件位置
lv_obj_set_pos(obj, lv_pct(20), lv_pct(20));
}
这样一个最简单的示例运行起来后,效果如图:
3. 创建-删除对象
在lvgl中,对象可以被动态的创建和删除,这意味着只有当前创建的控件会消耗RAM。
例如,当你需要一个chart控件时,可以在需要的时候创建它,并在不需要的时候删除它。
(1)对象创建API
每个对象类型(每种控件)都有它自己的创建API和统一的原型,如下:
lv_obj_t * lv_<widget>_create(lv_obj_t * parent, <other parameters if any>);
创建API有一个参数:
- parent:指向父对象的指针
返回值为 lv_obj_t 类型的指针,所有的控件都可以用此指针来指向。
(2)对象删除API
所有对象类型的删除API是统一的,如下:
void lv_obj_del(lv_obj_t * obj);
该API将会立即删除该对象和它所有的子对象。
如果不想理解删除,比如想在子对象的LV_EVENT_DELETE
时间中删除父对象,可以使用下面的API:
lv_obj_del_async(lv_obj_t * obj);
如果仅仅想移除某个对象的所有子对象,可以使用下面的API:
void lv_obj_clean(lv_obj_t * obj);
二、lvgl屏幕(Screens)
1. 创建screens
屏幕(Screens)是一种特殊的对象,它没有父对象,创建一个屏幕如下:
lv_obj_t * scr1 = lv_obj_create(NULL);
屏幕可以被创建为任何对象类型,比如基础对象或者一张用作壁纸的图片。
2. 获取当前活动的屏幕
lvgl默认创建并加载了一个基础对象作为屏幕,要获取当前活动的屏幕,可以使用 lv_scr_act()
API。
/**
* Get the active screen of the default display
* @return pointer to the active screen
*/
static inline lv_obj_t * lv_scr_act(void);
3. 加载新屏幕
要加载一个新屏幕,API如下:
static inline void lv_scr_load(lv_obj_t * scr);
4. 动画加载屏幕
加载一个新屏幕的时候可以带上动画,使用下面的API:
/**
* Switch screen with animation
* @param scr pointer to the new screen to load
* @param anim_type type of the animation from `lv_scr_load_anim_t`. E.g. `LV_SCR_LOAD_ANIM_MOVE_LEFT`
* @param time time of the animation
* @param delay delay before the transition
* @param auto_del true: automatically delete the old screen
*/
void lv_scr_load_anim(lv_obj_t * scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del);
参数意义如下:
- scr:指向新屏幕的指针
- anim_type:动画类型
- time:动画时间
- delay:延迟时间后,动画开始,新屏幕变为当前活动屏幕
- auto_del:当动作结束时,是否自动删除旧的屏幕
其中动画类型anim_type支持以下值:
typedef enum {
LV_SCR_LOAD_ANIM_NONE,
LV_SCR_LOAD_ANIM_OVER_LEFT,
LV_SCR_LOAD_ANIM_OVER_RIGHT,
LV_SCR_LOAD_ANIM_OVER_TOP,
LV_SCR_LOAD_ANIM_OVER_BOTTOM,
LV_SCR_LOAD_ANIM_MOVE_LEFT,
LV_SCR_LOAD_ANIM_MOVE_RIGHT,
LV_SCR_LOAD_ANIM_MOVE_TOP,
LV_SCR_LOAD_ANIM_MOVE_BOTTOM,
LV_SCR_LOAD_ANIM_FADE_ON,
} lv_scr_load_anim_t;
eg2. 动画加载新屏幕
void lv_study_object1(void)
{
lv_obj_t* obj = lv_obj_create(lv_scr_act());
// 设置控件大小
lv_obj_set_size(obj, lv_pct(50), lv_pct(50));
// 设置控件位置
lv_obj_set_pos(obj, lv_pct(20), lv_pct(20));
// 创建新屏幕
lv_obj_t* scr2 = lv_obj_create(NULL);
// 动画加载新屏幕
lv_scr_load_anim(scr2, LV_SCR_LOAD_ANIM_MOVE_RIGHT, 2000, 2000, true);
// 创建新屏幕上的控件
lv_obj_t* obj2 = lv_obj_create(scr2);
lv_obj_set_size(obj2, lv_pct(20), lv_pct(20));
lv_obj_set_pos(obj2, lv_pct(50), lv_pct(50));
}
三、控件的Parts
Parts实在想不到用什么中文翻译~
一个控件可以包含多个Parts,比如按钮只有一个主Parts,而活动条则由背景、指示块,旋钮三个Parts组成。
Parts的名称组成结构为LV_ + <TYPE> _PART_ <NAME>
,比如 LV_BTN_PART_MAIN
和 LV_SLIDER_PART_KNOB
。
Parts通常在给对象添加风格(style)时使用,通过Parts可以给控件的不同Parts分别添加不同的Style。
四、对象的状态
对象的状态可以是下列状态中的一个或者多个:
-
LV_STATE_DEFAULT
Normal, released state -
LV_STATE_CHECKED
Toggled or checked state -
LV_STATE_FOCUSED
Focused via keypad or encoder or clicked via touchpad/mouse -
LV_STATE_FOCUS_KEY
Focused via keypad or encoder but not via touchpad/mouse -
LV_STATE_EDITED
Edit by an encoder -
LV_STATE_HOVERED
Hovered by mouse (not supported now) -
LV_STATE_PRESSED
Being pressed -
LV_STATE_SCROLLED
Being scrolled -
LV_STATE_DISABLED
Disabled state -
LV_STATE_USER_1
Custom state -
LV_STATE_USER_2
Custom state -
LV_STATE_USER_3
Custom state -
LV_STATE_USER_4
Custom state
状态通常是由lvgl自动切换的,但也可以手动改变状态,要完全覆盖当前状态,可以使用下面的API:
/**
* Set the state (fully overwrite) of an object.
* If specified in the styles, transition animations will be started from the previous state to the current.
* @param obj pointer to an object
* @param state the new state
*/
static void lv_obj_set_state(lv_obj_t * obj, lv_state_t new_state);
五、快照
可以为对象及其子对象生成快照。
lvgl思维导图
- 【腾讯文档】lvgl