mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-21 06:53:01 +08:00
add scroll direction enable/disable support
This commit is contained in:
parent
9f2526a73c
commit
6e08d402c1
@ -1256,13 +1256,12 @@ static lv_coord_t find_snap_point_y(const lv_obj_t * obj, lv_coord_t min, lv_coo
|
|||||||
child = lv_obj_get_child_back(obj, child);
|
child = lv_obj_get_child_back(obj, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("child cnt: %d\n", cc);
|
|
||||||
|
|
||||||
return dist == LV_COORD_MAX ? 0 : -dist;
|
return dist == LV_COORD_MAX ? 0 : -dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scroll_limit(lv_indev_proc_t * proc, lv_coord_t * diff_x, lv_coord_t * diff_y)
|
static void scroll_limit(lv_indev_proc_t * proc, lv_coord_t * diff_x, lv_coord_t * diff_y)
|
||||||
{
|
{
|
||||||
|
lv_obj_t * obj = proc->types.pointer.scroll_obj;
|
||||||
if(diff_y) {
|
if(diff_y) {
|
||||||
if(proc->types.pointer.scroll_sum.y + *diff_y < proc->types.pointer.scroll_area.y1) {
|
if(proc->types.pointer.scroll_sum.y + *diff_y < proc->types.pointer.scroll_area.y1) {
|
||||||
*diff_y = proc->types.pointer.scroll_area.y1 - proc->types.pointer.scroll_sum.y;
|
*diff_y = proc->types.pointer.scroll_area.y1 - proc->types.pointer.scroll_sum.y;
|
||||||
@ -1301,8 +1300,16 @@ static void indev_scroll_handler(lv_indev_proc_t * proc)
|
|||||||
|
|
||||||
proc->types.pointer.scroll_obj = proc->types.pointer.act_obj;
|
proc->types.pointer.scroll_obj = proc->types.pointer.act_obj;
|
||||||
|
|
||||||
/*Go until find an scrollable object in the current direction*/
|
/* Go until find an scrollable object in the current direction
|
||||||
|
* More precisely:
|
||||||
|
* 1. Check the pressed object and all of its ancestors and try to find an object which is scrollable
|
||||||
|
* 2. Scrollable means it has some content out of it's area
|
||||||
|
* 3. If an object can be scrolled into the current direction then use it ("real match"")
|
||||||
|
* 4. If can be scrolled on the current axis (hor/ver) save it as candidate (at least show an elastic scroll effect)
|
||||||
|
* 5. Use the last candidate. Always the "deepest" parent or the object from point 3 */
|
||||||
while(proc->types.pointer.scroll_obj) {
|
while(proc->types.pointer.scroll_obj) {
|
||||||
|
|
||||||
|
/*Decide if it's a horizontal or vertical scroll*/
|
||||||
bool hor_en = false;
|
bool hor_en = false;
|
||||||
bool ver_en = false;
|
bool ver_en = false;
|
||||||
if(LV_MATH_ABS(proc->types.pointer.scroll_sum.x) > LV_MATH_ABS(proc->types.pointer.scroll_sum.y)) {
|
if(LV_MATH_ABS(proc->types.pointer.scroll_sum.x) > LV_MATH_ABS(proc->types.pointer.scroll_sum.y)) {
|
||||||
@ -1312,20 +1319,30 @@ static void indev_scroll_handler(lv_indev_proc_t * proc)
|
|||||||
ver_en = true;
|
ver_en = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*Consider both up-down or left/right scrollable according to the current direction*/
|
||||||
bool up_en = ver_en;
|
bool up_en = ver_en;
|
||||||
bool down_en = ver_en;
|
bool down_en = ver_en;
|
||||||
bool left_en = hor_en;
|
bool left_en = hor_en;
|
||||||
bool right_en = hor_en;
|
bool right_en = hor_en;
|
||||||
|
|
||||||
|
/*The object might have disabled some directions.*/
|
||||||
|
lv_dir_t scroll_dir = proc->types.pointer.scroll_obj->scroll_dir;
|
||||||
|
if((scroll_dir & LV_DIR_LEFT) == 0) left_en = false;
|
||||||
|
if((scroll_dir & LV_DIR_RIGHT) == 0) right_en = false;
|
||||||
|
if((scroll_dir & LV_DIR_TOP) == 0) up_en = false;
|
||||||
|
if((scroll_dir & LV_DIR_BOTTOM) == 0) down_en = false;
|
||||||
|
|
||||||
|
/*The object is scrollable to a direction if its content overflow in that direction. */
|
||||||
lv_coord_t st = lv_obj_get_scroll_top(proc->types.pointer.scroll_obj);
|
lv_coord_t st = lv_obj_get_scroll_top(proc->types.pointer.scroll_obj);
|
||||||
lv_coord_t sb = lv_obj_get_scroll_bottom(proc->types.pointer.scroll_obj);
|
lv_coord_t sb = lv_obj_get_scroll_bottom(proc->types.pointer.scroll_obj);
|
||||||
lv_coord_t sl = lv_obj_get_scroll_left(proc->types.pointer.scroll_obj);
|
lv_coord_t sl = lv_obj_get_scroll_left(proc->types.pointer.scroll_obj);
|
||||||
lv_coord_t sr = lv_obj_get_scroll_right(proc->types.pointer.scroll_obj);
|
lv_coord_t sr = lv_obj_get_scroll_right(proc->types.pointer.scroll_obj);
|
||||||
|
|
||||||
bool ver_scrollable = st > 0 || sb > 0 ? true : false;
|
/* If this object is scrollable into the current scroll direction then save it as a candidate.
|
||||||
bool hor_scrollable = sl > 0 || sr > 0 ? true : false;
|
* It's important only to be scrollable on the current axis (hor/ver) because if the scroll
|
||||||
|
* is propagated to this object it can show at least elastic scroll effect.
|
||||||
if(ver_scrollable &&
|
* But if not hor/ver scrollable do not scroll it at all (so it's not a good candidate) */
|
||||||
|
if((st > 0 || sb > 0) &&
|
||||||
((up_en && proc->types.pointer.scroll_sum.y >= indev_act->driver.scroll_limit) ||
|
((up_en && proc->types.pointer.scroll_sum.y >= indev_act->driver.scroll_limit) ||
|
||||||
(down_en && proc->types.pointer.scroll_sum.y <= - indev_act->driver.scroll_limit)))
|
(down_en && proc->types.pointer.scroll_sum.y <= - indev_act->driver.scroll_limit)))
|
||||||
{
|
{
|
||||||
@ -1333,7 +1350,7 @@ static void indev_scroll_handler(lv_indev_proc_t * proc)
|
|||||||
dirs_candidate = LV_SCROLL_DIR_VER;
|
dirs_candidate = LV_SCROLL_DIR_VER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hor_scrollable &&
|
if((sl > 0 || sr > 0) &&
|
||||||
((left_en && proc->types.pointer.scroll_sum.x >= indev_act->driver.scroll_limit) ||
|
((left_en && proc->types.pointer.scroll_sum.x >= indev_act->driver.scroll_limit) ||
|
||||||
(right_en && proc->types.pointer.scroll_sum.x <= - indev_act->driver.scroll_limit)))
|
(right_en && proc->types.pointer.scroll_sum.x <= - indev_act->driver.scroll_limit)))
|
||||||
{
|
{
|
||||||
@ -1341,19 +1358,23 @@ static void indev_scroll_handler(lv_indev_proc_t * proc)
|
|||||||
dirs_candidate = LV_SCROLL_DIR_HOR;
|
dirs_candidate = LV_SCROLL_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(sl <= 0) left_en = false;
|
||||||
if(sr <= 0) right_en = false;
|
if(sr <= 0) right_en = false;
|
||||||
|
|
||||||
|
/*If the object really can be scrolled into the current direction the use it. */
|
||||||
if((left_en && proc->types.pointer.scroll_sum.x >= indev_act->driver.scroll_limit) ||
|
if((left_en && proc->types.pointer.scroll_sum.x >= indev_act->driver.scroll_limit) ||
|
||||||
(right_en && proc->types.pointer.scroll_sum.x <= - indev_act->driver.scroll_limit) ||
|
(right_en && proc->types.pointer.scroll_sum.x <= - indev_act->driver.scroll_limit) ||
|
||||||
(up_en && proc->types.pointer.scroll_sum.y >= indev_act->driver.scroll_limit) ||
|
(up_en && proc->types.pointer.scroll_sum.y >= indev_act->driver.scroll_limit) ||
|
||||||
(down_en && proc->types.pointer.scroll_sum.y <= - indev_act->driver.scroll_limit))
|
(down_en && proc->types.pointer.scroll_sum.y <= - indev_act->driver.scroll_limit))
|
||||||
{
|
{
|
||||||
proc->types.pointer.scroll_dir = hor_en ? LV_SCROLL_DIR_HOR : LV_SCROLL_DIR_VER;
|
proc->types.pointer.scroll_dir = hor_en ? LV_SCROLL_DIR_HOR : LV_SCROLL_DIR_VER;
|
||||||
break; /*It's good scrollable object, use it*/
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*Try the parent */
|
||||||
proc->types.pointer.scroll_obj = lv_obj_get_parent(proc->types.pointer.scroll_obj);
|
proc->types.pointer.scroll_obj = lv_obj_get_parent(proc->types.pointer.scroll_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1381,7 +1402,6 @@ static void indev_scroll_handler(lv_indev_proc_t * proc)
|
|||||||
case LV_SCROLL_SNAP_ALIGN_START:
|
case LV_SCROLL_SNAP_ALIGN_START:
|
||||||
proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y1 + 1, LV_COORD_MAX, 0);
|
proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y1 + 1, LV_COORD_MAX, 0);
|
||||||
proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y1 - 1, 0);
|
proc->types.pointer.scroll_area.y2 = find_snap_point_y(obj, LV_COORD_MIN, obj->coords.y1 - 1, 0);
|
||||||
printf("%d, %d\n", proc->types.pointer.scroll_area.y1, proc->types.pointer.scroll_area.y2);
|
|
||||||
break;
|
break;
|
||||||
case LV_SCROLL_SNAP_ALIGN_END:
|
case LV_SCROLL_SNAP_ALIGN_END:
|
||||||
proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y2, LV_COORD_MAX, 0);
|
proc->types.pointer.scroll_area.y1 = find_snap_point_y(obj, obj->coords.y2, LV_COORD_MAX, 0);
|
||||||
@ -1441,6 +1461,12 @@ static void indev_scroll_handler(lv_indev_proc_t * proc)
|
|||||||
if(lv_obj_get_scroll_bottom(scroll_obj) < 0) diff_y = diff_y / 2;
|
if(lv_obj_get_scroll_bottom(scroll_obj) < 0) diff_y = diff_y / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if((scroll_obj->scroll_dir & LV_DIR_LEFT) == 0 && diff_x > 0) diff_x = 0;
|
||||||
|
if((scroll_obj->scroll_dir & LV_DIR_RIGHT) == 0 && diff_x < 0) diff_x = 0;
|
||||||
|
if((scroll_obj->scroll_dir & LV_DIR_TOP) == 0 && diff_y > 0) diff_y = 0;
|
||||||
|
if((scroll_obj->scroll_dir & LV_DIR_BOTTOM) == 0 && diff_y < 0) diff_y = 0;
|
||||||
|
|
||||||
/*Respect the scroll limit area*/
|
/*Respect the scroll limit area*/
|
||||||
scroll_limit(proc, &diff_x, &diff_y);
|
scroll_limit(proc, &diff_x, &diff_y);
|
||||||
|
|
||||||
|
@ -330,6 +330,7 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy)
|
|||||||
/*Set attributes*/
|
/*Set attributes*/
|
||||||
new_obj->adv_hittest = 0;
|
new_obj->adv_hittest = 0;
|
||||||
new_obj->scroll_mode = LV_SCROLL_MODE_AUTO;
|
new_obj->scroll_mode = LV_SCROLL_MODE_AUTO;
|
||||||
|
new_obj->scroll_dir = LV_DIR_ALL;
|
||||||
new_obj->flags = LV_OBJ_FLAG_CLICKABLE;
|
new_obj->flags = LV_OBJ_FLAG_CLICKABLE;
|
||||||
if(parent) new_obj->flags |= LV_OBJ_FLAG_GESTURE_BUBBLE;
|
if(parent) new_obj->flags |= LV_OBJ_FLAG_GESTURE_BUBBLE;
|
||||||
new_obj->state = LV_STATE_DEFAULT;
|
new_obj->state = LV_STATE_DEFAULT;
|
||||||
|
@ -171,6 +171,19 @@ enum {
|
|||||||
|
|
||||||
typedef uint8_t lv_state_t;
|
typedef uint8_t lv_state_t;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LV_DIR_NONE = 0x00,
|
||||||
|
LV_DIR_LEFT = (1 << 0),
|
||||||
|
LV_DIR_RIGHT = (1 << 1),
|
||||||
|
LV_DIR_TOP = (1 << 2),
|
||||||
|
LV_DIR_BOTTOM = (1 << 3),
|
||||||
|
LV_DIR_HOR = LV_DIR_LEFT | LV_DIR_RIGHT,
|
||||||
|
LV_DIR_VER = LV_DIR_TOP | LV_DIR_BOTTOM,
|
||||||
|
LV_DIR_ALL = LV_DIR_HOR | LV_DIR_VER,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef uint8_t lv_dir_t;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
LV_SCROLL_SNAP_ALIGN_NONE,
|
LV_SCROLL_SNAP_ALIGN_NONE,
|
||||||
LV_SCROLL_SNAP_ALIGN_START,
|
LV_SCROLL_SNAP_ALIGN_START,
|
||||||
@ -231,6 +244,7 @@ typedef struct _lv_obj_t {
|
|||||||
lv_scroll_mode_t scroll_mode :2; /**< How to display scrollbars*/
|
lv_scroll_mode_t scroll_mode :2; /**< How to display scrollbars*/
|
||||||
lv_scroll_snap_align_t snap_align_x : 2;
|
lv_scroll_snap_align_t snap_align_x : 2;
|
||||||
lv_scroll_snap_align_t snap_align_y : 2;
|
lv_scroll_snap_align_t snap_align_y : 2;
|
||||||
|
lv_scroll_dir_t scroll_dir :4;
|
||||||
lv_bidi_dir_t base_dir : 2; /**< Base direction of texts related to this object */
|
lv_bidi_dir_t base_dir : 2; /**< Base direction of texts related to this object */
|
||||||
uint8_t adv_hittest : 1; /**< 1: Use advanced hit-testing (slower) */
|
uint8_t adv_hittest : 1; /**< 1: Use advanced hit-testing (slower) */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user