1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

lv_btn ink improvements and fixes

This commit is contained in:
Gabor Kiss-Vamosi 2018-07-08 03:25:07 +02:00
parent 5e8c1d0221
commit 9676c2e486
3 changed files with 83 additions and 26 deletions

View File

@ -242,7 +242,7 @@
#define USE_LV_BTN 1
#if USE_LV_BTN
#define LV_BTN_DEF_INK_FILL_TIME 300 /*[ms] Time of fill the button on click with "ink" (0: disable the effect)*/
#define LV_BTN_DEF_INK_WIAT_TIME 50 /*[ms] Wait before the ink disappears*/
#define LV_BTN_DEF_INK_WAIT_TIME 50 /*[ms] Wait before the ink disappears*/
#endif
/*Button matrix (dependencies: -)*/

View File

@ -75,6 +75,10 @@ void lv_anim_create(lv_anim_t * anim_p)
/*Set the start value*/
if(new_anim->fp != NULL) new_anim->fp(new_anim->var, new_anim->start);
/* Creating an animation changed the linked list.
* It's important if it happens in a ready callback. (see `anim_task`)*/
anim_list_changed = true;
}
/**

View File

@ -22,12 +22,15 @@
* DEFINES
*********************/
#ifndef LV_BTN_DEF_INK_FILL_TIME
# define LV_BTN_DEF_INK_FILL_TIME 200 /*[ms] Time of fill the button on click with "ink" (0: disable the effect)*/
# define LV_BTN_DEF_INK_FILL_TIME 250 /*[ms] Time of fill the button on click with "ink" (0: disable the effect)*/
#endif
#ifndef LV_BTN_DEF_INK_WIAT_TIME
# define LV_BTN_DEF_INK_WIAT_TIME 10 /*[ms] Wait before the ink disappears*/
#ifndef LV_BTN_DEF_INK_WAIT_TIME
# define LV_BTN_DEF_INK_WAIT_TIME 100 /*[ms] Wait before the ink disappears*/
#endif
#define LV_BTN_INK_VALUE_MAX 1024
#define LV_BTN_INK_VALUE_MAX_SHIFT 10
/**********************
* TYPEDEFS
**********************/
@ -37,8 +40,8 @@
**********************/
static bool lv_btn_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_design_mode_t mode);
static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param);
static void lv_btn_circle_effect_anim(lv_obj_t * btn, int32_t val);
static void lv_btn_circle_effect_anim_ready(void * p);
static void lv_btn_ink_effect_anim(lv_obj_t * btn, int32_t val);
static void lv_btn_ink_effect_anim_ready(void * p);
/**********************
* STATIC VARIABLES
@ -51,6 +54,8 @@ static lv_coord_t ink_value;
static lv_obj_t * ink_obj;
static lv_btn_state_t ink_bg_state;
static lv_btn_state_t ink_circle_state;
static bool ink_ready;
static bool ink_playback;
#endif
/**********************
@ -95,7 +100,7 @@ lv_obj_t * lv_btn_create(lv_obj_t * par, lv_obj_t * copy)
ext->long_pr_action_executed = 0;
ext->toggle = 0;
ext->ink_fill_time = LV_BTN_DEF_INK_FILL_TIME;
ext->ink_wait_time = LV_BTN_DEF_INK_WIAT_TIME;
ext->ink_wait_time = LV_BTN_DEF_INK_WAIT_TIME;
lv_obj_set_signal_func(new_btn, lv_btn_signal);
lv_obj_set_design_func(new_btn, lv_btn_design);
@ -395,17 +400,19 @@ static bool lv_btn_design(lv_obj_t * btn, const lv_area_t * mask, lv_design_mode
lv_coord_t h = lv_obj_get_height(btn);
lv_coord_t r_max = LV_MATH_MIN(w, h) / 2;
/*In the first part of the animation increase the size of the circle (ink effect)
in the second part adjust the radius */
lv_area_t cir_area;
lv_coord_t coord_state = ink_value < LV_BTN_INK_VALUE_MAX / 2 ? ink_value : LV_BTN_INK_VALUE_MAX / 2;
cir_area.x1 = btn->coords.x1 + w / 2 - (((w / 2) * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
cir_area.y1 = btn->coords.y1 + h / 2 - (((h / 2) * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
cir_area.x2 = btn->coords.x1 + w / 2 + (((w / 2) * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
cir_area.y2 = btn->coords.y1 + h / 2 + (((h / 2) * coord_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
lv_coord_t r_state = ink_value > LV_BTN_INK_VALUE_MAX / 2 ? ink_value - LV_BTN_INK_VALUE_MAX / 2 : 0;
lv_style_t cir_style;
lv_style_copy(&cir_style, ext->styles[ink_circle_state]);
cir_style.body.radius = r_max + (((ext->styles[ink_bg_state]->body.radius - r_max) * ink_value) >> 10);
lv_area_t cir_area;
cir_area.x1 = btn->coords.x1 + w / 2 - (((w / 2) * ink_value) >> 10);
cir_area.y1 = btn->coords.y1 + h / 2 - (((h / 2) * ink_value) >> 10);
cir_area.x2 = btn->coords.x1 + w / 2 + (((w / 2) * ink_value) >> 10);
cir_area.y2 = btn->coords.y1 + h / 2 + (((h / 2) * ink_value) >> 10);
cir_style.body.radius = r_max + (((ext->styles[ink_bg_state]->body.radius - r_max) * r_state) >> (LV_BTN_INK_VALUE_MAX_SHIFT - 1));
lv_draw_rect(&cir_area, mask, &cir_style, LV_OPA_COVER);
}
@ -458,24 +465,26 @@ static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param)
#if USE_LV_ANIMATION
/*Forget the old inked button*/
if(ink_obj != NULL && ink_obj != btn) {
lv_anim_del(ink_obj, (lv_anim_fp_t)lv_btn_circle_effect_anim);
lv_anim_del(ink_obj, (lv_anim_fp_t)lv_btn_ink_effect_anim);
lv_obj_invalidate(ink_obj);
}
/*Save the new data for inking and start it's animation if enabled*/
if(ext->ink_fill_time > 0) {
ink_obj = btn;
ink_playback = false;
ink_ready = false;
lv_anim_t a;
a.var = btn;
a.start = 0;
a.end = 1024;//LV_MATH_MAX(lv_obj_get_width(btn), lv_obj_get_height(btn));
a.fp = (lv_anim_fp_t)lv_btn_circle_effect_anim;
a.end = LV_BTN_INK_VALUE_MAX;
a.fp = (lv_anim_fp_t)lv_btn_ink_effect_anim;
a.path = lv_anim_path_linear;
a.end_cb = lv_btn_circle_effect_anim_ready;
a.end_cb = lv_btn_ink_effect_anim_ready;
a.act_time = 0;
a.time = ext->ink_fill_time;
a.playback = ext->toggle ? 0 : 1;
a.playback_pause = 100;
a.playback = 0;
a.playback_pause = 0;
a.repeat = 0;
a.repeat_pause = 0;
lv_anim_create(&a);
@ -525,6 +534,26 @@ static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param)
if(ext->toggle) {
ink_circle_state = ext->state;
}
/*If not a toggle button and the "IN" inking is ready then start an "OUT" inking*/
else if(ink_ready && ext->ink_fill_time > 0) {
ink_obj = btn;
ink_playback = true; /*It is the playback. If not set `lv_btn_ink_effect_anim_ready` will start its own playback*/
lv_anim_t a;
a.var = ink_obj;
a.start = LV_BTN_INK_VALUE_MAX;
a.end = 0;
a.fp = (lv_anim_fp_t)lv_btn_ink_effect_anim;
a.path = lv_anim_path_linear;
a.end_cb = lv_btn_ink_effect_anim_ready;
a.act_time = 0;
a.time = ext->ink_fill_time;
a.playback = 0;
a.playback_pause = 0;
a.repeat = 0;
a.repeat_pause = 0;
lv_anim_create(&a);
}
#endif
} else if(sign == LV_SIGNAL_LONG_PRESS) {
if(ext->actions[LV_BTN_ACTION_LONG_PR] && state != LV_BTN_STATE_INA) {
@ -565,7 +594,7 @@ static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param)
else if(sign == LV_SIGNAL_CLEANUP) {
#if USE_LV_ANIMATION
if(btn == ink_obj) {
lv_anim_del(ink_obj, (lv_anim_fp_t)lv_btn_circle_effect_anim);
lv_anim_del(ink_obj, (lv_anim_fp_t)lv_btn_ink_effect_anim);
ink_obj = NULL;
}
#endif
@ -589,7 +618,7 @@ static lv_res_t lv_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * param)
* @param btn pointer to the animated button
* @param val the new radius
*/
static void lv_btn_circle_effect_anim(lv_obj_t * btn, int32_t val)
static void lv_btn_ink_effect_anim(lv_obj_t * btn, int32_t val)
{
if(ink_obj) {
ink_value = val;
@ -601,10 +630,34 @@ static void lv_btn_circle_effect_anim(lv_obj_t * btn, int32_t val)
* Called to clean up when the ink animation is ready
* @param p unused
*/
static void lv_btn_circle_effect_anim_ready(void * p)
static void lv_btn_ink_effect_anim_ready(void * p)
{
lv_btn_ext_t * ext = lv_obj_get_ext_attr(ink_obj);
lv_btn_state_t state = lv_btn_get_state(ink_obj);
lv_obj_invalidate(ink_obj);
ink_obj = NULL;
ink_ready = true;
if((state == LV_BTN_STATE_REL || state == LV_BTN_STATE_TGL_REL) && ext->toggle == 0 && ink_playback == false) {
lv_anim_t a;
a.var = ink_obj;
a.start = LV_BTN_INK_VALUE_MAX;
a.end = 0;
a.fp = (lv_anim_fp_t)lv_btn_ink_effect_anim;
a.path = lv_anim_path_linear;
a.end_cb = lv_btn_ink_effect_anim_ready;
a.act_time = -ext->ink_wait_time;
a.time = ext->ink_fill_time;
a.playback = 0;
a.playback_pause = 0;
a.repeat = 0;
a.repeat_pause = 0;
lv_anim_create(&a);
ink_playback = true;
} else {
ink_obj = NULL;
}
}
#endif /*USE_LV_ANIMATION*/