lvgl / lvgl

Embedded graphics library to create beautiful UIs for any MCU, MPU and display type.
https://lvgl.io
MIT License
16.51k stars 3.24k forks source link

Setting object position in a page doesn't take y offset of scrollable into account #181

Closed upbeat27 closed 6 years ago

upbeat27 commented 6 years ago

If you have a page that is scrollable, getting/setting an object's location within the page doesn't take into account the scrollable aspect.

If you have a page that is scrolled down a bit, then:

You end up with an object that is not at the same Y position as object you obtained the position from. The Y position of the get is relative to the top of the screen. The Y position of the set is relative to the top of the scrollable.

To correctly position an object within the page, you need to get the position of of the page's scrollable (lv_obj_get_coords(lv_page_get_scrl(page), &a)) and subtract that Y from the position of the object you are trying to position this new object at.

This seems like it might be a complicated problem to solve. At the very least maybe there should be a function for getting the position of an object in a page that includes the Y offset of the scrollable, so that these coords can be used to directly set an object's position within a page.

kisvegabor commented 6 years ago

Both the get/set functions refer to the scrollable. I think you were tricked by the autofit attribute of the scrollable.

    lv_obj_t * page = lv_page_create(lv_scr_act(), NULL);
    lv_obj_set_pos(page, 50, 50);
    lv_obj_set_size(page, 150, 200);

    lv_obj_t * o1 = lv_obj_create(page, NULL);
    lv_obj_set_size(o1, 10,10);
    lv_obj_set_pos(o1, 20, 30);

    lv_obj_t * o2 = lv_obj_create(page, NULL);
    lv_obj_set_size(o2, 10,10);
    lv_obj_set_pos(o2, 50, lv_obj_get_y(o1) + 10);

image

So it seems the set_y coordinate is not taken into account. But is because the scrollabel set's it's size to the only children and because a small scrollable can't be in the middle the the background it's moved back to the top.

With disabling the autofit of the scrollbale it works as as "expected"


    lv_obj_t * page = lv_page_create(lv_scr_act(), NULL);
    lv_obj_set_pos(page, 50, 50);
    lv_obj_set_size(page, 150, 200);
    lv_page_set_scrl_fit(page, false, false);
    lv_page_set_scrl_width(page, 100);
    lv_page_set_scrl_height(page, 150);

    lv_obj_t * o1 = lv_obj_create(page, NULL);
    lv_obj_set_size(o1, 10,10);
    lv_obj_set_pos(o1, 20, 30);

    lv_obj_t * o2 = lv_obj_create(page, NULL);
    lv_obj_set_size(o2, 10,10);
    lv_obj_set_pos(o2, 50, lv_obj_get_y(o1) + 10);

Results: image

kisvegabor commented 6 years ago

I updated the documentation of lv_page here: https://littlevgl.com/object-types/page-lv_page Now it explains this phenomenon.

I close this issue now, but feel free to reopen it if you have any remarks!

Polarisru commented 6 years ago

Hello, I have the same issue with scrollable page. I want to use it for displaying a set of buttons to make possible swiping thru this set. Here is the code for initializing the page element:

lv_obj_t * page = lv_page_create(lv_scr_act(), NULL);
lv_obj_set_size(page, 460, 200);
lv_obj_align(page, NULL, LV_ALIGN_CENTER, 0, 0);
lv_page_set_scrl_width(page, 800);
lv_page_set_scrl_height(page, 180);
lv_page_set_scrl_fit(page, false, false);
lv_page_set_sb_mode(page, LV_SB_MODE_AUTO); 

So the scrollable area is bigger than the base page, it should be scrollable now. But in fact I see only a part of the buttons, scrollable area is fitted to the size of the parent page:

scroll_issue

If I enable the fitting feature (true for the horizontal axis), I get something like this:

scroll_issue_2

So it seems to work, but I can't get right positioning of the buttons, you can see the difference between the paddings of two buttons. What am I doing wrong? I have read the whole chapter about the page object, but I can't find any information regarding this feature. This is the initializing code for every button (they are only shifted horizontally):

lv_obj_t * btn1 = lv_btn_create(page, NULL);
lv_obj_set_size(btn1, 200, 75);
lv_cont_set_fit(btn1, false, false);
lv_obj_align(btn1, NULL, LV_ALIGN_IN_LEFT_MID, 50, 0);
lv_obj_set_free_num(btn1, 1);

Thank you in advance and have a nice day!

kisvegabor commented 6 years ago

Hi, I've just pushed a fux to dev-5.2 branch. Is it working now?

Polarisru commented 6 years ago

Sorry, I can't compile the version 5.2 anymore, it seems not to be compartible with images, lv_img_t is missing and not to find in the source codes.

Polarisru commented 6 years ago

Hello, I could compile it with newer version of drivers and examples (probably 5.1 is not compartible with 5.2), but page object has the same behaviour :( I guess the problem is not solved in 5.2.

kisvegabor commented 6 years ago

Yes, the images are not compatible with v5.1. You should generate the images again with the new converter tool: http://www.test.littlevgl.com/image-to-c-array

I tried this code:

    lv_obj_t * page = lv_page_create(lv_scr_act(), NULL);
    lv_obj_set_size(page, 460, 200);
    lv_obj_align(page, NULL, LV_ALIGN_CENTER, 0, 0);
    lv_page_set_scrl_width(page, 800);
    lv_page_set_scrl_height(page, 180);
    lv_page_set_scrl_fit(page, false, false);
    lv_page_set_sb_mode(page, LV_SB_MODE_AUTO);

    lv_obj_t * btn1 = lv_btn_create(page, NULL);
    lv_obj_set_size(btn1, 200, 75);
    lv_cont_set_fit(btn1, false, false);
    lv_obj_align(btn1, NULL, LV_ALIGN_IN_LEFT_MID, 50, 0);
    lv_obj_set_free_num(btn1, 1);

    lv_obj_t * btn2 = lv_btn_create(page, NULL);
    lv_obj_set_size(btn2, 200, 75);
    lv_cont_set_fit(btn2, false, false);
    lv_obj_align(btn2, btn1, LV_ALIGN_OUT_RIGHT_MID, 50, 0);
    lv_obj_set_free_num(btn2, 1);

And it resulted: image

Please test with the code above.