add some code

This commit is contained in:
2025-09-05 13:25:11 +08:00
parent 9ff0a99e7a
commit 3cf1229a85
8911 changed files with 2535396 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
Nested scrolling
----------------
.. lv_example:: scroll/lv_example_scroll_1
:language: c
Snapping
--------
.. lv_example:: scroll/lv_example_scroll_2
:language: c
Floating button
----------------
.. lv_example:: scroll/lv_example_scroll_3
:language: c
Styling the scrollbars
----------------------
.. lv_example:: scroll/lv_example_scroll_4
:language: c
Right to left scrolling
-----------------------
.. lv_example:: scroll/lv_example_scroll_5
:language: c
Translate on scroll
-------------------
.. lv_example:: scroll/lv_example_scroll_6
:language: c
Infinite scrolling
------------------
.. lv_example:: scroll/lv_example_scroll_7
:language: c
circular scrolling
------------------
.. lv_example:: scroll/lv_example_scroll_8
:language: c

View File

@@ -0,0 +1,45 @@
/**
* @file lv_example_scroll.h
*
*/
#ifndef LV_EXAMPLE_SCROLL_H
#define LV_EXAMPLE_SCROLL_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
void lv_example_scroll_1(void);
void lv_example_scroll_2(void);
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);
void lv_example_scroll_8(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_EXAMPLE_SCROLL_H*/

View File

@@ -0,0 +1,101 @@
#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES
static lv_obj_t * panel;
static lv_obj_t * save_button;
static lv_obj_t * restore_button;
static int saved_scroll_x;
static int saved_scroll_y;
static void scroll_update_cb(lv_event_t * e);
static void button_event_cb(lv_event_t * e);
static void scroll_update_cb(lv_event_t * e)
{
LV_UNUSED(e);
LV_LOG("scroll info: x:%3" LV_PRId32", y:%3" LV_PRId32", top:%3" LV_PRId32", "
"bottom:%3" LV_PRId32", left:%3" LV_PRId32", right:%3" LV_PRId32"\n",
lv_obj_get_scroll_x(panel),
lv_obj_get_scroll_y(panel),
lv_obj_get_scroll_top(panel),
lv_obj_get_scroll_bottom(panel),
lv_obj_get_scroll_left(panel),
lv_obj_get_scroll_right(panel)
);
}
static void button_event_cb(lv_event_t * e)
{
lv_obj_t * obj = lv_event_get_target_obj(e);
if(obj == save_button) {
saved_scroll_x = lv_obj_get_scroll_x(panel);
saved_scroll_y = lv_obj_get_scroll_y(panel);
}
else {
lv_obj_scroll_to(panel, saved_scroll_x, saved_scroll_y, LV_ANIM_ON);
}
}
/**
* Demonstrate how scrolling appears automatically
*/
void lv_example_scroll_1(void)
{
/*Create an object with the new style*/
lv_obj_t * scr;
scr = lv_screen_active();
panel = lv_obj_create(scr);
lv_obj_set_size(panel, 200, 200);
lv_obj_align(panel, LV_ALIGN_CENTER, 44, 0);
lv_obj_t * child;
lv_obj_t * label;
child = lv_obj_create(panel);
lv_obj_set_pos(child, 0, 0);
lv_obj_set_size(child, 70, 70);
label = lv_label_create(child);
lv_label_set_text(label, "Zero");
lv_obj_center(label);
child = lv_obj_create(panel);
lv_obj_set_pos(child, 160, 80);
lv_obj_set_size(child, 80, 80);
lv_obj_t * child2 = lv_button_create(child);
lv_obj_set_size(child2, 100, 50);
label = lv_label_create(child2);
lv_label_set_text(label, "Right");
lv_obj_center(label);
child = lv_obj_create(panel);
lv_obj_set_pos(child, 40, 160);
lv_obj_set_size(child, 100, 70);
label = lv_label_create(child);
lv_label_set_text(label, "Bottom");
lv_obj_center(label);
/* When LV_OBJ_FLAG_SCROLL_ELASTIC is cleared, scrolling does not go past edge bounaries. */
/* lv_obj_clear_flag(panel, LV_OBJ_FLAG_SCROLL_ELASTIC); */
/* Call `scroll_update_cb` while panel is being scrolled. */
lv_obj_add_event_cb(panel, scroll_update_cb, LV_EVENT_SCROLL, NULL);
/* Set up buttons that save and restore scroll position. */
save_button = lv_button_create(scr);
restore_button = lv_button_create(scr);
lv_obj_t * lbl;
lbl = lv_label_create(save_button);
lv_label_set_text_static(lbl, "Save");
lbl = lv_label_create(restore_button);
lv_label_set_text_static(lbl, "Restore");
lv_obj_align_to(save_button, panel, LV_ALIGN_OUT_LEFT_MID, -10, -20);
lv_obj_align_to(restore_button, panel, LV_ALIGN_OUT_LEFT_MID, -10, 20);
lv_obj_add_event_cb(save_button, button_event_cb, LV_EVENT_CLICKED, NULL);
lv_obj_add_event_cb(restore_button, button_event_cb, LV_EVENT_CLICKED, NULL);
}
#endif

View File

@@ -0,0 +1,57 @@
#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_FLEX
static void sw_event_cb(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * sw = lv_event_get_target_obj(e);
if(code == LV_EVENT_VALUE_CHANGED) {
lv_obj_t * list = (lv_obj_t *) lv_event_get_user_data(e);
if(lv_obj_has_state(sw, LV_STATE_CHECKED)) lv_obj_add_flag(list, LV_OBJ_FLAG_SCROLL_ONE);
else lv_obj_remove_flag(list, LV_OBJ_FLAG_SCROLL_ONE);
}
}
/**
* Show an example to scroll snap
*/
void lv_example_scroll_2(void)
{
lv_obj_t * panel = lv_obj_create(lv_screen_active());
lv_obj_set_size(panel, 280, 120);
lv_obj_set_scroll_snap_x(panel, LV_SCROLL_SNAP_CENTER);
lv_obj_set_flex_flow(panel, LV_FLEX_FLOW_ROW);
lv_obj_align(panel, LV_ALIGN_CENTER, 0, 20);
uint32_t i;
for(i = 0; i < 10; i++) {
lv_obj_t * btn = lv_button_create(panel);
lv_obj_set_size(btn, 150, lv_pct(100));
lv_obj_t * label = lv_label_create(btn);
if(i == 3) {
lv_label_set_text_fmt(label, "Panel %" LV_PRIu32"\nno snap", i);
lv_obj_remove_flag(btn, LV_OBJ_FLAG_SNAPPABLE);
}
else {
lv_label_set_text_fmt(label, "Panel %" LV_PRIu32, i);
}
lv_obj_center(label);
}
lv_obj_update_snap(panel, LV_ANIM_ON);
#if LV_USE_SWITCH
/*Switch between "One scroll" and "Normal scroll" mode*/
lv_obj_t * sw = lv_switch_create(lv_screen_active());
lv_obj_align(sw, LV_ALIGN_TOP_RIGHT, -20, 10);
lv_obj_add_event_cb(sw, sw_event_cb, LV_EVENT_ALL, panel);
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "One scroll");
lv_obj_align_to(label, sw, LV_ALIGN_OUT_BOTTOM_MID, 0, 5);
#endif
}
#endif

View File

@@ -0,0 +1,49 @@
#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_LIST
static uint32_t btn_cnt = 1;
static void float_button_event_cb(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * float_btn = lv_event_get_target_obj(e);
if(code == LV_EVENT_CLICKED) {
lv_obj_t * list = (lv_obj_t *) lv_event_get_user_data(e);
char buf[32];
lv_snprintf(buf, sizeof(buf), "Track %d", (int)btn_cnt);
lv_obj_t * list_btn = lv_list_add_button(list, LV_SYMBOL_AUDIO, buf);
btn_cnt++;
lv_obj_move_foreground(float_btn);
lv_obj_scroll_to_view(list_btn, LV_ANIM_ON);
}
}
/**
* Create a list with a floating button
*/
void lv_example_scroll_3(void)
{
lv_obj_t * list = lv_list_create(lv_screen_active());
lv_obj_set_size(list, 280, 220);
lv_obj_center(list);
for(btn_cnt = 1; btn_cnt <= 2; btn_cnt++) {
char buf[32];
lv_snprintf(buf, sizeof(buf), "Track %d", (int)btn_cnt);
lv_list_add_button(list, LV_SYMBOL_AUDIO, buf);
}
lv_obj_t * float_btn = lv_button_create(list);
lv_obj_set_size(float_btn, 50, 50);
lv_obj_add_flag(float_btn, LV_OBJ_FLAG_FLOATING);
lv_obj_align(float_btn, LV_ALIGN_BOTTOM_RIGHT, 0, -lv_obj_get_style_pad_right(list, LV_PART_MAIN));
lv_obj_add_event_cb(float_btn, float_button_event_cb, LV_EVENT_ALL, list);
lv_obj_set_style_radius(float_btn, LV_RADIUS_CIRCLE, 0);
lv_obj_set_style_bg_image_src(float_btn, LV_SYMBOL_PLUS, 0);
lv_obj_set_style_text_font(float_btn, lv_theme_get_font_large(float_btn), 0);
}
#endif

View File

@@ -0,0 +1,67 @@
#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_LIST
/**
* Styling the scrollbars
*/
void lv_example_scroll_4(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_size(obj, 200, 100);
lv_obj_center(obj);
lv_obj_t * label = lv_label_create(obj);
lv_label_set_text(label,
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n"
"Etiam dictum, tortor vestibulum lacinia laoreet, mi neque consectetur neque, vel mattis odio dolor egestas ligula. \n"
"Sed vestibulum sapien nulla, id convallis ex porttitor nec. \n"
"Duis et massa eu libero accumsan faucibus a in arcu. \n"
"Ut pulvinar odio lorem, vel tempus turpis condimentum quis. Nam consectetur condimentum sem in auctor. \n"
"Sed nisl augue, venenatis in blandit et, gravida ac tortor. \n"
"Etiam dapibus elementum suscipit. \n"
"Proin mollis sollicitudin convallis. \n"
"Integer dapibus tempus arcu nec viverra. \n"
"Donec molestie nulla enim, eu interdum velit placerat quis. \n"
"Donec id efficitur risus, at molestie turpis. \n"
"Suspendisse vestibulum consectetur nunc ut commodo. \n"
"Fusce molestie rhoncus nisi sit amet tincidunt. \n"
"Suspendisse a nunc ut magna ornare volutpat.");
/*Remove the style of scrollbar to have clean start*/
lv_obj_remove_style(obj, NULL, LV_PART_SCROLLBAR | LV_STATE_ANY);
/*Create a transition the animate the some properties on state change*/
static const lv_style_prop_t props[] = {LV_STYLE_BG_OPA, LV_STYLE_WIDTH, 0};
static lv_style_transition_dsc_t trans;
lv_style_transition_dsc_init(&trans, props, lv_anim_path_linear, 200, 0, NULL);
/*Create a style for the scrollbars*/
static lv_style_t style;
lv_style_init(&style);
lv_style_set_width(&style, 4); /*Width of the scrollbar*/
lv_style_set_length(&style, 20); /*Length of the scrollbar*/
lv_style_set_pad_right(&style, 5); /*Space from the parallel side*/
lv_style_set_pad_top(&style, 5); /*Space from the perpendicular side*/
lv_style_set_radius(&style, 2);
lv_style_set_bg_opa(&style, LV_OPA_70);
lv_style_set_bg_color(&style, lv_palette_main(LV_PALETTE_BLUE));
lv_style_set_border_color(&style, lv_palette_darken(LV_PALETTE_BLUE, 3));
lv_style_set_border_width(&style, 2);
lv_style_set_shadow_width(&style, 8);
lv_style_set_shadow_spread(&style, 2);
lv_style_set_shadow_color(&style, lv_palette_darken(LV_PALETTE_BLUE, 1));
lv_style_set_transition(&style, &trans);
/*Make the scrollbars wider and use 100% opacity when scrolled*/
static lv_style_t style_scrolled;
lv_style_init(&style_scrolled);
lv_style_set_width(&style_scrolled, 8);
lv_style_set_bg_opa(&style_scrolled, LV_OPA_COVER);
lv_obj_add_style(obj, &style, LV_PART_SCROLLBAR);
lv_obj_add_style(obj, &style_scrolled, LV_PART_SCROLLBAR | LV_STATE_SCROLLED);
}
#endif

View File

@@ -0,0 +1,22 @@
#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_FONT_DEJAVU_16_PERSIAN_HEBREW
/**
* Scrolling with Right To Left base direction
*/
void lv_example_scroll_5(void)
{
lv_obj_t * obj = lv_obj_create(lv_screen_active());
lv_obj_set_style_base_dir(obj, LV_BASE_DIR_RTL, 0);
lv_obj_set_size(obj, 200, 100);
lv_obj_center(obj);
lv_obj_t * label = lv_label_create(obj);
lv_label_set_text(label,
"میکروکُنترولر (به انگلیسی: Microcontroller) گونه‌ای ریزپردازنده است که دارای حافظهٔ دسترسی تصادفی (RAM) و حافظهٔ فقط‌خواندنی (ROM)، تایمر، پورت‌های ورودی و خروجی (I/O) و درگاه ترتیبی (Serial Port پورت سریال)، درون خود تراشه است، و می‌تواند به تنهایی ابزارهای دیگر را کنترل کند. به عبارت دیگر یک میکروکنترلر، مدار مجتمع کوچکی است که از یک CPU کوچک و اجزای دیگری مانند تایمر، درگاه‌های ورودی و خروجی آنالوگ و دیجیتال و حافظه تشکیل شده‌است.");
lv_obj_set_width(label, 400);
lv_obj_set_style_text_font(label, &lv_font_dejavu_16_persian_hebrew, 0);
}
#endif

View File

@@ -0,0 +1,80 @@
#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_FLEX
static void scroll_event_cb(lv_event_t * e)
{
lv_obj_t * cont = lv_event_get_target_obj(e);
lv_area_t cont_a;
lv_obj_get_coords(cont, &cont_a);
int32_t cont_y_center = cont_a.y1 + lv_area_get_height(&cont_a) / 2;
int32_t r = lv_obj_get_height(cont) * 7 / 10;
int32_t i;
int32_t child_cnt = (int32_t)lv_obj_get_child_count(cont);
for(i = 0; i < child_cnt; i++) {
lv_obj_t * child = lv_obj_get_child(cont, i);
lv_area_t child_a;
lv_obj_get_coords(child, &child_a);
int32_t child_y_center = child_a.y1 + lv_area_get_height(&child_a) / 2;
int32_t diff_y = child_y_center - cont_y_center;
diff_y = LV_ABS(diff_y);
/*Get the x of diff_y on a circle.*/
int32_t x;
/*If diff_y is out of the circle use the last point of the circle (the radius)*/
if(diff_y >= r) {
x = r;
}
else {
/*Use Pythagoras theorem to get x from radius and y*/
uint32_t x_sqr = r * r - diff_y * diff_y;
lv_sqrt_res_t res;
lv_sqrt(x_sqr, &res, 0x8000); /*Use lvgl's built in sqrt root function*/
x = r - res.i;
}
/*Translate the item by the calculated X coordinate*/
lv_obj_set_style_translate_x(child, x, 0);
/*Use some opacity with larger translations*/
lv_opa_t opa = (lv_opa_t)lv_map(x, 0, r, LV_OPA_TRANSP, LV_OPA_COVER);
lv_obj_set_style_opa(child, LV_OPA_COVER - opa, 0);
}
}
/**
* Translate the object as they scroll
*/
void lv_example_scroll_6(void)
{
lv_obj_t * cont = lv_obj_create(lv_screen_active());
lv_obj_set_size(cont, 200, 200);
lv_obj_center(cont);
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
lv_obj_add_event_cb(cont, scroll_event_cb, LV_EVENT_SCROLL, NULL);
lv_obj_set_style_radius(cont, LV_RADIUS_CIRCLE, 0);
lv_obj_set_style_clip_corner(cont, true, 0);
lv_obj_set_scroll_dir(cont, LV_DIR_VER);
lv_obj_set_scroll_snap_y(cont, LV_SCROLL_SNAP_CENTER);
lv_obj_set_scrollbar_mode(cont, LV_SCROLLBAR_MODE_OFF);
uint32_t i;
for(i = 0; i < 20; i++) {
lv_obj_t * btn = lv_button_create(cont);
lv_obj_set_width(btn, lv_pct(100));
lv_obj_t * label = lv_label_create(btn);
lv_label_set_text_fmt(label, "Button %" LV_PRIu32, i);
}
/*Update the buttons position manually for first*/
lv_obj_send_event(cont, LV_EVENT_SCROLL, NULL);
/*Be sure the fist button is in the middle*/
lv_obj_scroll_to_view(lv_obj_get_child(cont, 0), LV_ANIM_OFF);
}
#endif

View File

@@ -0,0 +1,126 @@
#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 bool update_scroll_running = false;
static lv_obj_t * load_item(lv_obj_t * parent, int32_t num)
{
lv_obj_t * obj = (lv_obj_t *) lv_obj_create(parent);
lv_obj_set_size(obj, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_t * label = lv_label_create(obj);
lv_label_set_text_fmt(label, "%" PRId32, num);
return obj;
}
static void update_scroll(lv_obj_t * obj)
{
/* do not re-enter this function when `lv_obj_scroll_by`
* triggers this callback again.
*/
if(update_scroll_running) return;
update_scroll_running = true;
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);
}
update_scroll_running = false;
}
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_obj_t *) 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);
load_item(obj, 3);
/* These counters hold the the highest/lowest number currently loaded. */
top_num = 3;
bottom_num = 3;
lv_obj_update_layout(obj);
update_scroll(obj);
lv_obj_add_event_cb(obj, scroll_cb, LV_EVENT_SCROLL, NULL);
}
#endif

View File

@@ -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); // 列间距
int32_t total = (int32_t)lv_obj_get_child_count(cont);
for(int32_t 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, (int32_t)(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, (int32_t)(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);
int32_t total = (int32_t)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, (int32_t)(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, (int32_t)(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