LVGL官方文档-7.11.0-5-Porting-Input device interface

Types of input devices

配置输入设备的时候,需要初始化一个lv_indev_drv_t类型的变量:

lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);      /*Basic initialization*/
indev_drv.type =...                 /*See below.*/
indev_drv.read_cb =...              /*See below.*/
/*Register the driver in LVGL and save the created input device object*/
lv_indev_t * my_indev = lv_indev_drv_register(&indev_drv);

上述代码中type可以是如下值之一:

  • LV_INDEV_TYPE_POINTER 触摸板或者鼠标
  • LV_INDEV_TYPE_KEYPAD 键盘或者按键板
  • LV_INDEV_TYPE_ENCODER 能左、右、按下的编码器
  • LV_INDEV_TYPE_BUTTON 外部的能按屏幕的按键

read_cb是一个函数指针,这个函数会被周期性的调用来报告一个输入设备的当前状态。它也可以缓存数据。当缓存中没有数据读的时候,返回false,当缓存非空的时候,返回true。

请前往Input devices章节获取更多关于输入设备的信息。

Touchpad, mouse or any pointer

可以点击屏幕上的点的设备属于这一类。

indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_input_read;

...

bool my_input_read(lv_indev_drv_t * drv, lv_indev_data_t*data)
{
    data->point.x = touchpad_x;
    data->point.y = touchpad_y;
    data->state = LV_INDEV_STATE_PR or LV_INDEV_STATE_REL;
    return false; /*No buffering now so no more data read*/
}

提示:这一类设备在“LV_INDEC_STATE_REL”状态的时候,也要报告X/Y的坐标。

Keypad or keyboard

有完整字母的键盘,或者只有几个导航按键的按键板输入这一类。

要使用键盘或者按键板,需要做下面这些事情:

  • 用LV_INDEV_TYPE_KEYPAD类型注册read_cb。
  • 在lv_conf.h中使能LV_USE_GROUP。
  • 用lv_group_t *g = lv_group_create()创建对象组,然后用lv_group_add_obj(g, obj)向对象组中添加对象。
  • 用lv_indev_set_group(my_indev, g)将创建的对象组赋值给输入设备。其中,my_indev是lv_indev_drv_register()的返回值。
  • 用LV_KEY_…在组内的对象之间导航。键值详见lv_core/lv_group.h。
indev_drv.type = LV_INDEV_TYPE_KEYPAD;
indev_drv.read_cb = keyboard_read;

...

bool keyboard_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
  data->key = last_key();            /*Get the last pressed or released key*/

  if(key_pressed()) data->state = LV_INDEV_STATE_PR;
  else data->state = LV_INDEV_STATE_REL;

  return false; /*No buffering now so no more data read*/
}

Encoder

用编码器,你可以做以下4件事:

  1. 短按其按键;
  2. 长按其按键
  3. 左转;
  4. 右转;

简而言之,编码器类输入设备的工作方式如下:

  • 通过转编码器,你可以在对象之间移动焦点。
  • 在简单对象(例如按键)上按编码器,这个对象将会被点击。
  • 在复杂对象(例如列表,消息盒子等等)上按编码器,对象会进入编辑模式,这个时候,转编码器能在这个复杂对象内部移动焦点。
  • 长按按键,退出编辑模式。

与按键板类似,要使用编码器,对象需要添加到对象组里。

indev_drv.type = LV_INDEV_TYPE_ENCODER;
indev_drv.read_cb = encoder_read;

...

bool encoder_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
  data->enc_diff = enc_get_new_moves();

  if(enc_pressed()) data->state = LV_INDEV_STATE_PR;
  else data->state = LV_INDEV_STATE_REL;

  return false; /*No buffering now so no more data read*/
}

Using buttons with Encoder logic

除了标准的编码器行为以外,你也可以利用其逻辑用按键来移动焦点,编辑控件。如果你只有几个按键的时候,这会非常方便。或者可以同时使用按键和编码器。

你需要有三个按键可用:

  • LV_KEY_ENTER 模拟编码器的按钮
  • LV_KEY_LEFT 模拟编码器左转
  • LV_KEY_RIGHT 模拟编码器右转
  • 其他按键将传递给有焦点的空间

如果按住按键不放,将会模拟周期性的编码器点击事件。周期由indev_drv.long_press_rep_time来指定。

indev_drv.type = LV_INDEV_TYPE_ENCODER;
indev_drv.read_cb = encoder_with_keys_read;

...

bool encoder_with_keys_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
  data->key = last_key();            /*Get the last pressed or released key*/
                                     /* use LV_KEY_ENTER for encoder press */
  if(key_pressed()) data->state = LV_INDEV_STATE_PR;
  else {
      data->state = LV_INDEV_STATE_REL;
      /* Optionally you can also use enc_diff, if you have encoder*/
      data->enc_diff = enc_get_new_moves();
  }

  return false; /*No buffering now so no more data read*/
}

Button

按键的意思是放在屏幕旁边映射到屏幕固定坐标的实际按键。如果一个按键被按下了,就将模拟按在屏幕上映射的坐标处。(类似于触摸板)

用lv_indev_set_button_points(my_indev, points_array)来映射按键到坐标。其中,points_array是这个样子的:const lv_point_t points_array[] = {{10, 30}, {60. 90}, …}

需要注意的是,points_array需要是全局的,或者是函数里面的静态变量。

indev_drv.type = LV_INDEV_TYPE_BUTTON;
indev_drv.read_cb = button_read;

...

bool 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 = my_btn_read();     /*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_PR;  /*Set the pressed state*/
    } else {
       data->state = LV_INDEV_STATE_REL; /*Set the released state*/
    }

    data->btn = last_btn;            /*Save the last button*/

    return false;                    /*No buffering now so no more data read*/
}

Other features

除了read_cb之外,lv_indev_drv_t中还有一个feedback_cb回调可以用。feedback_cb在输入设备发送任何类型的事件的时候都会被调用。(与设备类型无关)。这能实现给用户的反馈,例如LV_EVENT_CLICK时间发生时,播放一个音效。

下面这些参数的默认值可以在lv_conf.h中设置,但是这些默认值在lv_indev_drv_t变量中可以被覆盖。

  • drag_limit 在实际拖动object之前,移动的像素数。
  • drag_throw 拖动放开时的减速速度,单位是【%】。值越大,减速越快。
  • long_press_time 按下多长时间发送LV_EVENT_LONG_PRESSED(单位毫秒)。
  • long_press_rep_time 发送LV_EVENT_LONG_PRESSED_REPEAT的时间间隔。
  • read_task 指向lv_task的指针,这个函数使用来读取输入设备的。他的参数可以用lv_task_…()函数来改变。

每个输入设备都被分配到一个display。默认情况下,新的输入设备被添加到最后创建或者最后选择(用lv_disp_set_default())的display。分配到的display存储在disp域,并且可以改变。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值