LVGL 本身会完成:

  • 触摸坐标命中检测;
  • 判断最上层可点击对象;
  • 按下、移动、释放;
  • 点击和长按;
  • 列表拖动滚动;
  • 按钮、开关、滑块状态变化;
  • 弹窗遮罩和控件层级处理。

我们只需要做两件事:

  1. 把触摸芯片坐标送给 LVGL;
  2. 给按钮注册 LV_EVENT_CLICKED 等事件。

触摸驱动

定时调用触摸驱动,判断是否有触摸和当前触摸的坐标

void Touch_Read(uint16_t *x, uint16_t *y)
{
	//触摸驱动
}

LVGL输入

LVGL 主动调用 read_cb,把内部 lv_indev_data_t 的地址放进来;回调里把坐标和按下状态写进 data->point / data->state,LVGL 返回后自己读走这些值。

static void touch_read_cb(lv_indev_drv_t *drv,lv_indev_data_t *data)
{
    uint16_t x;
    uint16_t y;
    bool pressed;
    (void)drv;

    pressed = Touch_Read(&x, &y);

    data->point.x = x;
    data->point.y = y;
    data->state = pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
}

void touch_indev_init(void)
{
    static lv_indev_drv_t driver;

    lv_indev_drv_init(&driver);
    driver.type = LV_INDEV_TYPE_POINTER;
    driver.read_cb = touch_read_cb; // lvgl内部定时回调

    lv_indev_drv_register(&driver);
}

按钮

lv_obj_t *button = lv_btn_create(parent);
lv_obj_set_pos(button, 20, 60);
lv_obj_set_size(button, 120, 40);

static void button_clicked_cb(lv_event_t *event)
{
    /* 执行按钮业务 */
}

lv_obj_add_event_cb(button,button_clicked_cb,LV_EVENT_CLICKED,NULL); //点击事件

当用户触摸 (30, 70) 时,LVGL 会自动:

读取触摸坐标
→ 遍历当前页面对象树
→ 找到坐标下最上层的按钮
→ 发送 LV_EVENT_PRESSED
→ 触摸释放
→ 发送 LV_EVENT_RELEASED
→ 满足点击条件
→ 发送 LV_EVENT_CLICKED
→ button_clicked_cb()

应用层完全不需要写:

if (x >= 20 && x <= 140 &&
    y >= 60 && y <= 100) {
    /* 用户点了这个按钮 */
}