Cooperation between textarea and keyboard

Important: unclear posts may not receive useful answers.

Before posting

  • Get familiar with Markdown to format and structure your post
  • Be sure to update lvgl from the latest version from the master branch.
  • Be sure you have checked the relevant part of the documentation.
  • If applicable use the Simulator to eliminate hardware related issues.

Delete this section if you read and applied the mentioned points.

Description

I want to do some cooperation between textarea and keyboard, such as when click textarea, it shows keyboard, then when I clicked the LV_SYMBOL_KEYBOARD hide the keyboard and the textarea cursor. I found some problems in my code.

1、how to hide textarea cursor? It’s not so convenient compare with V6.0.2
2、If I simply create a keyboard, then I clicked the LV_SYMBOL_KEYBOARD, it can’t hide the keyboard.
3、In my code, ta_event_cb. When I try to debug my code, once I clicked the textarea, It seems to run it in ta_event_cb again and again, but the lv_event_code_t code is different everytime.
4、If I add textarea through LV_EVENT_CLOSE not through LV_EVENT_ALL,then I found if I click one textarea, the keyboard will close, then I clicked this textarea again, it will not run into ta_event_cb again, when I click another textaren it run it in ta_event_cb again.

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

ARM335X

What LVGL version are you using?

V8.0.2

What do you want to achieve?

What have you tried so far?

Code to reproduce

Add a code snippet which can run in the simulator. It should contain only the relevant code that compiles without errors when separated from your main code base.

The code block(s) should be formatted like:

static void ta_event_cb(lv_event_t * e)
    {
        lv_event_code_t code = lv_event_get_code(e);
        lv_obj_t * ta = lv_event_get_target(e);
        if(code == LV_EVENT_CLICKED || code == LV_EVENT_FOCUSED) {
            /*Focus on the clicked text area*/
            if(g_keyboard != NULL)
                {
                lv_obj_clear_flag(g_keyboard, LV_OBJ_FLAG_HIDDEN);
                    lv_keyboard_set_textarea(g_keyboard, ta);
                }
        }

        else if(code == LV_EVENT_READY) {
            LV_LOG_USER("Ready, current text: %s", lv_textarea_get_text(ta));
        }
    }

static void KeyboardEventCB(lv_event_t* event)
{
//    lv_keyboard_def_event_cb(event);
//
    lv_event_code_t code = lv_event_get_code(event);
//
//    lv_obj_t* ta_of_kb = lv_keyboard_get_textarea(g_keyboard);
//
    if(code == LV_EVENT_CANCEL)
    {
//        lv_textarea_t * ta = (lv_textarea_t *)ta_of_kb;
//        ta->cursor.show = 0;
        lv_obj_add_flag(g_keyboard, LV_OBJ_FLAG_HIDDEN);
    }
}

void CreateKeyboard(lv_obj_t* parent, lv_coord_t w, lv_coord_t h)
{
    g_keyboard = lv_keyboard_create(parent);

   
    lv_obj_set_size(g_keyboard, w, h);
    lv_obj_align_to(g_keyboard, parent, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
  
//    lv_obj_add_event_cb(g_keyboard, KeyboardEventCB, LV_EVENT_CANCEL, NULL);

  
//    lv_obj_add_flag(g_keyboard, LV_OBJ_FLAG_HIDDEN);
}


int main()
{
    CreateKeyboard(lv_scr_act(), 940, 150);

    lv_obj_clear_flag(g_keyboard, LV_OBJ_FLAG_HIDDEN);

    lv_obj_t * text_ta = lv_textarea_create(lv_scr_act());
    lv_textarea_set_one_line(text_ta, true);
    lv_textarea_set_password_mode(text_ta, false);
    lv_obj_set_width(text_ta, lv_pct(40));
    lv_obj_add_event_cb(text_ta, ta_event_cb, LV_EVENT_ALL, NULL);
    lv_obj_align_to(text_ta, NULL, LV_ALIGN_TOP_LEFT, 0, 60);

    lv_obj_t * text_ta1 = lv_textarea_create(lv_scr_act());
    lv_textarea_set_one_line(text_ta1, true);
    lv_textarea_set_password_mode(text_ta1, false);
    lv_obj_set_width(text_ta1, lv_pct(40));
    lv_obj_add_event_cb(text_ta1, ta_event_cb, LV_EVENT_ALL, NULL);
    lv_obj_align_to(text_ta1, NULL, LV_ALIGN_TOP_RIGHT, 0, 60);
}

Screenshot and/or video

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

I optimize my code , then it can sovle some problems, code is shown below.
the textarea cursor may exists a bit problem while I debug the code.
If the ta_event_cb code without /*Remedial measures*/ two lines codes, When I first run into ta_event_cb, the cursor blink well; then I clear the state LV_STATE_FOCUSED and run into again, it show cursor but not blink. I speculate the widget textarea may exist this problem when change state LV_STATE_FOCUSED. So I add the /*Remedial measures*/ codes to avoid this, just want to call the static function start_cursor_blink

static void keyboard_event_cb(lv_event_t* e)
{
	lv_event_code_t code = lv_event_get_code(e);

	if (code == LV_EVENT_CANCEL)
	{
		lv_obj_t* ta = lv_keyboard_get_textarea(keyboard);
		lv_obj_clear_state(ta, LV_STATE_FOCUSED);
		lv_obj_add_flag(keyboard, LV_OBJ_FLAG_HIDDEN);

    	lv_state_t state = lv_obj_get_state(ta);
    	printf("textarea state is %04x", state);
	}
}

static void ta_event_cb(lv_event_t* e)
{
	lv_event_code_t code = lv_event_get_code(e);
	lv_obj_t * ta = lv_event_get_target(e);
    if(code == LV_EVENT_CLICKED || code == LV_EVENT_FOCUSED)
    {
    	lv_state_t state = lv_obj_get_state(ta);
    	printf("textarea state is %04x", state);

    	lv_obj_add_state(ta, LV_STATE_FOCUSED);
       /*Remedial measures*/
    	int32_t pos = lv_textarea_get_cursor_pos(ta);
    	lv_textarea_set_cursor_pos(ta, pos + 1);
       /*Remedial measures*/

        if(keyboard != NULL)
        {
        	lv_keyboard_set_textarea(keyboard, ta);
        	lv_obj_clear_flag(keyboard, LV_OBJ_FLAG_HIDDEN);
        }
    }
}

int main()
{
    /* create keyboard */
    keyboard = lv_keyboard_create(lv_scr_act());
    lv_obj_set_size(keyboard, 940, 150);
    lv_obj_align_to(keyboard, NULL, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
    lv_obj_add_event_cb(keyboard, keyboard_event_cb, LV_EVENT_CANCEL, NULL);
    lv_obj_add_flag(keyboard, LV_OBJ_FLAG_HIDDEN);

    /* create ta1 */
    ta1 = lv_textarea_create(lv_scr_act());
    lv_textarea_set_one_line(ta1, true);
    lv_obj_set_size(ta1, 300, 60);
    lv_obj_set_pos(ta1, 84, 40);
    lv_obj_add_event_cb(ta1, ta_event_cb, LV_EVENT_CLICKED, NULL);
}

Hi,

I pushed a fix to LVGL to make it easier to handle. This code worked well for me:


static lv_obj_t * kb;

static void keyboard_event_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);

    if(code == LV_EVENT_READY || code == LV_EVENT_CANCEL) {
        lv_obj_del(kb);
        kb = NULL;
    }

}

static void ta_event_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * ta = lv_event_get_target(e);
    if(code == LV_EVENT_CLICKED) {
        if(kb == NULL) {
            /*Create a keyboard to use it with an of the text areas*/
            kb = lv_keyboard_create(lv_scr_act());
            lv_obj_add_event_cb(kb, keyboard_event_cb, LV_EVENT_ALL, NULL);
        }

        lv_keyboard_set_textarea(kb, ta);
    }

    if(code == LV_EVENT_DEFOCUSED) {
        if(kb) {
            lv_obj_del(kb);
            kb = NULL;
        }
    }
}


void lv_example_keyboard_1(void)
{
    /*Create a text area. The keyboard will write here*/
    lv_obj_t * ta;
    ta = lv_textarea_create(lv_scr_act());
    lv_obj_align(ta, LV_ALIGN_TOP_LEFT, 10, 10);
    lv_obj_add_event_cb(ta, ta_event_cb, LV_EVENT_ALL, NULL);
    lv_textarea_set_placeholder_text(ta, "Hello");
    lv_obj_set_size(ta, 140, 80);

    ta = lv_textarea_create(lv_scr_act());
    lv_obj_align(ta, LV_ALIGN_TOP_RIGHT, -10, 10);
    lv_obj_add_event_cb(ta, ta_event_cb, LV_EVENT_ALL, NULL);
    lv_obj_set_size(ta, 140, 80);


    lv_obj_t * btn = lv_btn_create(lv_scr_act());
    lv_obj_align_to(btn, ta, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 5);
    lv_label_create(btn);
}

ta

Hi, @kisvegabor
I’m having the same problem. If instead of clicking on the Button (Text), after editing the textarea on the left, but you click on the “CLOSE” button of the keyboard, ie the lower left corner with the keyboard icon, it will close the keyboard. Now try clicking on the textarea again, and the keyboard will not open.

Aha, I found it, by looking at the implementation in the lv_demos
https://github.com/lvgl/lv_demos/blob/master/src/lv_demo_widgets/lv_demo_widgets.c

Just add:

  lv_obj_clear_state(ta, LV_STATE_FOCUSED);
  lv_indev_reset(NULL, ta);   /*To forget the last clicked object to make it focusable again*/

I was clearing the Focused state, but not using lv_indev_reset(NULL,ta);