此篇文章在2022年3月5日被記錄
在某些螢幕上我們沒有觸控功能,則需要使用按鍵操作控制元件
lvgl總共給了我們四種裝置輸入介面,分別是
1、LV_INDEV_TYPE_POINTER 觸控板或滑鼠
2、LV_INDEV_TYPE_KEYPAD 鍵盤或小鍵盤
3、LV_INDEV_TYPE_ENCODER 編碼器,帶有左/右轉和推動選項
4、LV_INDEV_TYPE_BUTTON 外部按鈕虛擬按下螢幕
我們使用實體按鍵適用第二種或第四種輸入方式,但是第四種輸入方式侷限性較大,只能作為一個按下螢幕的虛擬的點,也就是說,我們如果有三個按鍵,只能模擬三個點在螢幕按下;所以我們使用LV_INDEV_TYPE_KEYPAD 作為輸入方式。
LV_INDEV_TYPE_KEYPAD可以傳遞以下幾種狀態,如果可能我們可以連線一個真正的鍵盤來傳遞所有的值。
LV_KEY_NEXT 聚焦到下一個物件
LV_KEY_PREV 聚焦到上一個物件
LV_KEY_ENTER 觸發 LV_EVENT_PRESSED/CLICKED/LONG_PRESSED 等事件
LV_KEY_UP 增加值或向上移動
LV_KEY_DOWN 減少值或向下移動
LV_KEY_RIGHT 增加值或向右移動
LV_KEY_LEFT 減少值或向左移動
LV_KEY_ESC 關閉或退出(例如關閉 下拉選單)
LV_KEY_DEL 刪除(例如 文字區域 中右側的字元)
LV_KEY_BACKSPACE 刪除左邊的一個字元(例如在文字區域)
LV_KEY_HOME 跳到開頭/頂部(例如在 文字區域)
LV_KEY_END 跳到最後(例如在 文字區域)
如何在我們的工程中實現鍵盤功能:
1、硬體上必須要有三個按鍵,根據自己的連線方式進行初始化:
void key_init(void)
{
gpio_pad_select_gpio(KEY1);
gpio_pad_select_gpio(KEY2);
gpio_pad_select_gpio(KEY3);
gpio_pad_select_gpio(KEY4);
gpio_pad_pullup(KEY1);
gpio_pad_pullup(KEY2);
gpio_pad_pullup(KEY3);
gpio_pad_pullup(KEY4);
gpio_set_direction(KEY1, GPIO_MODE_INPUT);
gpio_set_direction(KEY2, GPIO_MODE_INPUT);
gpio_set_direction(KEY3, GPIO_MODE_INPUT);
gpio_set_direction(KEY4, GPIO_MODE_INPUT);
}
2、設定按鍵讀取函式,返回值與上述鍵值相對應:
int read_key(void)
{
if(gpio_get_level(KEY1)==0)
{
return LV_KEY_PREV;
}
else if (gpio_get_level(KEY2)==0)
{
return LV_KEY_NEXT;
}
else if (gpio_get_level(KEY4)==0)
{
return LV_KEY_ENTER;
}
else
{
return -1;
}
}
3、在初始化函式中配置註冊裝置:
lv_indev_t *mydev=NULL; //這個與後續的group相繫結
lv_indev_drv_t indev_drv_key;
lv_indev_drv_init(&indev_drv_key);
indev_drv_key.read_cb = button_read;
indev_drv_key.type = LV_INDEV_TYPE_KEYPAD;
mydev=lv_indev_drv_register(&indev_drv_key);
4、裝置回撥函式:
void button_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
static uint32_t last_btn = 0; /*Store the last pressed button*/
int btn_pr = read_key(); /*Get the ID (0,1,2...) of the pressed button*/
if(btn_pr >= 0) { /*Is there a button press? (E.g. -1 indicated no button was pressed)*/
last_btn = btn_pr; /*Save the ID of the pressed button*/
data->state = LV_INDEV_STATE_PRESSED; /*Set the pressed state*/
} else {
data->state = LV_INDEV_STATE_RELEASED; /*Set the released state*/
}
data->key = last_btn; /*Save the last button*/
}
5、新增了裝置還要與group相繫結,不然無法起到作用,新建三個物件用來做演示:
extern lv_indev_t *mydev;
static void btn_event_handler(lv_event_t * e)//按鍵回撥函式
{
lv_event_code_t code = lv_event_get_code(e);
if(code == LV_EVENT_CLICKED) {
LV_LOG_USER("Clicked");
}
else if(code == LV_EVENT_VALUE_CHANGED) {
LV_LOG_USER("Toggled");
}
}
static void event_handler(lv_event_t * e)//滑塊回撥函式
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
static int i = 0;
if(code == LV_EVENT_CLICKED){
printf("\r\nclick = %d",code);
if(i++ >12)
i=0;
lv_roller_set_selected(obj, i, LV_ANIM_ON);
}
}
void lv_example(void)
{
lv_obj_t *scr = lv_scr_act();
lv_group_t *group = lv_group_create();
lv_group_set_default(group);
lv_indev_set_group(mydev, group);
lv_group_focus_obj(group); //分組聚焦到物件
lv_group_set_editing(group, true); //編輯模式
lv_obj_t * label;
lv_obj_t * btn1 = lv_btn_create(lv_scr_act());
lv_obj_add_event_cb(btn1, btn_event_handler, LV_EVENT_ALL, NULL);
lv_obj_align(btn1, LV_ALIGN_CENTER, -50, -40);
label = lv_label_create(btn1);
lv_label_set_text(label, "Button");
lv_obj_center(label);
lv_obj_t * btn2 = lv_btn_create(lv_scr_act());
lv_obj_add_event_cb(btn2, btn_event_handler, LV_EVENT_ALL, NULL);
lv_obj_align(btn2, LV_ALIGN_CENTER, -50, 40);
lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);
lv_obj_set_height(btn2, LV_SIZE_CONTENT);
label = lv_label_create(btn2);
lv_label_set_text(label, "Toggle");
lv_obj_center(label);
lv_obj_t *roller1 = lv_roller_create(scr);
lv_roller_set_options(roller1,
"January\n"
"February\n"
"March\n"
"April\n"
"May\n"
"June\n"
"July\n"
"August\n"
"September\n"
"October\n"
"November\n"
"December",
LV_ROLLER_MODE_INFINITE);
lv_roller_set_visible_row_count(roller1, 4);
lv_obj_set_pos(roller1,150,100);
lv_obj_add_event_cb(roller1, event_handler, LV_EVENT_ALL, NULL);
lv_group_add_obj(group ,btn1);
lv_group_add_obj(group ,btn2);
lv_group_add_obj(group ,roller1);
}
最終效果: