Description
I have a text area that, when focused, pops up a keypad (button matrix) to allow data entry. Upon LV_EVENT_DEFOCUSED of that text area, the keypad is hidden. The “enter key” of the keypad, when clicked, confirms the new value that was entered by triggering an LV_EVENT_READY event on the text area. In the LV_EVENT_READY handler for the text area, I store the new value and then attempt to defocus the text area by calling lv_obj_remove_state(ta, LV_STATE_FOCUSED)
. The text area does indeed get visually defocused (cursor disappears), but the LV_EVENT_DEFOCUSED event handler is never called.
What MCU/Processor/Board and compiler are you using?
ESP32-2432S028R (cheap yellow display)
What LVGL version are you using?
9.2.2
What do you want to achieve?
I expect LVGL to call the LV_EVENT_DEFOCUSED event handler when the text area is defocused by calling lv_obj_remove_state(ta, LV_STATE_FOCUSED)
.
What have you tried so far?
I can manually invoke my defocus handler just after the call to remove the focused state, but I wouldn’t expect to need to since the text area is, in fact, experiencing a defocusing event. Plus, the lb_event_t
parameter isn’t accurate for the defocus handler (it is the LV_EVENT_READY event instead).
Code to reproduce
Global variable definitions omitted
void ta_Focused(lv_event_t* e) {
Serial.println("ta_Focused");
taSelected = (lv_obj_t*)lv_event_get_user_data(e);
lv_obj_update_flag(btnmtxKeypad, LV_OBJ_FLAG_HIDDEN, false);
}
void ta_Defocused(lv_event_t* e) {
Serial.println("ta_Defocused");
taSelected = nullptr;
lv_obj_update_flag(btnmtxKeypad, LV_OBJ_FLAG_HIDDEN, true);
}
void btnmtxKeypad_Click(lv_event_t * e)
{
if (taSelected == nullptr) {
return; // Should never happen, but just to be safe
}
const char* txt = lv_buttonmatrix_get_button_text(btnmtxKeypad, lv_buttonmatrix_get_selected_button(btnmtxKeypad));
if(lv_strcmp(txt, LV_SYMBOL_BACKSPACE) == 0) lv_textarea_delete_char(taSelected);
else if(lv_strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) lv_obj_send_event(taSelected, LV_EVENT_READY, NULL);
else lv_textarea_add_text(taSelected, txt);
}
void ta_Confirm(lv_event_t* e) {
Serial.println("ta_Confirm");
lv_obj_t* ta = (lv_obj_t*)lv_event_get_user_data(e);
if (ta == ui_taCompressed) {
Serial.println("Set compressed value");
} else if (ta == ui_taExtended) {
Serial.println("Set extended value");
} else
Serial.println("???");
}
lv_obj_remove_state(ta, LV_STATE_FOCUSED); // <--- PROBLEM IS HERE
// ta_Defocused(e); <-- hack that achieves the outcome I expect
}
void scrWheel_Loaded(lv_event_t* e) {
btnmtxKeypad = lv_buttonmatrix_create(lv_screen_active());
lv_obj_update_flag(btnmtxKeypad, LV_OBJ_FLAG_HIDDEN, true);
lv_obj_set_size(btnmtxKeypad, 200, 240);
lv_obj_align(btnmtxKeypad, LV_ALIGN_LEFT_MID, 0, 0);
lv_obj_add_event_cb(btnmtxKeypad, btnmtxKeypad_Click, LV_EVENT_VALUE_CHANGED, NULL);
lv_obj_remove_flag(btnmtxKeypad, LV_OBJ_FLAG_CLICK_FOCUSABLE); // Keep the text area focused on button clicks
lv_buttonmatrix_set_map(btnmtxKeypad, BUTTON_MAP_NUMERIC);
lv_obj_add_event_cb(ui_taCompressed, ta_Confirm, LV_EVENT_READY, ui_taCompressed);
lv_obj_add_event_cb(ui_taCompressed, ta_Focused, LV_EVENT_FOCUSED, ui_taCompressed);
lv_obj_add_event_cb(ui_taCompressed, ta_Defocused, LV_EVENT_DEFOCUSED, ui_taCompressed);
lv_obj_add_event_cb(ui_taExtended, ta_Confirm, LV_EVENT_READY, ui_taExtended);
lv_obj_add_event_cb(ui_taExtended, ta_Focused, LV_EVENT_FOCUSED, ui_taExtended);
lv_obj_add_event_cb(ui_taExtended, ta_Defocused, LV_EVENT_DEFOCUSED, ui_taExtended);
}