Scrollbar can't scroll normally


Important: unclear posts may not receive useful answers.

How to scroll properly?

Before posting

  • Get familiar with Markdown to format and structure your post
  • Be sure to update lvgl from the latest version from the master branch.
  • Be sure you have checked the relevant part of the documentation.
  • If applicable use the Simulator to eliminate hardware related issues.

Delete this section if you read and applied the mentioned points.

Description

What MCU/Processor/Board and compiler are you using?

IMX6SX

What LVGL version are you using?

V8.0.1

What do you want to achieve?

scrollbar run normally

What have you tried so far?

The image is displayed on an obj. The image can be zoomed in and out by setting the magnification on the button.This works normally on V7. After LVGL is migrated to V8, the scroll is normal when the image is not zoomed in or out. Once the scroll is zoomed in or out, the scroll cannot scroll normally.

Code to reproduce

Add a code snippet which can run in the simulator. It should contain only the relevant code that compiles without errors when separated from your main code base.

The code block(s) should be formatted like:

in file lv_conf.h:

#define LV_USE_LARGE_COORD  1
static void img_con_event_call_back(lv_event_t *event)
{
   
   lv_obj_t * obj = lv_event_get_target(event);
   lv_event_code_t code = lv_event_get_code(event);

   DITPATTERNFILEINFO * p_info = win_file_edit->file_info;
   if(LV_EVENT_PRESSED == code)
   {
      ...
   }
   else if(code == LV_EVENT_DRAW_MAIN) 
   {
      /* draw the image in view area*/
      file_edit_img_draw(event);
   }
}

lv_obj_t *  file_edit_creat_img_cont(lv_obj_t * par,
                        lv_event_cb_t   img_cont_event_cb)
{
    file_edit_obj_t       *win = (file_edit_obj_t *)par;
   //建立文件显示绘图区域。
    lv_obj_t * win_cont = lv_obj_create(win);
    if(win_cont  == NULL)
         return NULL;
    win->win_img_cont = win_cont;
    win_cont->obj_name = "file_edit_img_cont";
    lv_coord_t w = lv_obj_get_content_width(win);
    lv_coord_t h = lv_obj_get_content_height(win);

    lv_style_t   *page_style_p = &win->page_style;
    lv_style_init            ( page_style_p      );
    lv_style_set_pad_all     ( page_style_p,  0  );
    lv_style_set_radius      ( page_style_p,  0  );
    lv_style_set_bg_opa      ( page_style_p,  255);
    lv_style_set_bg_color    ( page_style_p,  LV_COLOR_MAKE(255,255,255));
    lv_style_set_border_width( page_style_p,  0  );
    
    lv_style_set_text_font( page_style_p,  &lv_font_montserrat_14);

    lv_obj_add_style(win_cont, page_style_p, LV_PART_MAIN);
     
    lv_obj_t * win_img_page = lv_obj_create(win_cont);
    if(win_img_page  == NULL)
    {
      lv_style_reset(page_style_p);
      lv_obj_del(win_cont);
      return NULL;
    }
    win_img_page->obj_name = "file_edit_img_page";  
    win->win_img_page = win_img_page;
   
    lv_obj_add_style(win_img_page, page_style_p, LV_PART_MAIN);
    lv_obj_set_style_bg_color    (win_img_page, LV_COLOR_MAKE(255,255,255),LV_PART_MAIN);
    lv_obj_set_style_bg_opa      (win_img_page, 255,LV_PART_MAIN);
    return win_cont;
}  
   
/******************************************************************************
*When the scaling is changed, calculate the target size and position          *                                   *
*                 缩放尽量以光标所在位置为基点缩放                            *
*******************************************************************************/
static void set_zoom_scal(int old_scal_size,int new_scal_size)
{
     const lv_area_t * page_area =   &win_file_edit->win_img_page->coords;
     lv_obj_t * scrl = win_file_edit->win_img_cont;
     lv_obj_t * page = win_file_edit->win_img_page;//lv_obj_get_parent(scrl);

     lv_area_t clip_area = scrl->coords;
     int board     = lv_obj_get_style_border_width( page,LV_PART_MAIN);   
     int pad_top    = lv_obj_get_style_pad_top( page,LV_PART_MAIN);
     int pad_bottom = lv_obj_get_style_pad_bottom( page,LV_PART_MAIN);
     int pad_right  = lv_obj_get_style_pad_right( page,LV_PART_MAIN);
     int pad_left   = lv_obj_get_style_pad_left( page,LV_PART_MAIN);
     
     clip_area.x1 += pad_left + board;
     clip_area.y1 += pad_top  + board;
     clip_area.x2 -= pad_right + board;
     clip_area.y2 -= pad_bottom + board;
     
     lv_point_t *pressed_point = &win_file_edit->pressed_point;

     int32_t new_width  = win_file_edit->file_info->Width  * new_scal_size;
     int32_t new_height = win_file_edit->file_info->Height * new_scal_size;

     int32_t clip_width  = (clip_area.x2  + 1 - clip_area.x1) ;
     int32_t clip_height = (clip_area.y2  + 1 - clip_area.y1) ;

     int32_t new_x1  = (page_area->x1 - pressed_point->x ) *  new_scal_size / old_scal_size;
     int32_t new_y1  = (page_area->y1 - pressed_point->y ) *  new_scal_size / old_scal_size;
     /*与父对象左上角坐标的距离 */
     new_x1 += pressed_point->x - clip_area.x1;
     new_y1 += pressed_point->y - clip_area.y1;

     /*保证两左上角的距离小于或等于0. */
     new_x1 = (new_x1> 0 )?0:new_x1;
     new_y1 = (new_y1> 0 )?0:new_y1;

     lv_coord_t w = lv_disp_get_hor_res(NULL) - 1;
     lv_coord_t h = lv_disp_get_ver_res(NULL) - 1;
     int32_t new_x2 = new_x1 + new_width  -1;
     int32_t new_y2 = new_y1 + new_height  -1;
     
     
     if( new_x2 <  w )
       new_x1 +=  (w - new_x2);
   
     if( new_y2 <  h )
       new_y1 +=  (h - new_y2);
   
     if( new_width <= clip_width)
       new_x1 = 0;
     else if(new_x1 < (clip_width - new_width  ))
       new_x1 = clip_width - new_width ;

      if( new_height <= clip_height)
       new_y1 = 0;
      else if(new_y1 < (clip_height - new_height ))
       new_y1 = clip_height - new_height ;

    
     lv_obj_set_size(page, 
                     new_width,
                     new_height);
     lv_obj_set_pos(page, 
                     new_x1,
                     new_y1);
}

/*You code here*/

Screenshot and/or video

If possible, add screenshots and/or videos about the current state.

Sorry but I don’t understand this. From the description I think the issue can be reproduced with much less code too. So could you send a shorter code snippet?

Continuing the discussion from Scrollbar can't scroll normally:

I draw pattern directly on an obj based on the scale I set.When this scale does not change, the scrolling operation works and the entire pattern(obj) can be scrolled.Once the scale has been changed, the pattern cannot be scrolled after the size and position of obj have been reset according to the scale .Drag the screen now, scrollbar can not scroll.


Please send a small code snippet to reproduce it.

Here is the complete code to reproduce the problem:

#include "lvgl.h"

static int scal = 100;
static lv_obj_t * cont;
static lv_obj_t * scroll_obj;
static int        scroll_obj_width;
static int        scroll_obj_height;

static void scal_btn_event_cb(lv_event_t * e)
{
    lv_obj_t * obj = lv_event_get_target(e);
    lv_event_code_t code = lv_event_get_code(e);
    
   if(code == LV_EVENT_VALUE_CHANGED)
   {
      uint16_t id = lv_btnmatrix_get_selected_btn(obj);

      if(id == LV_BTNMATRIX_BTN_NONE)
      {
        return;
      }
      if(id == 0)
        scal += 10;
      else
       (scal > 10)?scal -= 10:scal;
      lv_obj_set_size(scroll_obj,scal* scroll_obj_width / 100,scal * scroll_obj_height /100);
      lv_obj_center(scroll_obj);
   }
}

void lv_scallbar_example_1(void)
{
    lv_coord_t w = lv_disp_get_hor_res(lv_disp_get_default()) -100;
    lv_coord_t h = lv_disp_get_ver_res(lv_disp_get_default()) - 100;
    
    
    cont = lv_obj_create(lv_scr_act());
    scroll_obj = lv_obj_create(cont);
    
    lv_obj_set_style_bg_opa      (cont,255,LV_PART_MAIN);
    lv_obj_set_style_border_width      (cont,0,LV_PART_MAIN);
    lv_obj_set_style_bg_opa      (scroll_obj,255,LV_PART_MAIN);
    lv_obj_set_style_bg_color(scroll_obj,LV_COLOR_MAKE(255,0,0),LV_PART_MAIN);
    
    lv_obj_set_style_border_width      (scroll_obj,2,LV_PART_MAIN);
    lv_obj_set_style_border_color(scroll_obj,LV_COLOR_MAKE(0,0,0),LV_PART_MAIN);
    
    lv_obj_t * scal_btn  = lv_btnmatrix_create(lv_scr_act());
    
    static char * btn_map[] = {"zoom out","zoom in",""};
    lv_btnmatrix_set_map(scal_btn,btn_map);
   
    lv_obj_set_size(cont, w,h);
    
    scroll_obj_width = w;
    scroll_obj_height = h;
    
    lv_obj_set_size(scroll_obj,w,h);
   
    lv_obj_set_size(scal_btn,300,80);
         
    lv_obj_center(cont);
    lv_obj_set_pos(scroll_obj,0,0);
    lv_obj_center(scal_btn);
     
    lv_obj_add_event_cb(scal_btn, scal_btn_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
}

I see now. So the problem is that you can’t scroll up and right if the image is zoomed in? If so it’s the intended behavior similarly to how it works on WEB.

The scrolling became really weird when the object was enlarged, scrolled and the then shrunk.

To fix this I added this line:

static void scal_btn_event_cb(lv_event_t * e)
{
    lv_obj_t * obj = lv_event_get_target(e);
    lv_event_code_t code = lv_event_get_code(e);

    if(code == LV_EVENT_VALUE_CHANGED)
    {
        uint16_t id = lv_btnmatrix_get_selected_btn(obj);

        if(id == LV_BTNMATRIX_BTN_NONE)
        {
            return;
        }
        if(id == 0) scal += 10;
        else (scal > 10)?scal -= 10:scal;

        lv_obj_set_size(scroll_obj,scal* scroll_obj_width / 100,scal * scroll_obj_height /100);
        lv_obj_center(scroll_obj);

        //Add this
        lv_obj_readjust_scroll(cont, LV_ANIM_OFF);
    }
}

Thank you very much, but adding this line has no effect.Once zoom in, it still can’t drag right or down.
When it can roll normally, the cont->spec_attr->scroll.x and cont->spec_attr->scroll.y, It varies with the position of scroll_obj, but this two values are zero always when scroll_obj cannot be scrolled.so this line has no effect.

Once zoom in, it still can’t drag right or down.

Maybe I misunderstood the problem. Zoom in means enlarge and zoom out means “shrink” but these are swapped in your example.

So the goal is to allow scrolling to the right and down when the object is small? If it’s not possible this way because LVGL automatically detects if there is anything out of the parent and if not it can’t be scrolled.

I don’t really understand the use case (why do you need to somewhere if there is nothing there) but you can trick the scrolling mechanism in 2 ways:

  1. add a small transparent object out of the screen
  2. add a large parent on which you create the object that is zoomed

Yes,Zoom in means enlarge and zoom out means “shrink” ,the btn’s lable are swapped in example.

When zooming in (rather than zooming out), Can not scroll the object from left to right or from up to down, that is, the leftmost or topmost portion of the object is out of screen and cannot be dragged it
into the viewport. When zoomed out, the entire object is in the viewport and there is no need to drag it

I correct the btn_map as follow :

static char * btn_map[] = {“zoom in”,“zoom out”,""};
lv_btnmatrix_set_map(scal_btn,btn_map);

I see. But the case is what I mentioned above: it mimics the behaviour of the web where you can scroll only to the content on the right or bottom (with LTR write direction at least).

What you can do is check if the x and/or y coordinate of the container is negative after zooming (i.e. clipped on the left/top) and set 0 instead of the negative coordinate. It keeps the enlarged object in the top left corner of it’s too large.