lvgl / lv_apps

Ready to use UIs and high level components for applications
MIT License
11 stars 12 forks source link

Does not auto scroll to the out-of-screen items when using encoder or keypads. #8

Closed HamidSaffari closed 4 years ago

HamidSaffari commented 4 years ago

Hi, Pal. How can I shift menu items to see out of screen items when I'm using encoder or keypads as inputs? because it does not do that automatically even can selected the not-in-screen items.

  lv_indev_drv_t indev_drv;
  lv_indev_drv_init(&indev_drv);             /*Descriptor of a input device driver*/
  indev_drv.type = LV_INDEV_TYPE_ENCODER /* LV_INDEV_TYPE_POINTER */;    /*Touch pad is a pointer-like device*/
  indev_drv.read_cb = read_encoder /* my_touchpad_read */;      /*Set your driver function*/
  emulated_kp_indev = lv_indev_drv_register(&indev_drv);         /*Finally register the driver*/

  /*Create an object group*/
  group = lv_group_create();
  /*Assig the input device(s) to the created group*/
  lv_indev_set_group(emulated_kp_indev, group);
  lv_settings_set_group(group);
kisvegabor commented 4 years ago

Hi,

I've just fixed it. Can you confirm it works correctly now?

HamidSaffari commented 4 years ago

Thanks, it scrolling and focusing but still has two problems:

  1. When selecting one having-child-item from the first root menu to go to child page after rendering child page, when you changing the encoder to select item, the CPU halts and hangs. It has something to do with lv_list_focus(<obj>, LV_ANIM_ON); because by removing it it works.
  2. When coming back from root menu to the home page it has no group any more to select because home page not creating again to add groups again. Also it would be better to implement exit callback function to let us do something as soon as menu removed, like add objects to group again.
HamidSaffari commented 4 years ago

By home page I meant this page:

photo_2020-04-28_03-29-06

kisvegabor commented 4 years ago

I've pushed a fix, can you try it?

HamidSaffari commented 4 years ago

Previous problems resolved but Menu does not remove objects of home page out of group when activates.

kisvegabor commented 4 years ago

Menu does not remove objects of home page out of group when activates.

Sorry, but I don't understand. Please, describe it in more detail.

HamidSaffari commented 4 years ago
void setup void{
  lv_indev_drv_t indev_drv;
  lv_indev_drv_init(&indev_drv);   
  indev_drv.type = LV_INDEV_TYPE_ENCODER ;
  indev_drv.read_cb = read_encoder;
  emulated_kp_indev = lv_indev_drv_register(&indev_drv);  

  group = lv_group_create();
  lv_indev_set_group(emulated_kp_indev, group);
  lv_settings_set_group(group);

  create_home_page(lv_disp_get_scr_act(NULL));
  create_settings_Menu();
}

static void create_home_page(lv_obj_t * parent){
    dim_slider = lv_slider_create(parent, NULL);
    lv_group_add_obj(group, dim_slider); 

    lv_obj_t * btn_minus = lv_btn_create(parent, NULL);
    lv_group_add_obj(group, btn_minus); 
}

void create_settings_Menu(void)
{
    lv_obj_t *btn = lv_settings_create(&root_item, root_event_cb);
    lv_obj_align(btn, NULL, LV_ALIGN_IN_TOP_RIGHT, 0, 0);
    lv_group_add_obj(group, btn); 
    lv_settings_set_max_width(lv_obj_get_width(lv_scr_act())/1.3);
}

As you can see I added "dim_slider" and "btn_minus" from "home_page" to the group too. So when menu activates those objects must deleted/disabled from the group and when menu disappeared those objects must enable/add to the group again. but it wont and those objects remains in the group when menu actives in any level.

HamidSaffari commented 4 years ago

My hardware photo_2020-04-29_18-01-02

HamidSaffari commented 4 years ago

I can do that by removing those objects from the group at the idle-off(activation) of the menu and add again at the idle-on, but there is no callback for idle-on/off. am I right?

HamidSaffari commented 4 years ago

For removing home objects from menu at beginning I simply added lv_group_remove_all_objs(group); in my main pogrom but cannot execute proper callback to let me add them again at exit. for that I tried to add another event to root_event_cb LV_EVENT_REFRESH and added lv_event_send_func(root_event_cb, NULL, LV_EVENT_REFRESH, NULL); to lv_settings library but it halts CPU when trying to exit menu. here is my modification:

in main.cpp:

static void root_event_cb(lv_obj_t * btn, lv_event_t e)
{
    (void)btn;  /*Unused*/
    /*If the root element was clicked or asks for create a main menu*/
    if(e == LV_EVENT_CLICKED) {
      lv_group_remove_all_objs(group); // added this
        lv_settings_item_t * act_item = (lv_settings_item_t *)lv_event_get_data();
        lv_settings_open_page(act_item, main_menu_event_cb);
    }
     else if(e == LV_EVENT_REFRESH) { // added this
          lv_group_add_obj(group, dim_slider); // added this
                  lv_group_add_obj(group, btn_minus); // added this
      }
}

and in lv_setting.c:

static void root_event_cb(lv_obj_t * btn, lv_event_t e)
{
    if(e == LV_EVENT_CLICKED    || e == LV_EVENT_REFRESH) { /*I edited this and add || e==LV_EVENT_REFRESH*/
        root_ext_t * ext = lv_obj_get_ext_attr(btn);
        /*Call the button's event handler to create the menu*/
        lv_event_send_func(ext->event_cb, NULL, e,  ext->item);
    }
}

static void header_back_event_cb(lv_obj_t * btn, lv_event_t e)
{
    (void) btn; /*Unused*/
    if(e != LV_EVENT_CLICKED) return;
    lv_obj_t * old_menu_cont = act_cont;
    /*Delete the current item form the history. The goal is the previous.*/
    histroy_t * act_hist;
    act_hist = lv_ll_get_head(&history_ll);
    if(act_hist) {
        lv_ll_rem(&history_ll, act_hist);
        lv_mem_free(act_hist);
        /*Get the real previous item and open it*/
        histroy_t * prev_hist =  lv_ll_get_head(&history_ll);
        if(prev_hist) {
            /* Create the previous menu.
             * Remove it from the history because `lv_settings_create_page` will add it again */
            lv_ll_rem(&history_ll, prev_hist);
            lv_settings_open_page( prev_hist->item, prev_hist->event_cb);
            lv_mem_free(prev_hist);
        }
        else {
            /*No previous menu, so no main container*/
            act_cont = NULL;
            if(group) lv_group_add_obj(group, menu_btn);
          lv_event_send_func(root_event_cb, NULL, LV_EVENT_REFRESH, NULL);// I added this
        }
    }
.
.
.
}

Now what is the problem?

kisvegabor commented 4 years ago

I'm also thinking about a similar solution. I've pushed fix which sends LV_EVENT_CANCEL when the settings is closed. 4a6e144

HamidSaffari commented 4 years ago

Thanks Gabor, everything works fine now. here is my root_even_callback in main.c for helping viewers:

void setup (){
  lv_indev_drv_t indev_drv;
  lv_indev_drv_init(&indev_drv);   
  indev_drv.type = LV_INDEV_TYPE_ENCODER ;
  indev_drv.read_cb = read_encoder;
  emulated_kp_indev = lv_indev_drv_register(&indev_drv);  
  group = lv_group_create();
  lv_indev_set_group(emulated_kp_indev, group);
  lv_settings_set_group(group);
  create_home_page(lv_disp_get_scr_act(NULL));
  create_settings_Menu();
}

static void create_home_page(lv_obj_t * parent){
    dim_slider = lv_slider_create(parent, NULL);
    lv_group_add_obj(group, dim_slider); 
    btn_minus = lv_btn_create(parent, NULL);
    lv_group_add_obj(group, btn_minus); 
}

static void create_settings_Menu(void)
{
    lv_obj_t *btn = lv_settings_create(&root_item, root_event_cb);
    lv_obj_align(btn, NULL, LV_ALIGN_IN_TOP_RIGHT, 0, 0);
    lv_group_add_obj(group, btn); 
    lv_settings_set_max_width(lv_obj_get_width(lv_scr_act())/1.3);
}
static void root_event_cb(lv_obj_t * btn, lv_event_t e)
{
    (void)btn;  /*Unused*/
    /*If the root element was clicked or asks for create a main menu*/
    if(e == LV_EVENT_CLICKED) {
    lv_group_remove_all_objs(group);
        /*Get the caller item*/
        lv_settings_item_t * act_item = (lv_settings_item_t *)lv_event_get_data();
        lv_settings_open_page(act_item, main_menu_event_cb);
    }
    else if(e == LV_EVENT_CANCEL) {
    lv_group_add_obj(group, dim_slider); 
    lv_group_add_obj(group, btn_plus);
    lv_group_add_obj(group, btn_minus);
    }
}

Just one minor problem: when scrolling thru one menu pages and then comeback to the first item of that page it has not shown completely and it's first line hides under the menu title:

photo_2020-05-02_14-52-17 photo_2020-05-02_14-53-00

This thing not happened on the root menu page but children.

kisvegabor commented 4 years ago

I've pushed a fix.

HamidSaffari commented 4 years ago

I know you corrected not-scrolling and now it focused but now in children pages when you go down to bottom item and then go back to first one again it does not show the first line of first item completely. like picture:

kisvegabor commented 4 years ago

:man_facepalming: I haven't pushed the commit... Sorry. It should work now.

HamidSaffari commented 4 years ago

Yes man, everything's alright now. You rock Gabor, keep it coming.

kisvegabor commented 4 years ago

Awesome! :slightly_smiling_face:

I close this issue then.