How to check if list has been scrolled to bottom


I am trying to figure out how to get something like a terms of service type prompt working where you have to “read” everything to enable a button.
I currently have a list which can contain an arbitrary number of messages which the user should read before they proceed.
Then there is a button at the bottom of the screen to confirm they read the messages.
I was wanting to enable the button at the bottom only when the list had been scrolled to the bottom (all the buttons in the list had been shown).
I was looking for something like getting the list scroll position or checking visibility of objects.
But I haven’t found a way of doing that so far.
Any suggestions on how to achieve that?

I have a couple of other ideas if I can’t figure out how to do that:
-Put the confirmation button in the list at the bottom so if the messages go off the screen they have to scroll down to get the confirmation button.
-Get the user to press the messages in the list to acknowledge each one before the confirmation button is enabled.



You can use the LV_EVENT_DRAG_END event and lv_page_on_edge().

While I was testing it I’ve found a bug in library and fixed it in the master branch. So you should update lvgl from GitHub.

Here is my test code:

static void list_event(lv_obj_t * list, lv_event_t e)
    if(e == LV_EVENT_DRAG_BEGIN) {
    if(e == LV_EVENT_DRAG_END) {
       printf("end: %d\n", lv_page_on_edge(list, LV_PAGE_EDGE_BOTTOM));


    lv_obj_t* list = lv_list_create(lv_scr_act(), NULL);
    lv_list_add_btn(list, NULL, "a");
    lv_list_add_btn(list, NULL, "b");
    lv_list_add_btn(list, NULL, "c");
    lv_list_add_btn(list, NULL, "d");
    lv_list_add_btn(list, NULL, "e");
    lv_list_add_btn(list, NULL, "f");
    lv_list_add_btn(list, NULL, "g");
    lv_list_add_btn(list, NULL, "h");
    lv_obj_set_event_cb(list, list_event);

Wow thanks for the quick response.

I didn’t even look at lv_page_* so that was my bad.

Should lv_page_on_edge be returning true if the list isn’t scrollable?
For example change your test to only add 1 button.

I think it should (pretty sure I wrote it) but I never tested that feature.

This is what I am getting.


Drag it up as if you were scrolling (even though it doesn’t appear visually scrollable) and see if it shows top: 0 bottom: 1. I’m guessing that it thinks it is scrollable by a few pixels.

I can’t drag it so I guess it isn’t scrollable. I’m just using the default style.
My debugger isn’t working at the moment so sorry I’m not that helpful.

Right, debugging working.
The default size of the page doesn’t match up with the y2 of the scrl you get when you only put one thing in it.

Extra info:

  • Create a list
    list has size 2 * LV_DPI, 3 * LV_DPI
    list’s scrl has size 2 * LV_DPI, (not sure where y comes from but it != 3 * LV_DPI)

  • obj_set_size(list, h, v)
    list has size h, v
    list’s scrl has size h, vertical is unchanged

  • list_add_btn
    list’s scrl vertical dimension changes to match up with the size of the button I guess

So page_on_edge(bottom) is never true without me going and changing sizes.

I’m not very familiar with the lvgl source yet so I’m not really sure if this is intentional.

Yes, it’s intentional because it’s really on the top. You can check this

    if(lv_page_get_scrl_height(list) < lv_obj_get_height_fit(list)) {
        /*Always visible*/

Or a more generic method:

    if(e == LV_EVENT_DRAG_END) {
       lv_obj_t * btn = lv_list_get_prev_btn(list, NULL);
       if(btn->coords.y2 <= list->coords.y2) printf("visible\n");
       else  printf("not visible\n");

Instead of “events” you can create an lv_task to periodically check the position of the last element.

Cool thanks.
I figured that first example but I haven’t looked into lv_task yet.

As it turns out the requirements were changed so I probably don’t need this functionality anymore.

Thanks for all the help guys.

You’re welcome!