Indevices and groups - make an object clickable in navigate mode

Description

Hi there, I have quite a nice menu system up and running, with no touch screen and only an encoder.

I have used buttons and lists with some success, but I am having an issue with the behaviour of base objects.

Initially I wanted to have a table with 2 columns, but when I wanted to navigate it, I couldn’t get the whole row to focus at a time. I’m guessing this could be simulated by implementing it in the table draw callback, but I rather opted for a different route.

I now have a bunch of objects which are my “rows”, within them, I have two labels, simulating my columns.

When I click on one of the rows, I have a callback that changes the value in column two. This works quite well, the only issue is, I need to click twice (first to go into edit mode, then to change the value).

Making matters worse, once I have entered edit mode on the object, I cant seem to exit is. I can manually disable edit mode in the click callback to make my “table” scrollable again, but this will mean I have to click everything twice to change a value.

How can I change the behaviour of the base object (my “rows”) to act like a button? i.e. when navigating, I click once, it executes the callback and I can resume scrolling?

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

A custom board, STM32F769 and STM Cube IDE.

What LVGL version are you using?

Version 8+.

What do you want to achieve?

I want to change the behaviour of a “container”-like object to that of a button.

What have you tried so far?

I tried making the object clickable, I tried changing the edit/navigate mode manually, I also tried exiting the edit mode with a long press, all without success.

Code to reproduce

Here is me creating the “rows” (showing only the relevant bits)

//Clear of all objects
	lv_group_remove_all_objs(TestmenuGroup);

	//Create the array of setting items
	for(uint8_t i = 0; i < Settings_Count; i++)
	{
		//Create an object
		Display_SettingsObjects[i] = lv_obj_create(ParentWindow);

		//Set the object size / align
		lv_obj_set_width(Display_SettingsObjects[i], LV_PCT(100));
		lv_obj_set_height(Display_SettingsObjects[i], 30);
		lv_obj_align(Display_SettingsObjects[i], LV_ALIGN_CENTER, 0, 0);

		//Reduce padding
		lv_obj_set_style_pad_all(Display_SettingsObjects[i], 2, 0);

		//Add the first label
		lv_obj_t * child1 = lv_label_create(Display_SettingsObjects[i]);
		lv_label_set_text(child1, TestJigSettings[i].Name);

		//set the width
		lv_obj_set_width(child1, LV_PCT(65));
		lv_obj_align(child1, LV_ALIGN_LEFT_MID, 0, 0);

		//Convert settings value to text
		char tempSettingText[MAX_SETTING_TEXT_LENGTH];
		Display_getSettingText(Settings[i].Type, Settings[i].Current, Settings[i].Options, Settings[i].OptionCount, SettingText);

		//Add the second label
		lv_obj_t * child2 = lv_label_create(Display_SettingsObjects[i]);
		lv_label_set_text(child2, tempSettingText);

		//Add the object to the group
		lv_group_add_obj(TestmenuGroup, Display_SettingsObjects[i]);

		//set the width
		lv_obj_set_width(child2, LV_PCT(30));
		lv_obj_align(child2, LV_ALIGN_RIGHT_MID, 0, 0);

		//Enable scrolling
		lv_obj_add_flag(Display_SettingsObjects[i], LV_OBJ_FLAG_SCROLL_ON_FOCUS);

		//Make clickable
		lv_obj_add_flag(Display_SettingsObjects[i], LV_OBJ_FLAG_CLICKABLE);

		//Add the callback for the menu item
		lv_obj_add_event_cb(Display_SettingsObjects[i], Display_EditSetting, LV_EVENT_CLICKED, &Settings[i]);

	}

	//Set indevices
	lv_indev_set_group(MyInputDevice, TestmenuGroup);
	lv_indev_set_group(MyInputDevice2, TestmenuGroup);

Here is my click callback:

//get pointer to setting object
	Settings_t* Settingtemp = lv_event_get_user_data(e);

	//Get pointer to the "value" lable. It is the second child of the object
	lv_obj_t * tempObject = lv_event_get_target(e);
	lv_obj_t * tempValueLable = lv_obj_get_child(tempObject, 1);

	switch(Settingtemp->Type)
	{
	case 	MultiSelect:

		break;

	case	Checkbox:

		//This is a true/false, we can just toggle it
		if(Settingtemp->Current)
		{
			Settingtemp->Current = 0;
		}
		else
		{
			Settingtemp->Current = 1;
		}

		break;

	case 	Integer:

		break;

	case	Decimal:

		break;

	case 	String:

		break;

	default:
		break;

	}

	//Update the value label
	char tempSettingText[MAX_SETTING_TEXT_LENGTH];
	Display_getSettingText(Settingtemp->Type, Settingtemp->Current, Settingtemp->Options, Settingtemp->OptionCount, tempSettingText);

	lv_label_set_text(tempValueLable, tempSettingText);

	//Update the setting in NVRAM
	Settings_WriteNewValue(Settingtemp->Current, Settingtemp->Index);