How to self align an object with flexbox?


I want to align this object to the right.
The two objects are children of the container that has the flex layout.
I can’t align the second object (object highlighted in the image above) to the right.

Which version of LVGL you use ?

LVGL v8.1 (master)

As far as I understand you should use flex alignment. But I didn’t use v8, so maybe someone else can explain this.

If I use flexible alignment, I have to align all children of the container (lv_obj_set_style_flex_cross_place(cont, LV_FLEX_ALIGN_END, 0)) and I just want to align the second object to the left (LV_FLEX_ALIGN_END).

Align-self is not supported by LVGL at this moment.

As workaround I suggest this:

  1. Create a width=100% wrapper object for each text box
  2. Align these wrappers into a column with flex
  3. Set LV_ALIGN_TOP_LEFT/RIGHT on the text boxes.
3 Likes

Thanks @kisvegabor!

Kinda running into the same challenge here (same in LVGL v9.1.0).

Digging through the docs, I came across the “LV_OBJ_FLAG_IGNORE_LAYOUT”, which seems like it’s specifically intended for this sort of UI functionality.

In testing, ADDing said flag does not make any difference:

lv_obj_add_flag(lv_object, LV_OBJ_FLAG_IGNORE_LAYOUT);

but in the docs, it’s listed as

LV_OBJ_FLAG_IGNORE_LAYOUT Make the object positionable by the layouts

This seems to imply that if the flag is SET, that the object will be controlled by the container layout–seemingly completely opposite to the naming of the flag.

REMOVING the flag results in the object now being roughly centered in the container…but the object still ignores any and all absolute positioning calls (i.e. lv_obj_set_pos, lv_obj_set_align, etc.)

looks like the above solution (lv_obj wrapper for the flex positioning) is still the functional requisite.

I’ve just opened a PR to fix the typo in the docs: docs(obj): fix typo of LV_OBJ_FLAG_IGNORE_LAYOUT by kisvegabor · Pull Request #6713 · lvgl/lvgl · GitHub

Thank for mentioning it.

So now I’m confused…

In my experience, setting the “LV_OBJ_FLAG_IGNORE_LAYOUT” flag does not make any difference in a flex layout. CLEARING the flag resulted in the object no longer being bound to the flex layout–but it still ignores all positioning/alignment commands. (I don’t want the object to be “floated”; the goal is to align it to the bottom of the container.)

Putting the “flex” objects in their own container did provide a solution of sorts: the table can then be neatly aligned to the bottom of the main container.

Hello,

First off. I don’t mean to play internet janitor but please note that this topic is years old and it might be a better idea create a new topic regarding your specific issue this if this discussion goes on for longer.

Could you perhaps share your code where this goes wrong? I have a properly working example of this with just labels:

static lv_obj_t* showResultScreen(void)
{
    lv_obj_t* screen = lv_obj_create(lv_screen_active());
    if (screen == NULL) { return NULL; }

    lv_obj_set_size(screen, DISP_HOR_RES, DISP_VER_RES); // <- cover the whole screen
    lv_obj_set_pos(screen, 0, 0);
    lv_obj_add_style(screen, &Style_Square, LV_PART_MAIN); // <- this style just removed borders etc.
    lv_obj_set_style_pad_all(screen, 10, LV_PART_MAIN);
    lv_obj_set_style_bg_opa(screen, LV_OPA_TRANSP, LV_PART_MAIN);

    lv_obj_set_flex_flow(screen, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(screen, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);

    lv_obj_t* labConsumption = lv_label_create(screen);
    if (labConsumption != NULL)
    {
        lv_label_set_text(labConsumption, "Description");
        lv_obj_t* labConsumptionVal = lv_label_create(screen);
        if (labConsumptionVal != NULL)
        {
            lv_label_set_text_fmt(labConsumptionVal, "value");
        }
    }

    lv_obj_t* labPressure = lv_label_create(screen);
    if (labPressure != NULL)
    {
        lv_label_set_text(labPressure,  "Description");
        lv_obj_t* labPressureVal = lv_label_create(screen);
        if (labPressureVal != NULL)
        {
            ui_util_SetLabelValue(labPressureVal, "value");
        }

        lv_obj_add_flag(labPressure, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK);
    }

    lv_obj_t* labResult = lv_label_create(screen);
    if (labResult != NULL)
    {
        lv_label_set_text(labResult,  "Description");
        lv_obj_t* labResultVal = lv_label_create(screen);
        if (labResultVal != NULL)
        {
            ui_util_SetLabelValue(labResultVal, "value");
        }

        lv_obj_add_flag(labResult, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK);
    }


    lv_obj_t* labError = lv_label_create(screen);
    if (labError != NULL)
    {
        lv_label_set_text("some error");
        lv_obj_set_style_text_color(labError, lv_color_hex(UI_COL_RED), LV_PART_MAIN);
        lv_obj_add_flag(labError, LV_OBJ_FLAG_IGNORE_LAYOUT);
        lv_obj_align(labError, LV_ALIGN_BOTTOM_MID, 0, -20);
    }

    return screen;
}

My labError here gets aligned as expected, all previous labels also do (they use the flex layout specified).

1 Like

Please do so! Right now we don’t have enough bandwidth for an official presence on the forum, so we rely on the great community members like you. So thank you for the amazing work that you are doing!

It’s on my radar to ask someone in our team spend at least 1-2 hours per day here, but realistically we can have capacity fort it only next year.

Understood. In my case, I try to “tag onto” existing issues that are effectively identical to what I’m experiencing…although yes, that might not be the most ideal use. Part of what bugs me especially about the LVGL forum, is that a LOT of search results come back for LVGL v6 or v7–and due to the significant redesigns of the commands, said topics are of no value with LVGL v9. IMO having continuity with “identical issues” across the different versions in the same thread might be of potentially more value to the community.

I’ll have to experiment a bit, and/or create a “minimally reproducible example”. In my case, I was trying to align an “lv_table” to the bottom of an “lv_win”–and it either was bound by the “lv_win” flex rules, or was stuck in the center of the “lv_win” and couldn’t be moved with absolute positioning or align calls. (LVGL 9.1.0.) Not sure why…but putting the “flex” rules onto an “lv_obj” inside the “lv_win” allowed absolute positioning of the “lv_table” inside the “lv_win”.

Hello,

All right, I understand your reasoning for posting it here.

I think the issue you are having mainly lies in the use of the lv_win object, this might be a bit restrictive in its use. The window object does not really seem to have a defined bottom as it resizes with the contents of the content area. See the documentation: Window (lv_win) — LVGL documentation

However I think you can manually set the size of the content area like so:

lv_obj_t* win = lv_win_create(lv_screen_active())
lv_obj_t* cont = lv_win_get_content(win);

lv_obj_set_size(cont, WIDTH, HEIGHT);

/* Now align table to bottom */

lv_obj_t* table = lv_table_create(cont);
lv_obj_add_flag(table, LV_OBJ_FLAG_IGNORE_LAYOUT);
lv_obj_align(table, LV_ALIGN_BOTTOM_MID, 0, 0);

I did this from the top of my head so some of these function/macro names may not be completely correct but you get the idea.

Hope this helps

when i try this workaround the object wrapper width covers the whole flex container width . only the text moved to right/left


am i missing anything ?