Floating button

Description

Floating button

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

Lvgl Simulator on windows

What do you want to achieve?

I have a terminal page in a tabview that scrolls down.
Now I want to have a floating button on top that vcan clear the screen.

What have you tried so far?

Add a button to the tab. It scrolls down with the text.

Screenshot and/or video

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

You should create the button as a child of the page’s parent, and position it relative to the page with lv_obj_align(btn, page, LV_ALIGN_IN_TOP_RIGHT, 0, 0) (for example).

Thanks for you reply.

As I understand from the docs; a page consists of two containers on top of each other.
from the source I see that a tab in the tabview is a page.
The pages parent is the background container? Then I put the label on the foreground conainer and that should make the label scrollable and the button fixed.

when I try that I see no button;

void test_gui() {
	lv_coord_t hres = lv_disp_get_hor_res(NULL);
	lv_coord_t vres = lv_disp_get_ver_res(NULL);

	lv_obj_t* tv = lv_tabview_create(lv_disp_get_scr_act(NULL), NULL);
	lv_obj_set_size(tv, hres, vres);
	lv_obj_t* tab1 = lv_tabview_add_tab(tv, "Write");
	lv_obj_t* tab2 = lv_tabview_add_tab(tv, "List");
	lv_obj_t* tab3 = lv_tabview_add_tab(tv, "Terminal");

	/*Create a label for the text of the terminal*/
	label = lv_label_create(tab3, NULL);
	lv_label_set_long_mode(label, LV_LABEL_LONG_BREAK);
	lv_obj_set_width(label, lv_obj_get_width(tab3));
	//lv_label_set_static_text(label, txt_log);               /*Use the text array directly*/

	/*Create a clear button*/
	clr_btn = lv_btn_create(tab3->par, NULL);
	lv_btn_set_fit(clr_btn, LV_FIT_TIGHT);
	lv_obj_t* btn_label = lv_label_create(clr_btn, NULL);
	lv_label_set_text(btn_label, "Clear");
	lv_obj_align(clr_btn, tab3, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
}

image

When I create it not with tab3->par the button moves arrount with the scrolling of the label;

	/*Create a clear button*/
	clr_btn = lv_btn_create(tab3, NULL);
	lv_btn_set_fit(clr_btn, LV_FIT_TIGHT);
	lv_obj_t* btn_label = lv_label_create(clr_btn, NULL);
	lv_label_set_text(btn_label, "Clear");
	lv_obj_align(clr_btn, tab3, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);

image

You should not be accessing members of the lv_obj_t structure directly, unless the equivalent API does not exist. You should use the provided API functions (i.e. lv_obj_get_parent).

In your case creating it as a child of the tabview itself (not one of its tabs) should work, but you will need to position it below the buttons. I think you could do that with the following code (untested):

/* `tabview` is the tabview itself, not a tab */
lv_obj_t * btn = lv_btn_create(tabview, NULL);
lv_tabview_ext_t * tv_ext = lv_obj_get_ext_attr(tabview);
lv_obj_align(btn, tv_ext->btns, LV_ALIGN_OUT_BOTTOM_RIGHT, 0, 0);

@embeddedt Thanks for your your answer, but that makes the button appear on all tabs.

It only needs to be shown on the last tab, tab3.
So on tab3 is a label that should scroll down when overflown, and on top of the tab at the bottom is the clear button. When scrolling the text in the label the button should remain in the bottom right corner.

Now what I did was use a page on top of the tab3. that way I got it working. But is seems to me it should be possible to make this work with only the tab3.

void test_gui() {
	lv_coord_t hres = lv_disp_get_hor_res(NULL);
	lv_coord_t vres = lv_disp_get_ver_res(NULL);

	lv_obj_t* tv = lv_tabview_create(lv_disp_get_scr_act(NULL), NULL);
	lv_obj_set_size(tv, hres, vres);
	lv_obj_t* tab1 = lv_tabview_add_tab(tv, "Write");
	lv_obj_t* tab2 = lv_tabview_add_tab(tv, "List");
	lv_obj_t* tab3 = lv_tabview_add_tab(tv, "Terminal");
	lv_page_set_sb_mode(tab3, LV_SB_MODE_OFF);

	lv_obj_t* page = lv_page_create(tab3,NULL);
	lv_obj_set_size(page, lv_obj_get_width(tab3), lv_obj_get_height(tab3));
	//lv_page_set_sb_mode(page, LV_SB_MODE_OFF);
	lv_obj_align(page, tab3, LV_ALIGN_CENTER, 0, 0);
	lv_page_set_scrl_layout(page, LV_LAYOUT_COL_L);

	/*Create a label for the text of the terminal*/
	label = lv_label_create(page, NULL);
	lv_label_set_long_mode(label, LV_LABEL_LONG_BREAK);
	//lv_obj_set_width(label, lv_obj_get_width(tab3));
	lv_label_set_static_text(label, "1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n");

	/*Create a clear button*/
	clr_btn = lv_btn_create(tab3, NULL);
	lv_btn_set_fit(clr_btn, LV_FIT_TIGHT);
	lv_obj_t* btn_label = lv_label_create(clr_btn, NULL);
	lv_label_set_text(btn_label, "Clear");
	lv_obj_align(clr_btn, tab3, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
}

image

You can do it by using lv_obj_set_protect()

lv_obj_t * label ;
lv_obj_t * clr_btn;
void test_gui() {
    lv_coord_t hres = lv_disp_get_hor_res(NULL);
    lv_coord_t vres = lv_disp_get_ver_res(NULL);

    lv_obj_t* tv = lv_tabview_create(lv_disp_get_scr_act(NULL), NULL);
    lv_obj_set_size(tv, hres, vres);
    lv_obj_t* tab1 = lv_tabview_add_tab(tv, "Write");
    lv_obj_t* tab2 = lv_tabview_add_tab(tv, "List");
    lv_obj_t* tab3 = lv_tabview_add_tab(tv, "Terminal");
    lv_page_set_sb_mode(tab3, LV_SB_MODE_OFF);

    lv_page_set_scrl_layout(tab3, LV_LAYOUT_COL_L);
//    lv_page_set_scrl_fit()

    /*Create a label for the text of the terminal*/
    label = lv_label_create(tab3, NULL);
    lv_label_set_long_mode(label, LV_LABEL_LONG_BREAK);
    //lv_obj_set_width(label, lv_obj_get_width(tab3));
    lv_label_set_static_text(label, "1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n");

    /*Create a clear button*/
    clr_btn = lv_btn_create(tab3, NULL);
    lv_btn_set_fit(clr_btn, LV_FIT_TIGHT);
    lv_obj_t* btn_label = lv_label_create(clr_btn, NULL);
    lv_label_set_text(btn_label, "Clear");
    
    /* The children created on the page are automatically moved to the scrollable object.
     * So protect the button them from parent change and put the object back to the tab (page) */
    lv_obj_set_protect(clr_btn, LV_PROTECT_PARENT);
    lv_obj_set_parent(clr_btn, tab3);
    
    lv_obj_align(clr_btn, tab3, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
}
3 Likes

That is what I was looking for.

@embeddedt and @kisvegabor thanks for your help and the great framework.

1 Like