New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom scroll path support #2434
Comments
IMO these functions are too complicated to make the users reimplement them. I'm rather thinking about a callback for the indev driver like: void my_diff_modifier(lv_indev_drv_t * drv, lv_point_t * pressed_point, lv_coord_t * d)
{
//Dummy example slower scroll on the top sections
if(pressed_point->y < 200) *d = (*d) / 2;
} It makes LVGL believe you have scrolled less or more depending on various conditions. What do you think? In a project I also need a feature like this but it was much simpler. I just wanted to scroll slower at "half steps". |
Hi @kisvegabor, I agree those functions are too complicated to expose them to user.
The new position of object can be calculated with a function which defines object movement path. I'm not sure if there are better methods. I will investigate more these days. Edit: typo fix. |
Isn't the task is to change the scroll "sensitivity" based on the position on the screen? E.g. scroll less when the object is zoomed out? |
I may have mixed too issues here: zoom while scroll. The title "scroll path support" means that the object is limited to a path when scrolling. Please check below example. The object coordinates is actually following the path of this round screen. The scale of object(image in this case) is a function of its x coordinates. Basically it makes sure object always stays inside of the round screen. |
And is it managed on the "scroll handler's" level? So as the y coordinate changes you adjust the x coordinate too? If so I made something similar using only |
That basically what I needed. Thank you! I never thought to use style-translate. |
Hi @kisvegabor , The situation here is that object will resize when scrolling, thus not all children should move same distance. That's the reason I looked low level _lv_indev_scroll_handler. Using the tranlate style, it simply adds offset to coordinates that scroll handler calculates. When object size changes, it can't take object new size into consideration. Here is a screenshot to explain the issue: children moves faster than mouse and snap to center won't work because of wrong distance calculated. Do you have any suggestions? |
Correct me if I'm wrong but it seems to me that if you know the
you can change the scroll distance accordingly. That is a simple callback can work. The logic is to scroll less as you get closer to the top/bottom edge of the screen, isn't it? BTW, the rendering issue with opacity is already fixed 🙂 |
Yes. But where the callback should be made? And this callback should move the children accordingly, right? The logic is actuall make sure object being pressed follow mouse and others move accordingly. It may seem like scroll less but may need precise method to calculate distance.
Yes, we are currently using the release version. |
I imagine it like this:
This way you keep all the complex scrolling logic in LVGL (e.g. throw and elastic scroll) |
Yes, I agree. The callback should include all info you concluded to do the math. What about the position of children? Will there be a callback for every children? |
My idea is to add it to the indev driver. So you can modify only the scroll difference and let LVGL draw everything. Can you share to code of this UI. I can create something experimental to demonstrate what I mean. |
Thank you Gabor. The code is based on lv_example_scroll_6. Below is the full code I used. modified lv_example_scroll_6.c
#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES
static void scroll_event_cb(lv_event_t * e)
{
lv_obj_t * cont = lv_event_get_target(e);
lv_area_t cont_a;
lv_obj_get_coords(cont, &cont_a);
lv_coord_t cont_y_center = cont_a.y1 + lv_area_get_height(&cont_a) / 2;
lv_coord_t r = lv_obj_get_height(cont) * 3 / 10;
uint32_t i;
uint32_t child_cnt = lv_obj_get_child_cnt(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);
lv_coord_t child_y_center = child_a.y1 + lv_area_get_height(&child_a) / 2;
lv_coord_t diff_y = child_y_center - cont_y_center;
diff_y = LV_ABS(diff_y);
/*Get the x of diff_y on a circle.*/
lv_coord_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*/
lv_coord_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;
x = LV_MAX(0, x);
}
/*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_map(x, 0, r, LV_OPA_TRANSP, LV_OPA_COVER);
lv_obj_set_style_opa(child, LV_OPA_COVER - opa, 0);
lv_coord_t w = lv_map(r - x, 0, r, 0, 330);
lv_coord_t h = lv_map(r - x, 0, r, 0, 80);
w = LV_MAX(10, w);
h = LV_MAX(10, h);
LV_LOG_WARN("x: %d, w:%d, h: %d\n", x, w, h);
lv_obj_set_style_width(child, w, 0);
lv_obj_set_style_height(child, h, 0);
}
}
/**
* Translate the object as they scroll
*/
void lv_example_scroll_6(void)
{
lv_obj_t * cont = lv_obj_create(lv_scr_act());
lv_obj_set_size(cont, 400, 400);
lv_obj_set_style_border_width(cont, 5, 0);
// lv_obj_center(cont);
lv_obj_align(cont, LV_ALIGN_RIGHT_MID, 0, 0);
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_btn_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 %d", i);
}
/*Update the buttons position manually for first*/
lv_event_send(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 |
Yes, I noticed that too. That's my concern too. Using scroll function together with changing object size may have interferences. |
That's all because object size changed, distance snap function calculated is too far if object is zoomed in, I think. |
I agree. If I comment out the height change it works well. But the error on snapping seems too large. |
This issue is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 7 days. |
Hi @kisvegabor , The scrollable flag must be cleared in order to manully layout the list. This comes at a cost of no elastic effect, no default throw handler and no snap to center function. I'm going to simply copy relevant code to widget to fill the gap. What do you think? Should I continue to finish the functionality or seeking for other solutions like the scroll-diff-modifier? Regards, |
Nice! I'm just reviewing the PR and will comment there. |
This issue is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 7 days. |
This issue was closed because it has been stalled for 7 days with no activity. |
Introduce the problem
The default scroll event will map input device coordinates linearly to object coordinates. It's processed by lvgl by default.
Examples and cases
However, bellow example requires a custom scroll path and an object scale model.
The only solution I can come out is using pressing event, disable scrollable event and manually set the coordinates. But this won't work when children object exists that parent object won't get this event, thus won't work.
Suggested solution
Maybe a custom scroll process handler by user to override default behavior in
_lv_indev_scroll_handler, _lv_indev_scroll_throw_handler
etc.?cc @FASTSHIFT
Regards,
The text was updated successfully, but these errors were encountered: