1# Scroll
2
3## Overview
4In LVGL scrolling works very intuitively: if an object is outside its parent content area (the size without padding), the parent becomes scrollable and scrollbar(s) will appear. That's it.
5
6Any object can be scrollable including `lv_obj_t`, `lv_img`, `lv_btn`, `lv_meter`, etc
7
8The object can either be scrolled horizontally or vertically in one stroke; diagonal scrolling is not possible.
9
10### Scrollbar
11
12#### Mode
13Scrollbars are displayed according to a configured `mode`. The following `mode`s exist:
14- `LV_SCROLLBAR_MODE_OFF`  Never show the scrollbars
15- `LV_SCROLLBAR_MODE_ON`  Always show the scrollbars
16- `LV_SCROLLBAR_MODE_ACTIVE` Show scroll bars while an object is being scrolled
17- `LV_SCROLLBAR_MODE_AUTO`  Show scroll bars when the content is large enough to be scrolled
18
19`lv_obj_set_scrollbar_mode(obj, LV_SCROLLBAR_MODE_...)` sets the scrollbar mode on an object.
20
21
22#### Styling
23The scrollbars have their own dedicated part, called `LV_PART_SCROLLBAR`. For example a scrollbar can turn to red like this:
24```c
25static lv_style_t style_red;
26lv_style_init(&style_red);
27lv_style_set_bg_color(&style_red, lv_color_red());
28
29...
30
31lv_obj_add_style(obj, &style_red, LV_PART_SCROLLBAR);
32```
33
34An object goes to the `LV_STATE_SCROLLED` state while it's being scrolled. This allows adding different styles to the scrollbar or the object itself when scrolled.
35This code makes the scrollbar blue when the object is scrolled:
36```c
37static lv_style_t style_blue;
38lv_style_init(&style_blue);
39lv_style_set_bg_color(&style_blue, lv_color_blue());
40
41...
42
43lv_obj_add_style(obj, &style_blue, LV_STATE_SCROLLED | LV_PART_SCROLLBAR);
44```
45
46If the base direction of the `LV_PART_SCROLLBAR` is RTL (`LV_BASE_DIR_RTL`) the vertical scrollbar will be placed on the left.
47Note that, the `base_dir` style property is inherited. Therefore, it can be set directly on the `LV_PART_SCROLLBAR` part of an object
48or on the object's or any parent's main part to make a scrollbar inherit the base direction.
49
50`pad_left/right/top/bottom` sets the spacing around the scrollbars and `width` sets the scrollbar's width.
51
52### Events
53The following events are related to scrolling:
54- `LV_EVENT_SCROLL_BEGIN` Scrolling begins. The event parameter is `NULL` or an `lv_anim_t *` with a scroll animation descriptor that can be modified if required.
55- `LV_EVENT_SCROLL_END` Scrolling ends.
56- `LV_EVENT_SCROLL` Scroll happened. Triggered on every position change.
57Scroll events
58
59## Basic example
60TODO
61
62## Features of scrolling
63
64Besides, managing "normal" scrolling there are many interesting and useful additional features.
65
66
67### Scrollable
68
69It's possible to make an object non-scrollable with `lv_obj_clear_flag(obj, LV_OBJ_FLAG_SCROLLABLE)`.
70
71Non-scrollable objects can still propagate the scrolling (chain) to their parents.
72
73The direction in which scrolling happens can be controlled by `lv_obj_set_scroll_dir(obj, LV_DIR_...)`.
74The following values are possible for the direction:
75- `LV_DIR_TOP` only scroll up
76- `LV_DIR_LEFT` only scroll left
77- `LV_DIR_BOTTOM` only scroll down
78- `LV_DIR_RIGHT` only scroll right
79- `LV_DIR_HOR` only scroll horizontally
80- `LV_DIR_VER` only scroll vertically
81- `LV_DIR_ALL` scroll any directions
82
83OR-ed values are also possible. E.g. `LV_DIR_TOP | LV_DIR_LEFT`.
84
85
86### Scroll chain
87If an object can't be scrolled further (e.g. its content has reached the bottom-most position) additional scrolling is propagated to its parent. If the parent can be scrolled in that direction than it will be scrolled instead.
88It continues propagating to the grandparent and grand-grandparents as well.
89
90The propagation on scrolling is called "scroll chaining" and it can be enabled/disabled with `LV_OBJ_FLAG_SCROLL_CHAIN_HOR/VER` flag.
91If chaining is disabled the propagation stops on the object and the parent(s) won't be scrolled.
92
93### Scroll momentum
94When the user scrolls an object and releases it, LVGL can emulate inertial momentum for the scrolling. It's like the object was thrown and scrolling slows down smoothly.
95
96The scroll momentum can be enabled/disabled with the `LV_OBJ_FLAG_SCROLL_MOMENTUM` flag.
97
98### Elastic scroll
99Normally an object can't be scrolled past the extremeties of its content. That is the top side of the content can't be below the top side of the object.
100
101However, with `LV_OBJ_FLAG_SCROLL_ELASTIC` a fancy effect is added when the user "over-scrolls" the content. The scrolling slows down, and the content can be scrolled inside the object.
102When the object is released the content scrolled in it will be animated back to the valid position.
103
104### Snapping
105The children of an object can be snapped according to specific rules when scrolling ends. Children can be made snappable individually with the `LV_OBJ_FLAG_SNAPPABLE` flag.
106
107An object can align snapped children in four ways:
108- `LV_SCROLL_SNAP_NONE` Snapping is disabled. (default)
109- `LV_SCROLL_SNAP_START` Align the children to the left/top side of a scrolled object
110- `LV_SCROLL_SNAP_END` Align the children to the right/bottom side of a scrolled object
111- `LV_SCROLL_SNAP_CENTER` Align the children to the center of a scrolled object
112
113Snap alignment is set with `lv_obj_set_scroll_snap_x/y(obj, LV_SCROLL_SNAP_...)`:
114
115Under the hood the following happens:
1161. User scrolls an object and releases the screen
1172. LVGL calculates where the scroll would end considering scroll momentum
1183. LVGL finds the nearest scroll point
1194. LVGL scrolls to the snap point with an animation
120
121### Scroll one
122The "scroll one" feature tells LVGL to allow scrolling only one snappable child at a time.
123This requires making the children snappable and setting a scroll snap alignment different from `LV_SCROLL_SNAP_NONE`.
124
125This feature can be enabled by the `LV_OBJ_FLAG_SCROLL_ONE` flag.
126
127### Scroll on focus
128Imagine that there a lot of objects in a group that are on a scrollable object. Pressing the "Tab" button focuses the next object but it might be outside the visible area of the scrollable object.
129If the "scroll on focus" feature is enabled LVGL will automatically scroll objects to bring their children into view.
130The scrolling happens recursively therefore even nested scrollable objects are handled properly.
131The object will be scrolled into view even if it's on a different page of a tabview.
132
133## Scroll manually
134The following API functions allow manual scrolling of objects:
135- `lv_obj_scroll_by(obj, x, y, LV_ANIM_ON/OFF)` scroll by `x` and `y` values
136- `lv_obj_scroll_to(obj, x, y, LV_ANIM_ON/OFF)` scroll to bring the given coordinate to the top left corner
137- `lv_obj_scroll_to_x(obj, x, LV_ANIM_ON/OFF)` scroll to bring the given coordinate to the left side
138- `lv_obj_scroll_to_y(obj, y, LV_ANIM_ON/OFF)` scroll to bring the given coordinate to the top side
139
140From time to time you may need to retrieve the scroll position of an element, either to restore it later, or to display dynamically some elements according to the current scroll.
141Here is an example to see how to combine scroll event and store the scroll top position.
142```c
143static int scroll_value = 0;
144
145static void store_scroll_value_event_cb(lv_event_t* e) {
146  lv_obj_t* screen = lv_event_get_target(e);
147  scroll_value = lv_obj_get_scroll_top(screen);
148  printf("%d pixels are scrolled out on the top\n", scroll_value);
149}
150
151lv_obj_t* container = lv_obj_create(NULL);
152lv_obj_add_event_cb(container, store_scroll_value_event_cb, LV_EVENT_SCROLL, NULL);
153```
154
155Scrool coordinates can be retrieve from differents axes with these functions:
156- `lv_obj_get_scroll_x(obj)` Get the `x` coordinate of object
157- `lv_obj_get_scroll_y(obj)` Get the `y` coordinate of object
158- `lv_obj_get_scroll_top(obj)` Get the scroll coordinate from the top
159- `lv_obj_get_scroll_bottom(obj)` Get the scroll coordinate from the bottom
160- `lv_obj_get_scroll_left(obj)` Get the scroll coordinate from the left
161- `lv_obj_get_scroll_right(obj)` Get the scroll coordinate from the right
162
163## Self size
164
165Self size is a property of an object. Normally, the user shouldn't use this parameter but if a custom widget is created it might be useful.
166
167In short, self size establishes the size of an object's content. To understand it better take the example of a table.
168Let's say it has 10 rows each with 50 px height. So the total height of the content is 500 px. In other words the "self height" is 500 px.
169If the user sets only 200 px height for the table LVGL will see that the self size is larger and make the table scrollable.
170
171This means not only the children can make an object scrollable but a larger self size will too.
172
173LVGL uses the `LV_EVENT_GET_SELF_SIZE` event to get the self size of an object. Here is an example to see how to handle the event:
174```c
175if(event_code == LV_EVENT_GET_SELF_SIZE) {
176	lv_point_t * p = lv_event_get_param(e);
177
178  //If x or y < 0 then it doesn't neesd to be calculated now
179  if(p->x >= 0) {
180    p->x = 200;	//Set or calculate the self width
181  }
182
183  if(p->y >= 0) {
184    p->y = 50;	//Set or calculate the self height
185  }
186}
187```
188
189## Examples
190
191```eval_rst
192
193.. include:: ../../examples/scroll/index.rst
194
195```
196