diff --git a/examples/scroll/index.rst b/examples/scroll/index.rst index 1b1aae971e..e043a93db9 100644 --- a/examples/scroll/index.rst +++ b/examples/scroll/index.rst @@ -34,5 +34,10 @@ Infinite scrolling ------------------ .. lv_example:: scroll/lv_example_scroll_7 :language: c + +circular scrolling +------------------ +.. lv_example:: scroll/lv_example_scroll_8 + :language: c diff --git a/examples/scroll/lv_example_scroll.h b/examples/scroll/lv_example_scroll.h index de42c77eb0..6546c251e1 100644 --- a/examples/scroll/lv_example_scroll.h +++ b/examples/scroll/lv_example_scroll.h @@ -32,6 +32,7 @@ void lv_example_scroll_4(void); void lv_example_scroll_5(void); void lv_example_scroll_6(void); void lv_example_scroll_7(void); +void lv_example_scroll_8(void); /********************** * MACROS diff --git a/examples/scroll/lv_example_scroll_8.c b/examples/scroll/lv_example_scroll_8.c new file mode 100644 index 0000000000..3df5417cbc --- /dev/null +++ b/examples/scroll/lv_example_scroll_8.c @@ -0,0 +1,146 @@ +#include "../lv_examples.h" +#if LV_BUILD_EXAMPLES && LV_USE_FLEX + + +/* + * Circular list implementation based on: + * Reference: https://blog.csdn.net/TQW4321/article/details/145434819 + */ + +/* Applies to both width (for row items) and height (for column items) */ +#define ITEM_SIZE 80 + +/* Function to calculate the total content width of the container */ +static int32_t get_content_width(lv_obj_t * cont) +{ + int32_t w = 0; + int32_t pad_column = lv_obj_get_style_pad_column(cont, LV_PART_MAIN); // 列间距 + int total = lv_obj_get_child_count(cont); + + for(int i = 0; i < total; i++) { + w += lv_obj_get_width(lv_obj_get_child(cont, i)); + if(i < total - 1) w += pad_column; + } + return w + lv_obj_get_style_pad_left(cont, LV_PART_MAIN) + + lv_obj_get_style_pad_right(cont, LV_PART_MAIN); +} + +/* Scroll event callback for row layout */ +static void cont_row_scroll_event_cb(lv_event_t * e) +{ + static bool is_adjusting = false; + lv_obj_t * cont = lv_event_get_current_target_obj(e); + + if(!is_adjusting) { + is_adjusting = true; + int32_t scroll_x = lv_obj_get_scroll_x(cont); + int32_t cont_w = lv_obj_get_width(cont); + int32_t content_w = get_content_width(cont); + + /* Use ITEM_SIZE as horizontal item width */ + const int32_t item_width = ITEM_SIZE; + + if(scroll_x <= 0) { + lv_obj_t * last_child = lv_obj_get_child(cont, lv_obj_get_child_count(cont) - 1); + lv_obj_move_to_index(last_child, 0); + lv_obj_scroll_to_x(cont, scroll_x + item_width, LV_ANIM_OFF); + } + else if(scroll_x > content_w - cont_w) { + lv_obj_t * first_child = lv_obj_get_child(cont, 0); + lv_obj_move_to_index(first_child, lv_obj_get_child_count(cont) - 1); + lv_obj_scroll_to_x(cont, scroll_x - item_width, LV_ANIM_OFF); + } + is_adjusting = false; + } +} + +/* Function to calculate the total content height of the container */ +static int32_t get_content_height(lv_obj_t * cont) +{ + int32_t h = 0; + int32_t pad_row = lv_obj_get_style_pad_row(cont, LV_PART_MAIN); + int total = lv_obj_get_child_count(cont); + + for(int i = 0; i < total; i++) { + h += lv_obj_get_height(lv_obj_get_child(cont, i)); + if(i < total - 1) h += pad_row; + } + return h + lv_obj_get_style_pad_top(cont, LV_PART_MAIN) + + lv_obj_get_style_pad_bottom(cont, LV_PART_MAIN); +} + +/* Scroll event callback for column layout */ +static void cont_col_scroll_event_cb(lv_event_t * e) +{ + static bool is_adjusting = false; + lv_obj_t * cont = lv_event_get_current_target_obj(e); + + if(!is_adjusting) { + is_adjusting = true; + int32_t scroll_y = lv_obj_get_scroll_y(cont); + int32_t cont_h = lv_obj_get_height(cont); + int32_t content_h = get_content_height(cont); + + /* Use ITEM_SIZE as vertical item height */ + const int32_t item_height = ITEM_SIZE; + + if(scroll_y <= 0) { + lv_obj_t * last_child = lv_obj_get_child(cont, lv_obj_get_child_count(cont) - 1); + lv_obj_move_to_index(last_child, 0); + lv_obj_scroll_to_y(cont, scroll_y + item_height, LV_ANIM_OFF); + } + else if(scroll_y > content_h - cont_h) { + lv_obj_t * first_child = lv_obj_get_child(cont, 0); + lv_obj_move_to_index(first_child, lv_obj_get_child_count(cont) - 1); + lv_obj_scroll_to_y(cont, scroll_y - item_height, LV_ANIM_OFF); + } + is_adjusting = false; + } +} + +void lv_example_scroll_8(void) +{ + /* Create a scroll container with ROW flex direction */ + lv_obj_t * cont_row = lv_obj_create(lv_screen_active()); + lv_obj_set_size(cont_row, 300, 75); + lv_obj_align(cont_row, LV_ALIGN_TOP_MID, 0, 5); + lv_obj_set_flex_flow(cont_row, LV_FLEX_FLOW_ROW); + lv_obj_add_event_cb(cont_row, cont_row_scroll_event_cb, LV_EVENT_SCROLL, NULL); + /* Hide scrollbar visuals */ + lv_obj_set_scrollbar_mode(cont_row, LV_SCROLLBAR_MODE_OFF); + + /* Create a scroll container with COLUMN flex direction */ + lv_obj_t * cont_col = lv_obj_create(lv_screen_active()); + lv_obj_set_size(cont_col, 200, 150); + lv_obj_align_to(cont_col, cont_row, LV_ALIGN_OUT_BOTTOM_MID, 0, 5); + lv_obj_set_flex_flow(cont_col, LV_FLEX_FLOW_COLUMN); + lv_obj_add_event_cb(cont_col, cont_col_scroll_event_cb, LV_EVENT_SCROLL, NULL); + /* Hide scrollbar visuals */ + lv_obj_set_scrollbar_mode(cont_col, LV_SCROLLBAR_MODE_OFF); + + /* If the number of items is less than 3, scrolling may not be needed or may cause unexpected behavior. */ + uint32_t i; + for(i = 0; i < 10; i++) { + lv_obj_t * obj; + lv_obj_t * label; + + /*Add items to the row*/ + obj = lv_button_create(cont_row); + lv_obj_set_size(obj, ITEM_SIZE, LV_PCT(100)); + + label = lv_label_create(obj); + lv_label_set_text_fmt(label, "Item %" LV_PRIu32, i + 1); + lv_obj_center(label); + + /*Add items to the column*/ + obj = lv_button_create(cont_col); + lv_obj_set_size(obj, LV_PCT(100), ITEM_SIZE); + + label = lv_label_create(obj); + lv_label_set_text_fmt(label, "Item %" LV_PRIu32, i + 1); + lv_obj_center(label); + } +} + + +#endif