在某些屏幕上我们没有触摸功能,则需要使用按键操作控件

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);
}

最终效果:
demo.gif