Scrolling cannot be propagated to the parent object

Important: unclear posts may not receive useful answers.

Before posting

  • Get familiar with Markdown to format and structure your post
  • Be sure to update lvgl from the latest version from the master branch.
  • Be sure you have checked the FAQ and read the relevant part of the documentation.
  • If applicable use the Simulator to eliminate hardware related issues.

Delete this section if you read and applied the mentioned points.

Description

What MCU/Processor/Board and compiler are you using?

BES2700BP

What LVGL version are you using?

v8.3

What do you want to achieve?

Scroll propagation in multi-layer Flex layouts to parent objects.

What have you tried so far?

Analyze the implementation of the lv_indev_find_scroll_obj function.

Code to reproduce

Add a code snippet which can run in the simulator. It should contain only the relevant code that compiles without errors when separated from your main code base.

The code block(s) should be formatted like:

lv_obj_t * lv_indev_find_scroll_obj(lv_indev_t * indev)
{
    ...
    /*Vertical scroll*/
        snap_cnt = 0;
        int32_t st = 0;
        int32_t sb = 0;
        lv_scroll_snap_t snap_y = lv_obj_get_scroll_snap_y(obj_act);
        if(snap_y != LV_SCROLL_SNAP_NONE) {
            uint32_t child_cnt = lv_obj_get_child_count(obj_act);
            uint32_t i;
            for(i = 0; i < child_cnt; i++) {
                if(lv_obj_has_flag(lv_obj_get_child(obj_act, i), LV_OBJ_FLAG_SNAPPABLE)) {
                    snap_cnt++;
                    if(snap_cnt == 2) {
                        st = 1; /*Assume scrolling*/
                        sb = 1;
                        break;
                    }
                }
            }
        }
        if(snap_y == LV_SCROLL_SNAP_NONE || snap_cnt < 2) {
            st = lv_obj_get_scroll_top(obj_act);
            sb = lv_obj_get_scroll_bottom(obj_act);
        }


        /*If this object is scrollable into the current scroll direction then save it as a candidate.
         *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.
         *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    && obj_scroll_sum.y >=   scroll_limit) ||
            (down_en  && obj_scroll_sum.y <= - scroll_limit))) {
            obj_candidate = obj_act;
            dir_candidate = LV_DIR_VER;
        }

        ...

        if(st <= 0) up_en = false;
        if(sb <= 0) down_en = false;
        if(sl <= 0) left_en = false;
        if(sr <= 0) right_en = false;

        ...

        /*Try the parent*/
        obj_act = lv_obj_get_parent(obj_act);
    ...
}

Screenshot and/or video

If possible, add screenshots and/or videos about the current state.

In a multi-layer Flex layout, checking whether specific child objects use the LV_OBJ_FLAG_SNAPPABLE flag, could this condition potentially prevent the scroll chain from ever being passed to the parent object?

for(i = 0; i < child_cnt; i++) {
    if(lv_obj_has_flag(lv_obj_get_child(obj_act, i), LV_OBJ_FLAG_SNAPPABLE)) {
        snap_cnt++;
        if(snap_cnt == 2) {
            st = 1; /*Assume scrolling*/
            sb = 1;
            break;
        }
    }
}

The values of st and sb will always be 1, and will not become negative, even when scrolling beyond the top or bottom with a bounce feature.Please help confirm, thank you.

Refer the commit fix(indev): fix elastic scrolling with snapping (#6230) · lvgl/lvgl@63edb43 · GitHub

Hi,

Please send a code snippet to reproduce the issue.

Hi, @kisvegabor

The code of v8.3 is as follows:

#define LV_HOR_RES_MAX 466
#define LV_VER_RES_MAX 466

void CreateControlMenu(lv_obj_t *parent)
{
    auto m_menu_container = lv_obj_create(parent);

    lv_obj_remove_style_all(m_menu_container);
    lv_obj_set_size(m_menu_container, LV_HOR_RES_MAX, 466 / 2 + 102 / 2);
    lv_obj_set_scroll_snap_y(m_menu_container, LV_SCROLL_SNAP_START);
    lv_obj_set_flex_flow(m_menu_container, LV_FLEX_FLOW_COLUMN);
    lv_obj_align(m_menu_container, LV_ALIGN_TOP_MID, 0, 12);
    lv_obj_set_style_bg_opa(m_menu_container, LV_OPA_0, LV_PART_MAIN);
    lv_obj_set_scroll_dir(m_menu_container, LV_DIR_VER);
    lv_obj_align(m_menu_container, LV_ALIGN_TOP_MID, 0, 450);

    for (int8_t i = 0; i < 10; ++i)
    {
        lv_obj_t *obj;
        lv_obj_t *label;

        /*Add items to the column*/
        obj = lv_btn_create(m_menu_container);
        lv_obj_set_size(obj, LV_PCT(100), 100);

        label = lv_label_create(obj);
        lv_label_set_text_fmt(label, "Item: %" LV_PRIu32, i);
        lv_obj_center(label);
    }
}

void CreateControlView(lv_obj_t *parent)
{
    auto m_control_container = lv_obj_create(parent);
    lv_obj_set_size(m_control_container, LV_HOR_RES_MAX, LV_VER_RES_MAX);
    lv_obj_align(m_control_container, LV_ALIGN_TOP_MID, 0, 0);
    lv_obj_set_style_bg_opa(m_control_container, 0, 0);
    lv_obj_set_style_bg_opa(m_control_container, LV_OPA_0, LV_PART_SCROLLBAR | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(m_control_container, LV_OPA_0, LV_PART_SCROLLBAR | LV_STATE_SCROLLED);
    lv_obj_clear_flag(m_control_container, LV_OBJ_FLAG_SCROLL_MOMENTUM);
    lv_obj_clear_flag(m_control_container, LV_OBJ_FLAG_SCROLL_ELASTIC);

    auto place_holder = lv_obj_create(m_control_container);
    lv_obj_set_size(place_holder, LV_HOR_RES_MAX, 438);
    lv_obj_set_style_bg_opa(place_holder, 30, 0);
    lv_obj_set_style_bg_color(place_holder, lv_color_hex(0x3FF07F), 0);
    lv_obj_align(place_holder, LV_ALIGN_TOP_MID, 0, 0);
    lv_obj_set_y(place_holder, 0);
    lv_obj_clear_flag(place_holder, LV_OBJ_FLAG_CLICKABLE);


    CreateControlMenu(m_control_container);
    lv_obj_scroll_to_y(m_control_container, 0, LV_ANIM_OFF);
}

The code of v9.2 is as follows:

#define LV_HOR_RES_MAX 466
#define LV_VER_RES_MAX 466

void CreateControlMenu(lv_obj_t *parent)
{
    auto m_menu_container = lv_obj_create(parent);

    lv_obj_remove_style_all(m_menu_container);
    lv_obj_set_size(m_menu_container, LV_HOR_RES_MAX, 466 / 2 + 102 / 2);
    lv_obj_set_scroll_snap_y(m_menu_container, LV_SCROLL_SNAP_START);
    lv_obj_set_flex_flow(m_menu_container, LV_FLEX_FLOW_COLUMN);
    lv_obj_align(m_menu_container, LV_ALIGN_TOP_MID, 0, 12);
    lv_obj_set_style_bg_opa(m_menu_container, LV_OPA_0, LV_PART_MAIN);
    lv_obj_set_style_rotary_sensitivity(m_menu_container, 64, 0);
    lv_obj_set_scroll_dir(m_menu_container, LV_DIR_VER);
    lv_obj_align(m_menu_container, LV_ALIGN_TOP_MID, 0, 450);

    for (int8_t i = 0; i < 10; ++i)
    {
        lv_obj_t *obj;
        lv_obj_t *label;

        /*Add items to the column*/
        obj = lv_button_create(m_menu_container);
        lv_obj_set_size(obj, LV_PCT(100), 100);

        label = lv_label_create(obj);
        lv_label_set_text_fmt(label, "Item: %" LV_PRIu32, i);
        lv_obj_center(label);
    }
}

void CreateControlView(lv_obj_t *parent)
{
    auto m_control_container = lv_obj_create(parent);
    lv_obj_set_size(m_control_container, LV_HOR_RES_MAX, LV_VER_RES_MAX);
    lv_obj_align(m_control_container, LV_ALIGN_TOP_MID, 0, 0);
    lv_obj_set_style_bg_opa(m_control_container, 0, 0);
    lv_obj_set_style_bg_opa(m_control_container, LV_OPA_0, LV_PART_SCROLLBAR | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(m_control_container, LV_OPA_0, LV_PART_SCROLLBAR | LV_STATE_SCROLLED);
    lv_obj_clear_flag(m_control_container, LV_OBJ_FLAG_SCROLL_MOMENTUM);
    lv_obj_clear_flag(m_control_container, LV_OBJ_FLAG_SCROLL_ELASTIC);


    auto place_holder = lv_obj_create(m_control_container);
    lv_obj_set_size(place_holder, LV_HOR_RES_MAX, 438);
    lv_obj_set_style_bg_opa(place_holder, 30, 0);
    lv_obj_set_style_bg_color(place_holder, lv_color_hex(0x3FF07F), 0);
    lv_obj_align(place_holder, LV_ALIGN_TOP_MID, 0, 0);
    lv_obj_set_y(place_holder, 0);
    lv_obj_clear_flag(place_holder, LV_OBJ_FLAG_CLICKABLE);

    CreateControlMenu(m_control_container);
    lv_obj_scroll_to_y(m_control_container, 0, LV_ANIM_OFF);
}

Comparison Test:

  1. In the release/v8.3 demo test, the last two items at the end cannot be scrolled up and are stuck.
  2. Testing the release/v9.2 demo, the top-level ITEMS can be scrolled, but when scrolled to the top and then scrolled down further, the scrolling cannot be passed to the next layer.

I’m sorry that I kept you waiting so long. I just had time to take a deeper look today and sent a PR as well:

Please test it and let me know how it works.

HI kisvegabor,
I have tested it, and the current performance is correct, the Flex switch is quite accurate, thank you very much.

Awesome, thank you for the feedback! :slight_smile: