使用方法
源码 gui_scr_mgr.c 和 gui_scr_mgr.h 见最后参考资料,下面我会介绍一下使用方法,至于原理下面也有一些解释。
1、初始化,假设 LVGL 的入口是 lvgl_app_init();然后初始化我们界面管理系统,21行初始化界面管理系统,22行设置界面的根界面。当然需要包括头文件 gui_scr_mgr.h。
2、创建界面,假设创建界面 gui_main_scr.c 和 gui_main_scr.h。gui_main_scr.c 界面的框架如下(需要按照此框架写自己的代码),Create 创建 LVGL 控件;Enter 注册事件;Layout 界面的布局; Exit 与 Enter 对应,注销在 Enter 注册的事件,Destroy 与 Create 对应,释放在 Create 申请的空间。
gui_main_scr.h 的内容如下。
3、声明 ID 和界面结构体 Handle,下面以添加界面 gui_main_scr 为例,添加 ID,ID 必须放到全局的 .h 文件中。
声明界面结构体,在 gui_scr_mgr.c 中,将界面结构体放到界面管理系统中;然后在 gui_scr_mgr.h 中声明界面结构体。
4、按照上面的方法,在创建一个界面,然后在两个界面中添加一下控件,然后在控件的回调中去调用界面管理的 push 和 pop 函数。运行效果如下图所示,详情见参考资料 vs2019 工程。
1、简介
What is LVGL?
LVGL is the most popular free and open source embedded graphics library to create beautiful UIs for any MCU, MPU and display type. It has all the features to create modern and smartphone-like GUIs: 30+ built-in widgets, a powerful style system, web inspired layout managers, and a typography system
LVGL 之前好像叫做 litterVGL 不知道啥时候改名了,LVGL 和 litterVGL 说的是一个东西。相比于其他的嵌入式 UI,LVGL 的优势在于:1、它是免费开源的,白嫖的力量自然不用多说。2、第二个是它的 UI 风格类似于移动端,是比较好看的,更符合现在人的审美。3、它是跨平台的,基本上是适用于任何 MCU、MPC上显示。正事它的这些优势,LVGL 得以在最近一些年可以流行起来。
2、界面调度机制
LVGL 虽然提供了 30+ 的组件,和上百种的样式,还支持之定义组件,但是 LVGL 还是缺少了界面管理的功能,所以 LVGL 需要我们关注一下页面管理机制(项目的 GUI 交互不因该只停留在一个界面上)。管理界面管理的机制可以参考 Android 的实现,主要关注的是界面生命周期和界面返回栈,这个在最后的参考资料中给出。
2.1 界面的生命周期
嵌入式 UI 和移动端的 UI 还是有比较大的差距的,所以也不用弄得和 Android 的 Activity 生命周期弄那么复杂,简单概括一下就是,LVGL 的一个界面生命周期有如下几个状态:创建界面和组件、进入界面、界面布局、退出界面、销毁界面,示意图如下。至于下面的从 Exit 到 Entry 状态的转变涉及到界面返回栈,后面会分享到。
各个部分的主要功能如下表,这样就对界面处于某一状态下的功能有了具体的定义。这样就可以用一个结构体对一个界面进行描述了(见代码实现部分)。
Create | 界面 obj 的创建、各种组件的创建、定时器创建 |
Entry | 为组件添加事件,开启定时器,注册监听器 |
Layout | 对界面进行布局,界面处于活跃状态 |
Exit | 屏蔽组件事件,暂停定时器,注销监听器 |
Destroy | 销毁组件、销毁定时器、销毁界面 |
2.2 界面返回栈
界面返回栈是执行某项工作时产生的界面的集合,并按照界面打开的顺序排列在返回栈中,如下图所示,打开一个界面就向返回栈中执行 push 操作,关闭一个界面就执行一个 pop 操作。 这样做的好处是,界面与界面之间相互独立,也不用判断界面之间的跳转关系。
举个例子说明返回栈的优势,如下图所示,假设我们从主界面 scr1 执行了一些操作让其到 scr5 上,那么界面的打开顺序是 scr1 -> scr2 -> scr5,如果用户执行完操作后,关闭了 scr5,那需要在 scr5 中判断要返回到 scr2 上,而不是返回到 scr3、scr4、scr6 上。这样的操作会让界面之间存在关联,会导致在界面较多的时候,难以更改界面的跳转逻辑。
而返回栈就避免了这样问题,在界面打开的时候,就已经记录了界面的打开顺序,要想返回上一个打开的界面,直接执行 pop 操作就可以了。如下图所示,闭关界面 scr5 后,进入的是 scr2。
返回栈的 push 和 pop 操作对应界面的生命周期如下图。以 push 和 pop scr2 为例,绿色为界面的活跃状态,绿色条纹表示界面正在构建中,灰色表示界面的退出态(Exit)。
当有新的界面 scr2 入栈时,前一个界面 scr1 会进入 Exit 态;当 scr2 退出时,会先进入 Exit 态,最后在进入销毁态(Destory);这样做是确保在销毁界面前,关闭界面相关的回调、定时器等事件。
参考资料
VS2019模拟器工程:GitHub - ShallowGreen123/lvgl_mydemo: Daily development
见源码scr模块:https://github.com/ShallowGreen123/data
界面生命周期:SystemView
界面返回栈:Android 界面返回栈