Recolor the image (pressed) for image that's inside a button

Description

How can I change the color (opacity) of an image in a button (when pressed) properly?

Extra info - the image is LV_IMG_CF_ALPHA_4BIT - I want to have a different opacity per state of the button the image is inside of.

MCU/Processor/Board and compiler:

Testing with the lv_sim_eclipse_sdl demo (simulator via Eclipse)

LVGL version:

7.11.0

What do you want to achieve?

What have you tried so far?

My initial try is to use a button w/ custom sizing/style + image on top and set recolor per state - then I can customize the button style appropriately, but the image doesn’t update:

So a button w/ border radius, etc, default vs pressed:
Screen Shot 2021-05-06 at 10.36.39 AM
Screen Shot 2021-05-06 at 10.37.56 AM

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 lv_style_t btn_style, img_style;
// Style the button object:
lv_style_init(&btn_style);
lv_style_set_radius(&btn_style, LV_STATE_DEFAULT, 27);
lv_style_set_bg_opa(&btn_style, LV_STATE_DEFAULT, LV_OPA_100);
lv_style_set_bg_color(&btn_style, LV_STATE_DEFAULT, LV_COLOR_WHITE);
lv_style_set_bg_grad_color(&btn_style, LV_STATE_DEFAULT, LV_COLOR_WHITE);
lv_style_set_bg_grad_dir(&btn_style, LV_STATE_DEFAULT, LV_GRAD_DIR_VER);
lv_style_set_border_width(&btn_style, LV_STATE_DEFAULT, 2);
lv_style_set_border_color(&btn_style, LV_STATE_DEFAULT, LV_COLOR_BLACK);
lv_style_set_bg_opa(&btn_style, LV_STATE_PRESSED, LV_OPA_50);
lv_style_set_border_opa(&btn_style, LV_STATE_PRESSED, LV_OPA_50);

lv_style_init(&img_style);
lv_style_set_image_recolor(&img_style, LV_STATE_DEFAULT, LV_COLOR_BLACK);
lv_style_set_image_recolor_opa(&img_style, LV_STATE_DEFAULT, LV_OPA_100);
lv_style_set_image_recolor_opa(&img_style, LV_STATE_PRESSED, LV_OPA_50);

//create objects & assign style:
lv_obj_t *btn = lv_btn_create(parent, NULL);
lv_obj_set_event_cb(btn, cb);
lv_obj_add_style(btn, LV_BTN_PART_MAIN, &btn_style);
lv_obj_set_size(btn, 54, 54);
lv_obj_t *img = lv_img_create(btn, NULL);
lv_img_set_src(img, src_img);
lv_obj_add_style(img, LV_IMG_PART_MAIN, &img_style);



Just to mention, I ALSO tried imgbtn - but i wasn’t able to:

  1. Customize the initial image color in that case to not-black via image recolor for LV_STATE_DEFAULT, and
  2. also had issues customizing the background if i wanted it larger than the image. (like the above, where the image is just an icon / portion of the button, not the whole button).

As a hack, tried to set the OPA directly in the callback to no avail:


static void up_cb(lv_obj_t * obj, lv_event_t event){
	switch(event) {
		case LV_EVENT_PRESSED:
			lv_obj_set_style_local_image_recolor_opa(img, LV_IMG_PART_MAIN, LV_STATE_DEFAULT, 30);
			lv_obj_set_style_local_image_recolor_opa(img, LV_IMG_PART_MAIN, LV_STATE_CHECKED, 30);
			lv_obj_set_style_local_image_recolor_opa(img, LV_IMG_PART_MAIN, LV_STATE_FOCUSED, 30);
			lv_obj_set_style_local_image_recolor_opa(img, LV_IMG_PART_MAIN, LV_STATE_EDITED, 30);
			lv_obj_set_style_local_image_recolor_opa(img, LV_IMG_PART_MAIN, LV_STATE_HOVERED, 30);
			lv_obj_set_style_local_image_recolor_opa(img, LV_IMG_PART_MAIN, LV_STATE_PRESSED, 30);
			break;
		case LV_EVENT_SHORT_CLICKED:
		case LV_EVENT_CLICKED:
		case LV_EVENT_LONG_PRESSED:
		case LV_EVENT_LONG_PRESSED_REPEAT:
			break;
		case LV_EVENT_RELEASED:
			lv_obj_set_style_local_image_recolor_opa(img, LV_IMG_PART_MAIN, LV_STATE_DEFAULT, 100);
		break;
  }
}



i also tried invalidating the image lv_obj on callback and that also didn’t help.

anyone else done this / got ideas?

bump - any thoughts?