I’m using LVGL 9.2 and using the default theme. I have a button with two labels, as I have an icon font and a normal font. When the button gets focus with keypad navigation, I want to change the font color of the labels.
However, I cannot add a style to the label with LV_STATE_FOCUSED
as that is not propagated down to subcomponents of the label, probably for good reasons.
How would I go about this?
The best I have right now is to register to event listeners to the LV_EVENT_FOCUSED
and LV_EVENT_DEFOCUSED
on these buttons, and in the event listeners loop through the child objects, check if they are of class label and apply the text color directly, but this defies the whole purpose of a theme.
Some snippets:
I override the button styling based on focus:
static void new_theme_apply_cb(lv_theme_t * th, lv_obj_t * obj)
{
LV_UNUSED(th);
if(lv_obj_check_type(obj, &lv_button_class)) {
lv_obj_add_style(obj, &style_btn, LV_STATE_ANY & ~(LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY));
lv_obj_add_style(obj, &focus_style_btn, LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY);
}
}
But this doesn’t work here for the child labels.
I got it working by registering event callbacks on the button:
lv_obj_add_event_cb(btn, _app_button_state, LV_EVENT_FOCUSED, NULL);
lv_obj_add_event_cb(btn, _app_button_state, LV_EVENT_DEFOCUSED, NULL);
And just setting the style directly:
static void _app_button_state(lv_event_t *e) {
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t *button = lv_event_get_current_target(e);
int count = lv_obj_get_child_count_by_type(button, &lv_label_class);
for (int i = 0; i < count; i++) {
lv_obj_t *label = lv_obj_get_child_by_type(button, i, &lv_label_class);
if (event_code == LV_EVENT_FOCUSED) {
lv_obj_set_style_text_color(label, lv_color_white(), 0);
}
if (event_code == LV_EVENT_DEFOCUSED) {
lv_obj_set_style_text_color(label, lv_color_make(0x2C, 0x2C, 0x2C), 0);
}
}
}
This has two issues: the initial state is incorrect, which I can probably fix by adding one more event listener after initialisation or something like that. And the second is that it’s an ugly solution and deviates on how a theme extension should be made.
Is there a more elegant way of achieving this? Is it possible to have the state bubble down on request, similar to how a LV_OBJ_FLAG_EVENT_BUBBLE
pushes events up, can there be a flag LV_OBJ_FLAG_STATE_PROPAGATE
or something like that?