在LVGL的List控件使用过程中,虽然通过触摸按键选择item,但是有些场景需要实体按键选取item,但是LVGL 的V8.3中没有像Emwin那样有函数选择list item的函数。LVGL中List引入了Group的概念,把列表项都添加到同一个group中。然后通过更改group的焦点达到选择list item的作用。
#include "LVGL/GUI_APP/lv_mainstart.h"
#include "lvgl.h"
#include <stdio.h>
#include "./BSP/KEY/key.h"
#define scr_act_width() lv_obj_get_width(lv_scr_act())
#define scr_act_height() lv_obj_get_height(lv_scr_act())
static lv_obj_t *list; ? ? ? ? ? ? ?/* 定义列表 */
static lv_obj_t *list_label; ? ? ? ?/* 定义标签 */
static const lv_font_t *font; ? ? ? /* 定义字体 */
extern lv_indev_t * indev_keypad;
lv_obj_t* BtnUp,*BtnDn, *label;
lv_group_t * group;
static void list_btn_event_cb(lv_event_t *e)
{
? ? lv_obj_t *list_btn = lv_event_get_target(e);? ? ? ? ? ? ? ? ? ? ? ? ??
? ? lv_label_set_text(list_label, lv_list_get_btn_text(list, list_btn));? ??
? ? lv_obj_add_state(list_btn, LV_STATE_FOCUS_KEY);? ? ? ? ? ? ? ? ??
}
下面是另外的触摸按键的UP/Down实现选择list item
由于没有找到重新聚焦group的函数,所以另辟蹊径,在up/down的事件回调函数中下发实体按键事件中。
static void event_btn_handler(lv_event_t *e)
{
? ? lv_obj_t* targetObj = lv_event_get_target(e);
? ? if (targetObj == BtnUp)
? ? {
? ? ? ?set_virl_key(KEY1_PRES);
? ? }
? ? if (targetObj == BtnDn)
? ? {
? ? ? ?set_virl_key(KEY0_PRES);
? ? }
}
static void lv_example_list(void)
{
? ? /* 根据屏幕大小设置字体 */
? ? if (scr_act_width() <= 320)
? ? {
? ? ? ? font = &lv_font_montserrat_14;
? ? }
? ? else if (scr_act_width() <= 480)
? ? {
? ? ? ? font = &lv_font_montserrat_16;
? ? }
? ? else
? ? {
? ? ? ? font = &lv_font_montserrat_18;
? ? }
? ? /* 创建左侧矩形背景 */
? ? lv_obj_t* obj_left = lv_obj_create(lv_scr_act()); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 创建一个基础对象 */
? ? lv_obj_set_width(obj_left, scr_act_width() * 0.7); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 设置宽度 */
? ? lv_obj_set_height(obj_left, scr_act_height() * 0.9); ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 设置高度 */
? ? lv_obj_align(obj_left, LV_ALIGN_LEFT_MID, 5, 0); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 设置位置 */
? ? lv_obj_update_layout(obj_left); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 手动更新物体的参数 */
? ? /* 创建右侧矩形背景 */
? ? lv_obj_t* obj_right = lv_obj_create(lv_scr_act()); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 创建一个基础对象 */
? ? lv_obj_set_width(obj_right, scr_act_width() - lv_obj_get_width(obj_left) - 15); /* 设置宽度 */
? ? lv_obj_set_height(obj_right, lv_obj_get_height(obj_left)); ? ? ? ? ? ? ? ? ? ? ?/* 设置高度 */
? ? lv_obj_align_to(obj_right, obj_left, LV_ALIGN_OUT_RIGHT_MID, 5, 0); ? ? ? ? ? ? /* 设置位置 */
? ? lv_obj_update_layout(obj_right); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 手动更新物体的参数 */
? ? /* 显示当前选项的文本内容 */
? ? list_label = lv_label_create(obj_right); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 创建标签 */
? ? lv_obj_set_width(list_label, lv_obj_get_width(obj_right) - 13); ? ? ? ? ? ? ? ? /* 设置标签的宽度 */
? ? lv_obj_align(list_label, LV_ALIGN_TOP_MID, 0, 5); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 设置标签位置 */
? ? lv_obj_update_layout(list_label); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 手动更新标签的参数 */
? ? lv_obj_set_style_text_align(list_label, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN); ? ?/* 设置标签文本对齐方式 */
? ? lv_label_set_text(list_label, "New"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 设置标签文本 */
? ? lv_obj_set_style_text_font(list_label, font, LV_PART_MAIN); ? ? ? ? ? ? ? ? ? ? /* 设置标签文本字体 */
?//
? BtnUp = lv_btn_create(obj_right);
? lv_obj_set_size(BtnUp, 100, 50);
? lv_obj_align(BtnUp, LV_ALIGN_TOP_RIGHT, -20, 100);
?// lv_obj_add_flag( BtnUp, LV_OBJ_FLAG_CHECKABLE ); ? ?
? lv_obj_add_event_cb(BtnUp, event_btn_handler,LV_EVENT_CLICKED,NULL);
? label = lv_label_create(BtnUp); ? ? ? ? ? ? ? ? //创建label
? lv_label_set_text(label, "Up"); ? ? ? ? ? ?//设置label的字内容
? lv_obj_center(label); ? ? ? ? ? ? ? ? ? ? ? ? ?//居中对象
? BtnDn = lv_btn_create(obj_right);
? lv_obj_set_size(BtnDn, 100, 50);
? lv_obj_align(BtnDn, LV_ALIGN_BOTTOM_RIGHT, -20, -100);
?// lv_obj_add_flag( BtnDn, LV_OBJ_FLAG_CHECKABLE ); ? ?
? lv_obj_add_event_cb(BtnDn, event_btn_handler, LV_EVENT_CLICKED, NULL);
? label = lv_label_create(BtnDn); ? ? ? ? ? ? ? ? //创建label
? lv_label_set_text(label, "Down"); ? ? ? ? ? ?//设置label的字内容
? lv_obj_center(label);
?///
? ? /* 创建列表 */
? ? list = lv_list_create(obj_left); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 创建列表 */
? ? lv_obj_set_width(list, lv_obj_get_width(obj_left) * 0.8); ? ? ? ? ? ? ? ? ? ? ? /* 设置列表宽度 */
? ? lv_obj_set_height(list, lv_obj_get_height(obj_left) * 0.9); ? ? ? ? ? ? ? ? ? ? /* 设置列表高度 */
? ? lv_obj_center(list); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 设置列表的位置 */
? ? lv_obj_set_style_text_font(list, font, LV_PART_MAIN); ? ? ? ? ? ? ? ? ? ? ? ? ? /* 设置字体 */
? ? /* 为列表添加按钮 */
? ? lv_obj_t* btn;
? ? ? ? group = lv_group_create();
lv_indev_set_group(indev_keypad, group);
? ? lv_list_add_text(list, "File"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 添加列表文本 */
? ? btn = lv_list_add_btn(list, LV_SYMBOL_FILE, "New"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 添加按钮 */
? ? lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); ? ? ? ? ? ?/* 添加按钮回调 */
lv_group_add_obj(group, btn);
? label = lv_label_create(btn); ? ? ? ? ? ? ? ? //创建label
? lv_label_set_text(label, "Down"); ? ? ? ? ? ?//设置label的字内容
? lv_obj_center(label);
?
? ? btn = lv_list_add_btn(list, LV_SYMBOL_DIRECTORY, "Open"); ? ? ? ? ? ? ? ? ? ? ? /* 添加按钮 */
? ? lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); ? ? ? ? ? ?/* 添加按钮回调 */
lv_group_add_obj(group, btn);
? ? btn = lv_list_add_btn(list, LV_SYMBOL_SAVE, "Save"); ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 添加按钮 */
? ? lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); ? ? ? ? ? ?/* 添加按钮回调 */
lv_group_add_obj(group, btn);
? ? btn = lv_list_add_btn(list, LV_SYMBOL_CLOSE, "Delete"); ? ? ? ? ? ? ? ? ? ? ? ? /* 添加按钮 */
? ? lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); ? ? ? ? ? ?/* 添加按钮回调 */
lv_group_add_obj(group, btn);
? ? btn = lv_list_add_btn(list, LV_SYMBOL_EDIT, "Edit"); ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 添加按钮 */
? ? lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); ? ? ? ? ? ?/* 添加按钮回调 */
?lv_group_add_obj(group, btn);
? ? lv_list_add_text(list, "Connectivity"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 添加列表文本 */
? ? btn = lv_list_add_btn(list, LV_SYMBOL_BLUETOOTH, "Bluetooth"); ? ? ? ? ? ? ? ? ?/* 添加按钮 */
? ? lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); ? ? ? ? ? ?/* 添加按钮回调 */
lv_group_add_obj(group, btn);
? ? btn = lv_list_add_btn(list, LV_SYMBOL_GPS, "Navigation"); ? ? ? ? ? ? ? ? ? ? ? /* 添加按钮 */
? ? lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); ? ? ? ? ? ?/* 添加按钮回调 */
lv_group_add_obj(group, btn);
? ? btn = lv_list_add_btn(list, LV_SYMBOL_USB, "USB"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 添加按钮 */
? ? lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); ? ? ? ? ? ?/* 添加按钮回调 */
lv_group_add_obj(group, btn);
? ? btn = lv_list_add_btn(list, LV_SYMBOL_BATTERY_FULL, "Battery"); ? ? ? ? ? ? ? ? /* 添加按钮 */
? ? lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); ? ? ? ? ? ?/* 添加按钮回调 */
lv_group_add_obj(group, btn);
? ? lv_list_add_text(list, "Exit"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 添加列表文本 */
? ? btn = lv_list_add_btn(list, LV_SYMBOL_OK, "Apply"); ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 添加按钮 */
lv_group_add_obj(group, btn);
? ? lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); ? ? ? ? ? ?/* 添加按钮回调 */
? ? btn = lv_list_add_btn(list, LV_SYMBOL_CLOSE, "Close"); ? ? ? ? ? ? ? ? ? ? ? ? ?/* 添加按钮 */
? ? lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); ? ? ? ? ? ?/* 添加按钮回调 */
lv_group_add_obj(group, btn);? ? ?
}
注意在添加实体按键group时需要注意变量的声明的先后顺序。在lv_port_indev_template.C中初始化实体按键后,不能立即添加组,除非需要被添加的obj已经声明赋值,否则就会错误死机。在例程中的
? ?/* 接着你需要用 `lv_group_t * group = lv_group_create()` 来创建组
? ? * 用 `lv_group_add_obj(group, obj)` 往组中添加物体
? ? * 并将这个输入设备分配到组中,以导航到它:
? ? * `lv_indev_set_group(indev_keypad, group);` */
当把注释取消后就是死机,无法找到原因,后来才发现,obj还没有声明赋值
void lv_mainstart(void)
{
? ? lv_example_list();
}
在key.c中添加按键和虚拟触摸按键的处理。
void set_virl_key(uint8_t key)
{
? ? vir_key = key;
}
uint8_t key_scan(uint8_t mode)
{
? ? static uint8_t key_up = 1; ?/* 按键按松开标志 */
? ? uint8_t keyval = 0;
? ? if (mode) key_up = 1; ? ? ? /* 支持连按 */
? ? if (key_up && (KEY0 == 0 || KEY1 == 0 || KEY2 == 0 || WK_UP == 1)) ?/* 按键松开标志为1, 且有任意一个按键按下了 */
? ? {
? ? ? ? delay_ms(10); ? ? ? ? ? /* 去抖动 */
? ? ? ? key_up = 0;
? ? ? ? if (KEY0 == 0) ?keyval = KEY0_PRES;
? ? ? ? if (KEY1 == 0) ?keyval = KEY1_PRES;
? ? ? ? if (KEY2 == 0) ?keyval = KEY2_PRES;
? ? ? ? if (WK_UP == 1) keyval = WKUP_PRES;
? ? }
? ? else if(vir_key!=0)
? ? {
? ? ? ? keyval = vir_key;
? ? ? ? vir_key = 0;
? ? }
? ? else if (KEY0 == 1 && KEY1 == 1 && KEY2 == 1 && WK_UP == 0) ? ? ? ? /* 没有任何按键按下, 标记按键松开 */
? ? {
? ? ? ? key_up = 1;
? ? }
? ? return keyval; ? ? ? ? ? ? ?/* 返回键值 */
}