1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

scroll: handle horizontayl scrolling

This commit is contained in:
Gabor Kiss-Vamosi 2020-07-14 15:23:20 +02:00
parent ce0fb2da4d
commit f3a1028064
3 changed files with 159 additions and 41 deletions

View File

@ -1259,7 +1259,7 @@ static void indev_drag(lv_indev_proc_t * proc)
/*Go until find the object or parent scrollable in this direction*/ /*Go until find the object or parent scrollable in this direction*/
while(proc->types.pointer.drag_obj) { while(proc->types.pointer.drag_obj) {
/*Get which object to drad/scroll*/ /*Get which object to drad/scroll*/
lv_drag_dir_t dirs = LV_DRAG_DIR_VER; //scrollable ? lv_obj_get_scroll_dir(target_obj) : lv_obj_get_drag_dir(target_obj); lv_drag_dir_t dirs = LV_DRAG_DIR_ONE; //scrollable ? lv_obj_get_scroll_dir(target_obj) : lv_obj_get_drag_dir(target_obj);
/*Enough move?*/ /*Enough move?*/
bool hor_en = false; bool hor_en = false;
@ -1282,16 +1282,32 @@ static void indev_drag(lv_indev_proc_t * proc)
lv_coord_t st = lv_obj_get_scroll_top(proc->types.pointer.drag_obj); lv_coord_t st = lv_obj_get_scroll_top(proc->types.pointer.drag_obj);
lv_coord_t sb = lv_obj_get_scroll_bottom(proc->types.pointer.drag_obj); lv_coord_t sb = lv_obj_get_scroll_bottom(proc->types.pointer.drag_obj);
lv_coord_t sl = lv_obj_get_scroll_left(proc->types.pointer.drag_obj);
lv_coord_t sr = lv_obj_get_scroll_right(proc->types.pointer.drag_obj);
if((up_en && proc->types.pointer.drag_sum.y >= indev_act->driver.drag_limit) || bool ver_scrollable = st > 0 || sb > 0 ? true : false;
(down_en && proc->types.pointer.drag_sum.y <= - indev_act->driver.drag_limit)) bool hor_scrollable = sl > 0 || sr > 0 ? true : false;
if(ver_scrollable &&
((up_en && proc->types.pointer.drag_sum.y >= indev_act->driver.drag_limit) ||
(down_en && proc->types.pointer.drag_sum.y <= - indev_act->driver.drag_limit)))
{ {
scroll_candidate_obj = proc->types.pointer.drag_obj; scroll_candidate_obj = proc->types.pointer.drag_obj;
dirs_candidate = LV_DRAG_DIR_VER; dirs_candidate = LV_DRAG_DIR_VER;
} }
if(hor_scrollable &&
((left_en && proc->types.pointer.drag_sum.x >= indev_act->driver.drag_limit) ||
(right_en && proc->types.pointer.drag_sum.x <= - indev_act->driver.drag_limit)))
{
scroll_candidate_obj = proc->types.pointer.drag_obj;
dirs_candidate = LV_DRAG_DIR_HOR;
}
if(st <= 0) up_en = false; if(st <= 0) up_en = false;
if(sb <= 0) down_en = false; if(sb <= 0) down_en = false;
if(sl <= 0) left_en = false;
if(sr <= 0) right_en = false;
/*If a move is greater then LV_DRAG_LIMIT then begin the drag*/ /*If a move is greater then LV_DRAG_LIMIT then begin the drag*/
@ -1350,15 +1366,16 @@ static void indev_drag(lv_indev_proc_t * proc)
if(scrollable) { if(scrollable) {
lv_area_t child_box; lv_area_t child_box;
lv_obj_get_children_box(obj, &child_box); lv_obj_get_children_box(obj, &child_box);
lv_coord_t diff_y = proc->types.pointer.vect.y; lv_coord_t diff_y = proc->types.pointer.drag_dir == LV_DRAG_DIR_VER ? proc->types.pointer.vect.y : 0;
if(obj->scroll.y > 0 && diff_y > 0) { lv_coord_t diff_x = proc->types.pointer.drag_dir == LV_DRAG_DIR_HOR ? proc->types.pointer.vect.x : 0;
diff_y = diff_y / 2; if(obj->scroll.x > 0 && diff_x > 0) {
diff_x = diff_x / 2;
} }
if(child_box.y2 < obj->coords.y2 && diff_y < 0) { if(child_box.y2 < obj->coords.y2 && diff_y < 0) {
diff_y = diff_y / 2; diff_y = diff_y / 2;
} }
lv_obj_scroll_by(obj, 0, diff_y, LV_ANIM_OFF); lv_obj_scroll_by(obj, diff_x, diff_y, LV_ANIM_OFF);
} else { } else {
lv_obj_set_pos(obj, act_x, act_y); lv_obj_set_pos(obj, act_x, act_y);
} }
@ -1425,8 +1442,14 @@ static void indev_drag_throw(lv_indev_proc_t * proc)
switch(proc->types.pointer.drag_dir) { switch(proc->types.pointer.drag_dir) {
case LV_DRAG_DIR_HOR: case LV_DRAG_DIR_HOR:
{
proc->types.pointer.drag_throw_vect.y = 0; proc->types.pointer.drag_throw_vect.y = 0;
lv_coord_t sl = lv_obj_get_scroll_left(target_obj);
lv_coord_t sr = lv_obj_get_scroll_right(target_obj);
/*If scrolled inside reduce faster*/
if(sl < 0 || sr < 0) proc->types.pointer.drag_throw_vect.x = proc->types.pointer.drag_throw_vect.x >> 1;
break; break;
}
case LV_DRAG_DIR_VER: case LV_DRAG_DIR_VER:
{ {
proc->types.pointer.drag_throw_vect.x = 0; proc->types.pointer.drag_throw_vect.x = 0;
@ -1438,21 +1461,9 @@ static void indev_drag_throw(lv_indev_proc_t * proc)
} }
} }
if((proc->types.pointer.drag_throw_vect.x != 0 || proc->types.pointer.drag_throw_vect.y != 0)) { if((proc->types.pointer.drag_throw_vect.x != 0 || proc->types.pointer.drag_throw_vect.y != 0)) {
/*Get the coordinates and modify them*/ /*Get the coordinates and modify them*/
if(scrollable) { if(scrollable) {
// if(target_obj->scroll.y + proc->types.pointer.drag_throw_vect.y > 0) {
// proc->types.pointer.drag_throw_vect.y = 0;
// lv_obj_scroll_to_y(target_obj, 0, LV_ANIM_OFF);
// }
//
// if(child_box.y2 + proc->types.pointer.drag_throw_vect.y < target_obj->coords.y2) {
// proc->types.pointer.drag_throw_vect.y = 0;
// lv_obj_scroll_by(target_obj, 0, -(child_box.y2 - target_obj->coords.y2), LV_ANIM_OFF);
// }
lv_obj_scroll_by(target_obj, proc->types.pointer.drag_throw_vect.x, proc->types.pointer.drag_throw_vect.y, LV_ANIM_OFF); lv_obj_scroll_by(target_obj, proc->types.pointer.drag_throw_vect.x, proc->types.pointer.drag_throw_vect.y, LV_ANIM_OFF);
} else { } else {
lv_area_t coords_ori; lv_area_t coords_ori;

View File

@ -104,7 +104,8 @@ static void refresh_event_task_cb(lv_task_t * t);
static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find); static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_find);
static void lv_obj_del_async_cb(void * obj); static void lv_obj_del_async_cb(void * obj);
static void obj_del_core(lv_obj_t * obj); static void obj_del_core(lv_obj_t * obj);
static lv_res_t get_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv); static lv_res_t get_ver_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv);
static lv_res_t get_hor_scrollbar_area(lv_obj_t * obj, lv_area_t * sbh);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
@ -1099,31 +1100,28 @@ void lv_obj_scroll_by(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable
lv_anim_init(&a); lv_anim_init(&a);
lv_anim_set_var(&a, obj); lv_anim_set_var(&a, obj);
lv_anim_path_t path;
lv_anim_path_init(&path);
lv_anim_path_set_cb(&path, lv_anim_path_ease_out);
if(x) { if(x) {
lv_anim_set_time(&a, lv_anim_speed_to_time(lv_disp_get_hor_res(d), 0, y)); lv_anim_set_time(&a, lv_anim_speed_to_time(lv_disp_get_hor_res(d), 0, x));
lv_anim_set_values(&a, obj->scroll.x, obj->scroll.x + x); lv_anim_set_values(&a, obj->scroll.x, obj->scroll.x + x);
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) scroll_anim_x_cb); lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) scroll_anim_x_cb);
lv_anim_set_path(&a, &path);
lv_anim_start(&a); lv_anim_start(&a);
} }
if(y) { if(y) {
lv_anim_path_t path;
lv_anim_path_init(&path);
lv_anim_path_set_cb(&path, lv_anim_path_ease_out);
lv_anim_set_time(&a, lv_anim_speed_to_time((lv_disp_get_ver_res(d) * 3) >> 2, 0, y)); lv_anim_set_time(&a, lv_anim_speed_to_time((lv_disp_get_ver_res(d) * 3) >> 2, 0, y));
lv_anim_set_values(&a, obj->scroll.y, obj->scroll.y + y); lv_anim_set_values(&a, obj->scroll.y, obj->scroll.y + y);
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) scroll_anim_y_cb); lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) scroll_anim_y_cb);
lv_anim_set_path(&a, &path); lv_anim_set_path(&a, &path);
lv_anim_start(&a); lv_anim_start(&a);
} }
} else { } else {
lv_obj_scroll_by_raw(obj, x, y); lv_obj_scroll_by_raw(obj, x, y);
} }
} }
/** /**
@ -1144,7 +1142,7 @@ void lv_obj_scroll_to(lv_obj_t * obj, lv_coord_t x, lv_coord_t y, lv_anim_enable
*/ */
void lv_obj_scroll_to_x(lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en) void lv_obj_scroll_to_x(lv_obj_t * obj, lv_coord_t x, lv_anim_enable_t anim_en)
{ {
// refresh_children_position(obj, x, y); lv_obj_scroll_by(obj, x - obj->scroll.x, 0, anim_en);
} }
/** /**
@ -1194,6 +1192,42 @@ lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj)
return y2 - obj->coords.y2; return y2 - obj->coords.y2;
} }
/**
* Return the weight of the area on the left the parent.
* That is the number of pixels the object can be scrolled down.
* Normally positive but can be negative when scrolled inside.
* @param obj
* @return
*/
lv_coord_t lv_obj_get_scroll_left(lv_obj_t * obj)
{
return -obj->scroll.x;
}
/**
* Return the width of the area below the object.
* That is the number of pixels the object can be scrolled left.
* Normally positive but can be negative when scrolled inside.
* @param obj
* @return
*/
lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, LV_OBJX_NAME);
lv_coord_t x2 = LV_COORD_MIN;
lv_obj_t * child = lv_obj_get_child(obj, NULL);
if(child == NULL) return 0;
while(child) {
x2 = LV_MATH_MAX(x2, child->coords.x2 + lv_obj_get_style_margin_right(child, LV_OBJ_PART_MAIN));
child = lv_obj_get_child(obj, child);
}
return x2 - obj->coords.x2;
}
/** /**
* Set the size of an extended clickable area * Set the size of an extended clickable area
* If TINY mode is used, only the largest of the horizontal and vertical padding * If TINY mode is used, only the largest of the horizontal and vertical padding
@ -3851,12 +3885,19 @@ static lv_design_res_t lv_obj_design(lv_obj_t * obj, const lv_area_t * clip_area
if(lv_obj_get_screen(obj) == lv_scr_act()) { if(lv_obj_get_screen(obj) == lv_scr_act()) {
lv_area_t sb; lv_area_t sb;
if(get_scrollbar_area(obj, &sb)) { if(get_ver_scrollbar_area(obj, &sb)) {
lv_draw_rect_dsc_t sb_rect_dsc; lv_draw_rect_dsc_t sb_rect_dsc;
lv_draw_rect_dsc_init(&sb_rect_dsc); lv_draw_rect_dsc_init(&sb_rect_dsc);
sb_rect_dsc.bg_color = LV_COLOR_RED; sb_rect_dsc.bg_color = LV_COLOR_RED;
lv_draw_rect(&sb, clip_area, &sb_rect_dsc); lv_draw_rect(&sb, clip_area, &sb_rect_dsc);
} }
if(get_hor_scrollbar_area(obj, &sb)) {
lv_draw_rect_dsc_t sb_rect_dsc;
lv_draw_rect_dsc_init(&sb_rect_dsc);
sb_rect_dsc.bg_color = LV_COLOR_BLUE;
lv_draw_rect(&sb, clip_area, &sb_rect_dsc);
}
} }
} }
else if(mode == LV_DESIGN_DRAW_POST) { else if(mode == LV_DESIGN_DRAW_POST) {
@ -3934,13 +3975,30 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param)
} }
else if(sign == LV_SIGNAL_SCROLL_END) { else if(sign == LV_SIGNAL_SCROLL_END) {
lv_area_t child_box; // lv_area_t child_box;
lv_obj_get_children_box(obj, &child_box); // lv_obj_get_children_box(obj, &child_box);
if(obj->scroll.y > 0) {
lv_obj_scroll_to_y(obj, 0, LV_ANIM_ON); lv_coord_t st = lv_obj_get_scroll_top(obj);
lv_coord_t sb = lv_obj_get_scroll_bottom(obj);
lv_coord_t sl = lv_obj_get_scroll_left(obj);
lv_coord_t sr = lv_obj_get_scroll_right(obj);
/*Revert if scrolled in*/
if(st > 0 || sb > 0) { /*Is vertically scrollable*/
if(st < 0) {
lv_obj_scroll_by(obj, 0, st, LV_ANIM_ON);
}
else if(sb < 0) {
lv_obj_scroll_by(obj, 0, -sb, LV_ANIM_ON);
}
}
if(sl > 0 || sr > 0) { /*Is horizontally scrollable*/
if(sl < 0) {
lv_obj_scroll_by(obj, sl, 0, LV_ANIM_ON);
}
else if(sr < 0) {
lv_obj_scroll_by(obj, -sr, 0, LV_ANIM_ON);
} }
else if(child_box.y2 < obj->coords.y2) {
lv_obj_scroll_by(obj, 0, -(child_box.y2 - obj->coords.y2), LV_ANIM_ON);
} }
} }
else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) {
@ -4486,6 +4544,7 @@ static void fade_in_anim_ready(lv_anim_t * a)
static void scroll_anim_x_cb(lv_obj_t * obj, lv_anim_value_t v) static void scroll_anim_x_cb(lv_obj_t * obj, lv_anim_value_t v)
{ {
lv_obj_scroll_by_raw(obj, v - obj->scroll.x, 0);
} }
static void scroll_anim_y_cb(lv_obj_t * obj, lv_anim_value_t v) static void scroll_anim_y_cb(lv_obj_t * obj, lv_anim_value_t v)
@ -4524,7 +4583,7 @@ static bool obj_valid_child(const lv_obj_t * parent, const lv_obj_t * obj_to_fin
return false; return false;
} }
static lv_res_t get_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv) static lv_res_t get_ver_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv)
{ {
lv_coord_t obj_h = lv_obj_get_height(obj); lv_coord_t obj_h = lv_obj_get_height(obj);
@ -4537,9 +4596,6 @@ static lv_res_t get_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv)
return LV_RES_INV; return LV_RES_INV;
} }
lv_coord_t sb_h = (obj_h * obj_h) / content_h; lv_coord_t sb_h = (obj_h * obj_h) / content_h;
if(sb_h != 150) {
volatile int x = 0;
}
lv_coord_t rem = obj_h - sb_h; /*Remaining size from the scrollbar track that is not the scrollbar itself*/ lv_coord_t rem = obj_h - sb_h; /*Remaining size from the scrollbar track that is not the scrollbar itself*/
lv_coord_t scroll_h = content_h - obj_h; /*The size of the content which can be really scrolled*/ lv_coord_t scroll_h = content_h - obj_h; /*The size of the content which can be really scrolled*/
if(scroll_h <= 0) { if(scroll_h <= 0) {
@ -4561,4 +4617,37 @@ static lv_res_t get_scrollbar_area(lv_obj_t * obj, lv_area_t * sbv)
return LV_RES_OK; return LV_RES_OK;
} }
static lv_res_t get_hor_scrollbar_area(lv_obj_t * obj, lv_area_t * sbh)
{
lv_coord_t obj_w = lv_obj_get_width(obj);
lv_area_t child_box;
lv_res_t res = lv_obj_get_children_box(obj, &child_box);
if(res != LV_RES_OK) return res;
lv_coord_t content_w = (child_box.x2 - obj->scroll.x) - obj->coords.x1 ;
if(content_w < obj_w) {
return LV_RES_INV;
}
lv_coord_t sb_h = (obj_w * obj_w) / content_w;
lv_coord_t rem = obj_w - sb_h; /*Remaining size from the scrollbar track that is not the scrollbar itself*/
lv_coord_t scroll_w = content_w - obj_w; /*The size of the content which can be really scrolled*/
if(scroll_w <= 0) {
sbh->y2 = obj->coords.y2;
sbh->y1 = sbh->y2 - 10;
sbh->x2 = obj->coords.x2;
sbh->x1 = obj->coords.x1;
return LV_RES_OK;
}
lv_coord_t sb_x = (rem * (child_box.x2 - obj->coords.x2)) / scroll_w;
sb_x = rem - sb_x;
sbh->x1 = obj->coords.x1 + sb_x;
sbh->x2 = sbh->x1 + sb_h;
sbh->y2 = obj->coords.y2;
sbh->y1 = sbh->y2 - 10;
return LV_RES_OK;
}

View File

@ -594,6 +594,24 @@ lv_coord_t lv_obj_get_scroll_top(lv_obj_t * obj);
lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj); lv_coord_t lv_obj_get_scroll_bottom(lv_obj_t * obj);
/**
* Return the weight of the area on the left the parent.
* That is the number of pixels the object can be scrolled down.
* Normally positive but can be negative when scrolled inside.
* @param obj
* @return
*/
lv_coord_t lv_obj_get_scroll_left(lv_obj_t * obj);
/**
* Return the width of the area below the object.
* That is the number of pixels the object can be scrolled left.
* Normally positive but can be negative when scrolled inside.
* @param obj
* @return
*/
lv_coord_t lv_obj_get_scroll_right(lv_obj_t * obj);
/** /**
* Set the size of an extended clickable area * Set the size of an extended clickable area
* @param obj pointer to an object * @param obj pointer to an object