A very stupid/crude implementation…
static void update_slider_label(lv_obj_t *slider, bool pressed)
{
if (slider_label == NULL)
return;
uint32_t _value = lv_slider_get_value(slider);
// Cast to lv_slider_t object
lv_slider_t *slider_obj = (lv_slider_t *)slider;
// Get the Knob Area
printf("Pressing Point: %d,%d\n", slider_obj->pressed_point.x, slider_obj->pressed_point.y);
// Calculate the Center position of Knob, slider_obj->right_knob_area
int32_t knob_x = 0;
if (pressed == true)
{
knob_x = slider_obj->pressed_point.x;
}
else
{
knob_x = (slider_obj->right_knob_area.x1 + slider_obj->right_knob_area.x2) / 2;
}
int32_t knob_y = (slider_obj->right_knob_area.y1 + slider_obj->right_knob_area.y2) / 2;
printf("Slider value: %ld, Knob center: %d,%d\n", _value, knob_x, knob_y);
// Move the label to the knob position, put it 30px above the knob center
if (slider_label)
{
lv_obj_set_pos(slider_label, knob_x - (lv_obj_get_width(slider_label) / 2), knob_y - 30 - (lv_obj_get_height(slider_label) / 2));
lv_label_set_text_fmt(slider_label, "%ld", _value);
lv_obj_update_layout(slider_label);
printf("Showing label at %d,%d\n", lv_obj_get_x(slider_label), lv_obj_get_y(slider_label));
// Show label...
//lv_obj_clear_flag(slider_label, LV_OBJ_FLAG_HIDDEN);
}
else
{
printf("No slider label!\n");
}
}
void action_slider_test_pressed(lv_event_t *e)
{
lv_event_code_t code = lv_event_get_code(e);
if (code == LV_EVENT_PRESSED)
{
printf("Slider pressed: %ld\n", lv_slider_get_value(lv_event_get_target_obj(e)));
lv_obj_send_event(lv_event_get_target_obj(e), LV_EVENT_RELEASED, e);
}
else if (code == LV_EVENT_RELEASED)
{
printf("Slider released: %ld\n", lv_slider_get_value(lv_event_get_target_obj(e)));
// Get user Data
uint32_t v = (uintptr_t)lv_event_get_user_data(e);
if (lv_obj_has_flag(slider_label, LV_OBJ_FLAG_HIDDEN) == false)
{
printf("Slider released while label visible: %ld\n", lv_slider_get_value(lv_event_get_target_obj(e)));
lv_obj_add_flag(slider_label, LV_OBJ_FLAG_HIDDEN);
}
else
{
printf("Slider released while label hidden: %ld\n", lv_slider_get_value(lv_event_get_target_obj(e)));
lv_obj_remove_flag(slider_label, LV_OBJ_FLAG_HIDDEN);
}
update_slider_label(lv_event_get_target_obj(e), true);
}
else if (code == LV_EVENT_VALUE_CHANGED)
{
printf("Slider value changed: %ld\n", lv_slider_get_value(lv_event_get_target_obj(e)));
update_slider_label(lv_event_get_target_obj(e), false);
}
}
Create a label object on the current screen, and enable LV_OBJ_FLAG_HIDDEN.
You need to add this include for it to work:
#include "lvgl.h"
#include "lvgl_private.h"

Another option and myabe “better” is to subcribe to events like LV_EVENT_DRAW_MAIN… Maybe LV_EVENT_DRAW_MAIN_END that should be called when the knob is already “drawn” to get the current knob position.
And in reality you don’t even need to add the lvgl_private.h since this calculations can be made using the public API:
- You know the position and size of the slider
- You know the value of the slider
- You can “calculate” the position of the knob…
Something like this:
lv_obj_t *slider = lv_event_get_target(e);
int32_t value = lv_slider_get_value(slider);
printf("Slider value: %d\n", value);
//Print Pos and Size of slider
lv_area_t area;
lv_obj_get_coords(slider, &area);
printf("Slider pos: (%d,%d) size: (%d,%d)\n", area.x1, area.y1, lv_area_get_width(&area), lv_area_get_height(&area));
//Position the label at slider Knob position
//Calculate the knob position based on the value... don't forget to include "padding"/"margin" that may be associated to the slider / knob....
int32_t slider_width = lv_area_get_width(&area);
int32_t knob_x = area.x1 + (value * slider_width) / lv_slider_get_max_value(slider);
int32_t knob_y = (area.y1 + area.y2) / 2; // Vertically center the label
//Set the label position
lv_obj_set_pos(objects.label_slider, knob_x - lv_obj_get_width(objects.label_slider) / 2, knob_y - lv_area_get_height(&area));
//Set the label text, (don't forget to multiply the value if using a different scale...)
lv_label_set_text_fmt(objects.label_slider, "%03d", value);