摘要:打造个性化界面 Lvgl自定义控件开发 在嵌入式设备的界面开发过程中,选择好的UI框架可以提高开发效率以及UI界面的美观程度。如今,Lvgl作为UI开发的新秀,已经被广泛应用于各个领
打造个性化界面 Lvgl自定义控件开发
在嵌入式设备的界面开发过程中,选择好的UI框架可以提高开发效率以及UI界面的美观程度。如今,Lvgl作为UI开发的新秀,已经被广泛应用于各个领域,其方便的开发方式和强大的功能得到了越来越多开发者的关注。现在,我们一起来看看Lvgl如何实现自定义控件,实现个性化的UI界面吧。
一、 如何创建一个自定义控件
在Lvgl中,要想自定义一个控件,需要进行如下步骤:
1. 继承Lv_obj_t结构体
我们可以通过继承Lv_obj_t结构体来创建我们的自定义控件,这里值得注意的是,我们需要将派生出的结构体作为参数传入Lv_obj_create函数中。下面是一个自定义控件结构体的示例代码:
```c typedef struct { lv_obj_t obj; // 在这里添加控件的属性以及需要的数据结构 }my_widget_t; ```2. 重写自定义控件的回调函数
由于控件的行为不同,所以需要根据每个控件的实际需求重新实现回调函数,这里的回调函数并不是我们常用的一些响应函数,而是指控件事件的回调函数,如绘制事件、大小改变事件等等。下面是一些常见的控件回调函数的介绍:
- 绘制事件:我们可以根据需要重新绘制控件,为控件增添不同的外观(例如:边框、背景、阴影等等)。
- 大小改变事件:如果我们的控件可以进行拖拽操作或者根据不同的用户输入改变大小,那么这个事件就非常重要。
- 键盘事件:由于嵌入式设备的屏幕空间有限,因此有时我们需要通过键盘或者组合键来完成用户的输入操作。
- 其他事件:由于控件种类繁多,这里我们只介绍一些比较常见的控件回调函数。其他更多细节请参考Lvgl的官方文档。
3. 在控件链表中添加新的自定义控件
最后,我们需要将我们自定义的控件链接到控件链表中,这样就可以在UI界面中正常使用了。下面是一个控件链表初始化的代码示例:
```c /*初始化控件链表*/ void lv_widgets_init(void) { /*添加自定义控件*/ lv_obj_class_t *scr_class = lv_obj_class_get_static(lv_scr_act()); lv_obj_class_add_obj_type(scr_class, \"my_widget\"); lv_obj_class_set_style(cs, &style_my_widget_bg); // 设置自定义控件的样式 lv_obj_class_set_style(cs, &style_my_widget_fg); // 设置自定义控件的样式 } ```二、如何与现有控件进行联动
对于现有控件,我们也可以实现控件之间的联动,为嵌入式设备的界面带来更为丰富、具有交互性的功能。下面我们来介绍如何与现有的控件进行联动。
1. 添加接口函数
为了方便与自定义控件交互,我们可以给自定义控件添加一些外部接口,例如设置属性、获取属性、执行控件的操作等等。下面是一个自定义控件的添加外部接口的示例:
```c static inline void my_widget_set_width(lv_obj_t *obj, LV_COORD_T w) { lv_obj_set_width(obj, w); } static inline LV_COORD_T my_widget_get_width(const lv_obj_t *obj) { return lv_obj_get_width(obj); } ```2. 修改现有控件的回调函数
要实现控件之间的联动,我们还需要对现有控件进行一些修改。这里以按钮控件为例,来介绍如何将自定义控件与按钮控件进行联动:
```c /* 重写按钮控件的回调函数 */ static lv_res_t btn_new(struct _lv_obj_t * btn, lv_event_t event) { if(event == LV_EVENT_PRESSED){ /* 执行按钮的操作 */ } return LV_RES_OK; } /* 在自定义控件的回调函数中实现控件之间的联动 */ static void my_widget_event_cb(lv_obj_t *obj, lv_event_t event) { if(event == LV_EVENT_CLICKED) { lv_obj_t *btn = lv_obj_find_type(obj, LV_OBJ_TREE_PART_MAIN, \"lv_btn\"); if(btn != NULL) { btn_new(btn, LV_EVENT_PRESSED); } } } ```三、自定义控件的优化
对于一个好的UI框架来说,控件应该尽可能地轻便,避免浪费系统资源。下面是一些自定义控件的优化技巧:
1. 缓存控件的状态
在大多数情况下,控件状态的更改较少,因此我们可以使用缓存来避免不必要的状态更新。例如,在一个复杂的列表控件中,我们可以将列表项的状态缓存下来,当控件需要更新时,只针对改变的项进行状态更新,这样可以减少不必要的操作。下面是一个控件状态缓存的示例:
```c struct _my_widget_cache_t { uint8_t state; }my_widget_cache_t; void my_widget_create(lv_obj_t *parent, my_widget_t *widget) { /* 操作控件的state属性 */ my_widget_cache_t *cache = (my_widget_cache_t*)lv_obj_allocate_ext_attr(widget, sizeof(my_widget_cache_t)); cache->state = MY_WIDGET_DEF_STATE; } void my_widget_update(my_widget_t *widget, const my_widget_state_t *state) { my_widget_cache_t *cache = (my_widget_cache_t*)lv_obj_get_ext_attr(widget); lv_obj_invalidate(widget); } ```2. 避免无用的回调函数
在自定义控件的开发过程中,由于控件内容很少,因此有相对较短的事件周期,而对于一些复杂的控件,例如,列表控件、树控件等等,控件中的元素很多,因此事件周期会很慢,一些不必要的回调函数会显著影响控件的整体性能。因此,我们需要对无用的回调函数进行过滤和删除。
结束语
Lvgl是一个自由、开源、高效、跨平台的UI框架,在嵌入式领域具有极大的应用潜力。通过本文,我们了解了如何制作自定义控件、控件之间的联动和优化控件的性能,希望各位开发者能够在工作中加以运用,打造更具个性化的嵌入式设备UI界面。