From 5272788bfb296e91fe2146083ba6ed043778f7e1 Mon Sep 17 00:00:00 2001 From: Liam <30486941+liamHowatt@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:34:14 -0500 Subject: [PATCH] feat(examples): add infinite scroll example (#7388) --- examples/scroll/index.rst | 5 ++ examples/scroll/lv_example_scroll.h | 1 + examples/scroll/lv_example_scroll_7.c | 123 ++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 examples/scroll/lv_example_scroll_7.c diff --git a/examples/scroll/index.rst b/examples/scroll/index.rst index 0691ce77b..1b1aae971 100644 --- a/examples/scroll/index.rst +++ b/examples/scroll/index.rst @@ -30,4 +30,9 @@ Translate on scroll .. lv_example:: scroll/lv_example_scroll_6 :language: c +Infinite scrolling +------------------ +.. lv_example:: scroll/lv_example_scroll_7 + :language: c + diff --git a/examples/scroll/lv_example_scroll.h b/examples/scroll/lv_example_scroll.h index f6443b455..de42c77eb 100644 --- a/examples/scroll/lv_example_scroll.h +++ b/examples/scroll/lv_example_scroll.h @@ -31,6 +31,7 @@ void lv_example_scroll_3(void); void lv_example_scroll_4(void); void lv_example_scroll_5(void); void lv_example_scroll_6(void); +void lv_example_scroll_7(void); /********************** * MACROS diff --git a/examples/scroll/lv_example_scroll_7.c b/examples/scroll/lv_example_scroll_7.c new file mode 100644 index 000000000..e4c1d8c41 --- /dev/null +++ b/examples/scroll/lv_example_scroll_7.c @@ -0,0 +1,123 @@ +#include "../lv_examples.h" +#if LV_BUILD_EXAMPLES && LV_USE_FLEX + +static lv_obj_t * high_label; +static lv_obj_t * low_label; +static int32_t top_num; +static int32_t bottom_num; + +static lv_obj_t * load_item(lv_obj_t * parent, int32_t num) +{ + lv_obj_t * new = lv_obj_create(parent); + lv_obj_set_size(new, LV_PCT(100), LV_SIZE_CONTENT); + lv_obj_t * label = lv_label_create(new); + lv_label_set_text_fmt(label, "%"PRId32, num); + return new; +} + +static void update_scroll(lv_obj_t * obj) +{ + int32_t top_num_original = top_num; + int32_t bottom_num_original = bottom_num; + + /* load items we're getting close to */ + while(bottom_num > -30 && lv_obj_get_scroll_bottom(obj) < 200) { + bottom_num -= 1; + load_item(obj, bottom_num); + lv_obj_update_layout(obj); + LV_LOG_USER("loaded bottom num: %"PRId32, bottom_num); + } + while(top_num < 30 && lv_obj_get_scroll_top(obj) < 200) { + top_num += 1; + int32_t bottom_before = lv_obj_get_scroll_bottom(obj); + lv_obj_t * new_item = load_item(obj, top_num); + lv_obj_move_to_index(new_item, 0); + lv_obj_update_layout(obj); + int32_t bottom_after = lv_obj_get_scroll_bottom(obj); + lv_obj_scroll_by(obj, 0, bottom_before - bottom_after, LV_ANIM_OFF); + LV_LOG_USER("loaded top num: %"PRId32, top_num); + } + + /* delete far-away items */ + while(lv_obj_get_scroll_bottom(obj) > 600) { + bottom_num += 1; + lv_obj_t * child = lv_obj_get_child(obj, -1); + lv_obj_delete(child); + lv_obj_update_layout(obj); + LV_LOG_USER("deleted bottom num: %"PRId32, bottom_num); + } + while(lv_obj_get_scroll_top(obj) > 600) { + top_num -= 1; + int32_t bottom_before = lv_obj_get_scroll_bottom(obj); + lv_obj_t * child = lv_obj_get_child(obj, 0); + lv_obj_delete(child); + lv_obj_update_layout(obj); + int32_t bottom_after = lv_obj_get_scroll_bottom(obj); + lv_obj_scroll_by(obj, 0, bottom_before - bottom_after, LV_ANIM_OFF); + LV_LOG_USER("deleted top num: %"PRId32, top_num); + } + + if(top_num != top_num_original) { + lv_label_set_text_fmt(high_label, "current largest\nloaded value:\n%"PRId32, top_num); + } + if(bottom_num != bottom_num_original) { + lv_label_set_text_fmt(low_label, "current smallest\nloaded value:\n%"PRId32, bottom_num); + } +} + +static void scroll_cb(lv_event_t * e) +{ + lv_obj_t * obj = lv_event_get_target_obj(e); + update_scroll(obj); +} + +static void checkbox_cb(lv_event_t * e) +{ + lv_obj_t * checkbox = lv_event_get_target_obj(e); + lv_obj_t * obj = lv_event_get_user_data(e); + bool checked = lv_obj_has_state(checkbox, LV_STATE_CHECKED); + lv_obj_set_style_opa(obj, checked ? LV_OPA_COVER : LV_OPA_TRANSP, LV_PART_SCROLLBAR); +} + +/** + * Dynamically load widgets while scrolling + */ +void lv_example_scroll_7(void) +{ + lv_obj_t * scr = lv_screen_active(); + lv_obj_t * obj = lv_obj_create(scr); + lv_obj_set_size(obj, 160, 220); + lv_obj_align(obj, LV_ALIGN_RIGHT_MID, -10, 0); + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_opa(obj, LV_OPA_TRANSP, LV_PART_SCROLLBAR); + + high_label = lv_label_create(scr); + lv_label_set_text_static(high_label, "current largest\nloaded value:"); + lv_obj_align(high_label, LV_ALIGN_TOP_LEFT, 10, 10); + + lv_obj_t * checkbox = lv_checkbox_create(scr); + lv_checkbox_set_text_static(checkbox, "show\nscrollbar"); + lv_obj_align(checkbox, LV_ALIGN_LEFT_MID, 10, 0); + lv_obj_add_event_cb(checkbox, checkbox_cb, LV_EVENT_VALUE_CHANGED, obj); + + low_label = lv_label_create(scr); + lv_label_set_text_static(low_label, "current smallest\nloaded value:"); + lv_obj_align(low_label, LV_ALIGN_BOTTOM_LEFT, 10, -10); + + /* These counters hold the the highest/lowest number currently shown. + * Since no numbers are show yet, set them such that they will be + * correct after the first value is added. + * I.e., if a value is added at the top, `top_num` will be incremented + * and its new value (4) will be added to the top (`top_num`=4, `bottom_num`=4). + * If a value is added to the bottom, `bottom_num` will be decremented + * and its new value (3) will be added to the bottom (`top_num`=3, `bottom_num`=3). + */ + top_num = 3; + bottom_num = 4; + + lv_obj_update_layout(obj); + update_scroll(obj); + lv_obj_add_event_cb(obj, scroll_cb, LV_EVENT_SCROLL, NULL); +} + +#endif