Right To Left Layout In container

Description

I have created a status bar for showing the time, and a number of icons to show the status of hardware (SD card, power, battery life etc…) I wish to have the icons right aligned inside a container.

Everything works perfectly, i.e. when an icon is removed they re-align. I just would like it right aligned, not left.

What LVGL version are you using?

7.8.1

What have you tried so far?

As suggested by the documentation:

If the object which applies the layout has base_dir == LV_BIDI_DIR_RTL the row will start from the right applying pad.right spaceRow top align

The Code

  statusRight = lv_cont_create(lv_scr_act(), NULL);
  lv_obj_add_style(statusRight, LV_OBJ_PART_MAIN, &statusStyle);

  lv_obj_set_height(statusRight, STATUS_BAR_HEIGHT);
  lv_obj_set_width(statusRight, LV_HOR_RES/2);
  lv_obj_align(statusRight, statusLeft, LV_ALIGN_OUT_RIGHT_TOP, 0, 0);  /*This parametrs will be used when realigned*/
  lv_cont_set_fit(statusRight, LV_FIT_NONE); // We want our container to be static. We want to align our buttons
  lv_obj_set_base_dir(statusRight, LV_BIDI_DIR_RTL);
  lv_cont_set_layout(statusRight, LV_LAYOUT_ROW_TOP);

  static lv_style_t iconStyle;
  lv_style_init(&iconStyle);
  lv_style_set_text_font(&iconStyle,LV_STATE_DEFAULT, LV_THEME_DEFAULT_FONT_TITLE);

  charge = lv_label_create(statusRight, NULL);
  lv_label_set_text(charge, "");
  // lv_obj_align_origo(charge, statusRight, LV_ALIGN_IN_RIGHT_MID, -30, -3);
  lv_obj_add_style(charge, LV_OBJ_PART_MAIN, &iconStyle);

Screenshot and/or video

I think your problem might be that the container itself is not right-aligned to the status bar. Try moving the lv_obj_align(statusRight call to after you create the icons.

Thanks @embeddedt for the suggestion. My status bar is made up of two containers that each consume half the screen. A style is applied to them to have a bottom border, which is seemless across the screen when they are aligned.

I can confirm the containers are spanning half the screen and in the right place (evidence is the grey bar across the screen). Which must mean the icons are left aligned, not right. Additonaly, when the icons appear / disappear they re-align left, not right.

I have tried as you suggested, and no changes ocurred.

Below is the full left and right container code, when appropriate I use to show and hide icons.

 if(_status.sdCardPresent){
    lv_label_set_text(sd, LV_SYMBOL_SD_CARD);
  } else {
    lv_label_set_text(sd, "");
  }
  DEBUG_DISPLAY("Setup status bar");
  static lv_style_t statusStyle;
  lv_style_init(&statusStyle);

  /*Set a background color and a radius*/
  lv_style_set_radius(&statusStyle, LV_STATE_DEFAULT, 0);
  /*Add border to the bottom+right*/
  lv_style_set_border_color(&statusStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
  lv_style_set_border_width(&statusStyle, LV_STATE_DEFAULT, 2);
  lv_style_set_border_opa(&statusStyle, LV_STATE_DEFAULT, LV_OPA_50);
  lv_style_set_border_side(&statusStyle, LV_STATE_DEFAULT, LV_BORDER_SIDE_BOTTOM);
  lv_style_set_pad_right(&statusStyle, LV_STATE_DEFAULT, 4);
  lv_style_set_pad_inner(&statusStyle, LV_STATE_DEFAULT, 4);
  lv_style_set_pad_top(&statusStyle, LV_STATE_DEFAULT, 2);

  statusLeft = lv_cont_create(lv_scr_act(), NULL);
  lv_obj_add_style(statusLeft, LV_OBJ_PART_MAIN, &statusStyle);

  lv_obj_set_height(statusLeft, STATUS_BAR_HEIGHT);
  lv_obj_set_width(statusLeft, LV_HOR_RES/2);
  lv_obj_align(statusLeft, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);  /*This parametrs will be used when realigned*/
  lv_cont_set_fit(statusLeft, LV_FIT_NONE); // We want our container to be static. We want to align our buttons

  time = lv_label_create(statusLeft, NULL);
  lv_label_set_text(time, "");
  lv_obj_align_origo(time, statusLeft, LV_ALIGN_IN_LEFT_MID, 4, 0);

  statusRight = lv_cont_create(lv_scr_act(), NULL);
  lv_obj_add_style(statusRight, LV_OBJ_PART_MAIN, &statusStyle);

  lv_obj_set_height(statusRight, STATUS_BAR_HEIGHT);
  lv_obj_set_width(statusRight, LV_HOR_RES/2);
  lv_cont_set_fit(statusRight, LV_FIT_NONE); // We want our container to be static. We want to align our buttons
  lv_obj_set_base_dir(statusRight, LV_BIDI_DIR_RTL);
  lv_cont_set_layout(statusRight, LV_LAYOUT_ROW_TOP);
  lv_obj_align(statusRight, statusLeft, LV_ALIGN_OUT_RIGHT_TOP, 0, 0);  /*This parametrs will be used when realigned*/

  static lv_style_t iconStyle;
  lv_style_init(&iconStyle);
  lv_style_set_text_font(&iconStyle,LV_STATE_DEFAULT, LV_THEME_DEFAULT_FONT_TITLE);

  charge = lv_label_create(statusRight, NULL);
  lv_label_set_text(charge, "");
  // lv_obj_align_origo(charge, statusRight, LV_ALIGN_IN_RIGHT_MID, -30, -3);
  lv_obj_add_style(charge, LV_OBJ_PART_MAIN, &iconStyle);

  sd = lv_label_create(statusRight, NULL);
  lv_label_set_text(sd,"");
  // lv_obj_align_origo(sd, statusRight, LV_ALIGN_IN_RIGHT_MID, -50, -3);
  lv_obj_add_style(sd, LV_OBJ_PART_MAIN, &iconStyle);

  usb = lv_label_create(statusRight, NULL);
  lv_label_set_text(usb,"");
  // lv_obj_align_origo(usb, statusRight, LV_ALIGN_IN_RIGHT_MID, -80, -3);
  lv_obj_add_style(usb, LV_OBJ_PART_MAIN, &iconStyle);

  eth = lv_label_create(statusRight, NULL);
  lv_label_set_text(eth,"");
  // lv_obj_align_origo(eth, statusRight, LV_ALIGN_IN_RIGHT_MID, -110, -3);
  lv_obj_add_style(eth, LV_OBJ_PART_MAIN, &iconStyle);

  wifi = lv_label_create(statusRight, NULL);
  lv_label_set_text(wifi,"");
  // lv_obj_align_origo(wifi, statusRight, LV_ALIGN_IN_RIGHT_MID, -140, -3);
  lv_obj_add_style(wifi, LV_OBJ_PART_MAIN, &iconStyle);

I’ve tried your code (with minor modifications for missing globals, etc.) and strangely it works fine for me. This is what I’m using to test. I have made statusRight have a red background to ease debugging.

   static lv_style_t statusStyle;
  lv_style_init(&statusStyle);

  /*Set a background color and a radius*/
  lv_style_set_radius(&statusStyle, LV_STATE_DEFAULT, 0);
  /*Add border to the bottom+right*/
  lv_style_set_border_color(&statusStyle, LV_STATE_DEFAULT, LV_COLOR_BLACK);
  lv_style_set_border_width(&statusStyle, LV_STATE_DEFAULT, 2);
  lv_style_set_border_opa(&statusStyle, LV_STATE_DEFAULT, LV_OPA_50);
  lv_style_set_border_side(&statusStyle, LV_STATE_DEFAULT, LV_BORDER_SIDE_BOTTOM);
  lv_style_set_pad_right(&statusStyle, LV_STATE_DEFAULT, 4);
  lv_style_set_pad_inner(&statusStyle, LV_STATE_DEFAULT, 4);
  lv_style_set_pad_top(&statusStyle, LV_STATE_DEFAULT, 2);

  lv_obj_t * statusLeft = lv_cont_create(lv_scr_act(), NULL);
  lv_obj_add_style(statusLeft, LV_OBJ_PART_MAIN, &statusStyle);

  lv_obj_set_height(statusLeft, STATUS_BAR_HEIGHT);
  lv_obj_set_width(statusLeft, LV_HOR_RES/2);
  lv_cont_set_fit(statusLeft, LV_FIT_NONE); // We want our container to be static. We want to align our buttons

  lv_obj_align(statusLeft, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);  /*This parametrs will be used when realigned*/

  lv_obj_t * time = lv_label_create(statusLeft, NULL);
  lv_label_set_text(time, "");
  lv_obj_align_origo(time, statusLeft, LV_ALIGN_IN_LEFT_MID, 4, 0);

  lv_obj_t * statusRight = lv_cont_create(lv_scr_act(), NULL);
  lv_obj_add_style(statusRight, LV_OBJ_PART_MAIN, &statusStyle);
  lv_obj_set_style_local_bg_color(statusRight, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED);

  lv_obj_set_height(statusRight, STATUS_BAR_HEIGHT);
  lv_obj_set_width(statusRight, LV_HOR_RES/2);
  lv_cont_set_fit(statusRight, LV_FIT_NONE); // We want our container to be static. We want to align our buttons
  lv_obj_set_base_dir(statusRight, LV_BIDI_DIR_RTL);
  lv_cont_set_layout(statusRight, LV_LAYOUT_ROW_TOP);
  lv_obj_align(statusRight, statusLeft, LV_ALIGN_OUT_RIGHT_TOP, 0, 0);  /*This parametrs will be used when realigned*/

  static lv_style_t iconStyle;
  lv_style_init(&iconStyle);
  lv_style_set_text_font(&iconStyle,LV_STATE_DEFAULT, LV_THEME_DEFAULT_FONT_TITLE);

  lv_obj_t * charge = lv_label_create(statusRight, NULL);
  lv_label_set_text(charge, "");
  // lv_obj_align_origo(charge, statusRight, LV_ALIGN_IN_RIGHT_MID, -30, -3);
  lv_obj_add_style(charge, LV_OBJ_PART_MAIN, &iconStyle);

  lv_obj_t * sd = lv_label_create(statusRight, NULL);
  lv_label_set_text(sd, LV_SYMBOL_SD_CARD);
  // lv_obj_align_origo(sd, statusRight, LV_ALIGN_IN_RIGHT_MID, -50, -3);
  lv_obj_add_style(sd, LV_OBJ_PART_MAIN, &iconStyle);

  lv_obj_t * usb = lv_label_create(statusRight, NULL);
  lv_label_set_text(usb, LV_SYMBOL_USB);
  // lv_obj_align_origo(usb, statusRight, LV_ALIGN_IN_RIGHT_MID, -80, -3);
  lv_obj_add_style(usb, LV_OBJ_PART_MAIN, &iconStyle);

  lv_obj_t * eth = lv_label_create(statusRight, NULL);
  lv_label_set_text(eth, LV_SYMBOL_BLUETOOTH);
  // lv_obj_align_origo(eth, statusRight, LV_ALIGN_IN_RIGHT_MID, -110, -3);
  lv_obj_add_style(eth, LV_OBJ_PART_MAIN, &iconStyle);

  lv_obj_t * wifi = lv_label_create(statusRight, NULL);
  lv_label_set_text(wifi, LV_SYMBOL_WIFI);
  // lv_obj_align_origo(wifi, statusRight, LV_ALIGN_IN_RIGHT_MID, -140, -3);
  lv_obj_add_style(wifi, LV_OBJ_PART_MAIN, &iconStyle);

I am calling lv_label_set_text(sd, "") a few seconds later and the remaining icons appear to shift to the right.

Thanks for your time @embeddedt, i tried your code and to no avail. It got me thinking what could be different, and took a look at the lv_conf.h file. I feel slightly foolish.

RTL support is default as off in the config, maybe a note in the documentation could help others in the future.

#define LV_USE_BIDI     0 <-- Defaults as OFF, changed to 1

Works perfectly now :star_struck:, thanks.

Done. https://github.com/lvgl/lvglhttps://github.com/lvgl/lvgl/commit/f0c52b35112e7734d52a2e25101e0d58ff50cea7

The change will be reflected when the documentation is rebuilt.

1 Like