09. 按键矩阵部件
一、按钮矩阵部件
在 LVGL 中,按钮矩阵部件相当于一系列伪按钮的集合,它按一定的序列来排布这些按钮。这些伪按钮并不是真正的按钮部件(lv_btn),它们只是具有按钮外观的图形,但这些图形具有和按钮一样的点击效果。伪按钮所占的内存非常小,一个伪按钮大概占用 8 个字节,而一个普通按钮部件所占的内存大概为 100 ~ 150 个字节。
按钮矩阵部件由两个部分组成:主体背景(LV_PART_MAIN)和 按钮(LV_PART_ITEMS),示意图如下:
LVGL 官方提供了一些与按钮矩阵部件相关 API。
#define lv_btnmatrix_create lv_buttonmatrix_create
lv_obj_t * lv_buttonmatrix_create(lv_obj_t * parent); // 创建按钮矩阵部件
#define lv_btnmatrix_set_map lv_buttonmatrix_set_map
void lv_buttonmatrix_set_map(lv_obj_t * obj, const char * map[]); // 设置多个按钮属性
#define lv_btnmatrix_set_selected_btn lv_buttonmatrix_set_selected_button
void lv_buttonmatrix_set_selected_button(lv_obj_t * obj, uint32_t btn_id); // 设置选中的按钮
#define lv_btnmatrix_set_btn_ctrl lv_buttonmatrix_set_button_ctrl
void lv_buttonmatrix_set_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl); // 设置一个按钮的属性
#define lv_btnmatrix_clear_btn_ctrl lv_buttonmatrix_clear_button_ctrl
void lv_buttonmatrix_clear_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl); // 清除某个按钮的属性
#define lv_btnmatrix_set_btn_ctrl_all lv_buttonmatrix_set_button_ctrl_all
void lv_buttonmatrix_set_button_ctrl_all(lv_obj_t * obj, lv_buttonmatrix_ctrl_t ctrl); // 设置所有按钮的属性
#define lv_btnmatrix_has_button_ctrl lv_buttonmatrix_has_button_ctrl
bool lv_buttonmatrix_has_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl); // 获取按钮的状态
#define lv_btnmatrix_set_btn_width lv_buttonmatrix_set_button_width
void lv_buttonmatrix_set_button_width(lv_obj_t * obj, uint32_t btn_id, uint32_t width); // 设置单个按钮的相对宽度
#define lv_btnmatrix_set_one_checked lv_buttonmatrix_set_one_checked
void lv_buttonmatrix_set_one_checked(lv_obj_t * obj, bool en); // 设置按钮互斥
#define lv_btnmatrix_get_one_checked lv_buttonmatrix_get_one_checked
bool lv_buttonmatrix_get_one_checked(const lv_obj_t * obj); // 判断按钮互斥是否开启
#define lv_btnmatrix_get_map lv_buttonmatrix_get_map
const char ** lv_buttonmatrix_get_map(const lv_obj_t * obj); // 获取按钮相关映射
#define lv_btnmatrix_get_selected_btn lv_buttonmatrix_get_selected_button
uint32_t lv_buttonmatrix_get_selected_button(const lv_obj_t * obj); // 获取用户最后点击的按钮的索引
#define lv_btnmatrix_get_btn_text lv_buttonmatrix_get_button_text
const char * lv_buttonmatrix_get_button_text(const lv_obj_t * obj, uint32_t btn_id); // 获取按钮的文本
我们可以使用 lv_btnmatrix_create()
函数 创建按钮矩阵部件。
/**
* @brief 创建按钮矩阵部件
*
* @param parent 指向父部件的指针
* @return lv_obj_t* 指向按键矩阵部件的指针
*/
lv_obj_t * lv_btnmatrix_create(lv_obj_t * parent);
在 LVGL中,按钮矩阵部件中的每个按钮都可以设置文本,如果用户想设置这些按钮文本,则需要定义一个字符串数组(指针),并在该数组中传入所需的文本内容,最后通过 lv_btnmatrix_set_map()
函数设置按钮文本。
/**
* @brief 设置多个按钮属性
*
* @param obj 指向按钮矩阵对象的指针
* @param map 指针一个字符串数组,最后一个元素必须为空,可以使用 "\n" 换行
*/
void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]);
该数组最后一个元素必须为空。
如果用户需要让按钮换行,可以在字符串数组中使用换行符 "\n"。
在默认情况下,按钮矩阵每一行按钮的宽度都是自动计算的,如果用户想改变按钮的宽度,可以调用 lv_btnmatrix_set_btn_width()
函数来进行设置。在按钮矩阵部件中,按钮只能设置 相对宽度。
/**
* @brief 设置单个按钮的相对宽度
*
* @param obj 指向按钮矩阵部件的指针
* @param btn_id 按钮索引
* @param width 相对宽度,可选值的范围:1~7
*/
void lv_btnmatrix_set_btn_width(lv_obj_t * obj, uint32_t btn_id, uint32_t width);
用户可以调用 lv_btnmatrix_set_btn_ctrl()
函数,为按钮添加、清除指定的属性,这些属性的相关枚举如下:
#define LV_BTNMATRIX_CTRL_HIDDEN LV_BUTTONMATRIX_CTRL_HIDDEN // 按钮隐藏
#define LV_BTNMATRIX_CTRL_NO_REPEAT LV_BUTTONMATRIX_CTRL_NO_REPEAT // 禁用长按
#define LV_BTNMATRIX_CTRL_DISABLED LV_BUTTONMATRIX_CTRL_DISABLED // 禁用按钮
#define LV_BTNMATRIX_CTRL_CHECKABLE LV_BUTTONMATRIX_CTRL_CHECKABLE // 启用按钮状态切换
#define LV_BTNMATRIX_CTRL_CHECKED LV_BUTTONMATRIX_CTRL_CHECKED // 选中按钮
#define LV_BTNMATRIX_CTRL_CLICK_TRIG LV_BUTTONMATRIX_CTRL_CLICK_TRIG // 启用:在点击时发送 LV_EVENT_VALUE_CHANGE;禁用:在按下时发送 LV_EVENT_VALUE_CHANGE
#define LV_BTNMATRIX_CTRL_POPOVER LV_BUTTONMATRIX_CTRL_POPOVER // 此按钮时在弹出窗口中显示按钮标签
#define LV_BTNMATRIX_CTRL_CUSTOM_1 LV_BUTTONMATRIX_CTRL_CUSTOM_1 // 可自定义使用的标志
#define LV_BTNMATRIX_CTRL_CUSTOM_2 LV_BUTTONMATRIX_CTRL_CUSTOM_2 // 可自定义使用的标志
按钮互斥 是指在某一时刻,只允许有一个按钮处于按下不弹起状态(被选中),当我们选中一个按钮之后,其他的按钮将会自动清除选中属性。用户可以调用 lv_btnmatrix_set_one_checked()
函数,开启按钮互斥功能。
/**
* @brief 设置按钮互斥
*
* @param obj 指向按钮矩阵部件的指针
* @param en 是否启用按钮互斥功能
*/
void lv_btnmatrix_set_one_checked(lv_obj_t * obj, bool en);
二、实验例程
#include "lvgl.h"
#include "lv_port_disp_template.h"
#include "lv_port_indev_template.h"
lv_obj_t *label;
int main(void)
{
const char *map[] = {"Sakura", "\n", "Akame", "Kurome", ""};
HAL_Init();
System_Clock_Init(8, 336, 2, 7);
Delay_Init(168);
SPI_Simulate_Init();
// SRAM_Init();
TIM_Base_Init(&g_tim6_handle, TIM6, 83, 999);
__HAL_TIM_CLEAR_IT(&g_tim6_handle, TIM_IT_UPDATE); // 清除更新中断标志位
HAL_TIM_Base_Start_IT(&g_tim6_handle); // 使能更新中断,并启动计数器
lv_init();
lv_port_disp_init();
lv_port_indev_init();
// 测试代码
label = lv_label_create(lv_scr_act()); // 创建标签部件
lv_obj_set_align(label, LV_ALIGN_TOP_MID); // 设置标签部件考上居中对齐
lv_obj_set_style_text_font(label, &lv_font_montserrat_30, LV_PART_MAIN); // 设置标签部件的字体样式
lv_label_set_text(label, "buttonMatrix test"); // 设置标签部件的文本
lv_obj_t *buttonMatrix = lv_btnmatrix_create(lv_scr_act()); // 创建按钮矩阵部件
lv_obj_center(buttonMatrix); // 将按钮矩阵部件居中
lv_btnmatrix_set_map(buttonMatrix, map); // 设置按钮矩阵部件的映射表
lv_btnmatrix_set_btn_width(buttonMatrix, 1, 2); // 设置按钮的相对宽度
lv_btnmatrix_set_btn_ctrl_all(buttonMatrix, LV_BTNMATRIX_CTRL_CHECKABLE); // 启用按钮状态切换
lv_btnmatrix_set_one_checked(buttonMatrix, true); // 设置按钮单次选中
lv_obj_add_event_cb(buttonMatrix, buttonMatrix_event_cb, LV_EVENT_CLICKED, NULL);
while (1)
{
lv_timer_handler();
Delay_ms(5);
}
return 0;
}
void buttonMatrix_event_cb(lv_event_t *e)
{
lv_event_code_t code = lv_event_get_code(e); // 获取事件的事发类型
lv_obj_t *target = lv_event_get_target(e); // 获取事件的触发源
uint8_t id = 0;
const char *text;
if (code == LV_EVENT_CLICKED)
{
id = lv_btnmatrix_get_selected_btn(target); // 获取按键的索引
text = lv_btnmatrix_get_btn_text(target, id); // 获取按键的文本
lv_label_set_text(label, text);
}
}