mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-21 06:53:01 +08:00
lv_slider: experimental bar and slider animation update
This commit is contained in:
parent
c318a7fc37
commit
4743e11967
@ -30,6 +30,9 @@
|
||||
static bool lv_bar_design(lv_obj_t * bar, const lv_area_t * mask, lv_design_mode_t mode);
|
||||
static lv_res_t lv_bar_signal(lv_obj_t * bar, lv_signal_t sign, void * param);
|
||||
|
||||
static void lv_bar_animate(void * bar, int32_t value);
|
||||
static void lv_bar_anim_ready(void * bar);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
@ -70,6 +73,9 @@ lv_obj_t * lv_bar_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
ext->min_value = 0;
|
||||
ext->max_value = 100;
|
||||
ext->cur_value = 0;
|
||||
ext->anim_start = 0;
|
||||
ext->anim_end = 0;
|
||||
ext->anim_state = LV_BAR_ANIM_STATE_INV;
|
||||
ext->sym = 0;
|
||||
ext->style_indic = &lv_style_pretty_color;
|
||||
|
||||
@ -142,13 +148,26 @@ void lv_bar_set_value_anim(lv_obj_t * bar, int16_t value, uint16_t anim_time)
|
||||
new_value = value > ext->max_value ? ext->max_value : value;
|
||||
new_value = new_value < ext->min_value ? ext->min_value : new_value;
|
||||
|
||||
if(ext->cur_value == new_value) return;
|
||||
|
||||
/*NO animation in progress -> simply set the values*/
|
||||
if(ext->anim_state == LV_BAR_ANIM_STATE_INV) {
|
||||
ext->anim_start = ext->cur_value;
|
||||
ext->anim_end = new_value;
|
||||
}
|
||||
/*Animation in progress. Start from the animation end value*/
|
||||
else {
|
||||
ext->anim_start = ext->anim_end;
|
||||
ext->anim_end = new_value;
|
||||
}
|
||||
|
||||
lv_anim_t a;
|
||||
a.var = bar;
|
||||
a.start = ext->cur_value;
|
||||
a.end = new_value;
|
||||
a.fp = (lv_anim_fp_t)lv_bar_set_value;
|
||||
a.start = LV_BAR_ANIM_STATE_START;
|
||||
a.end = LV_BAR_ANIM_STATE_END;
|
||||
a.fp = (lv_anim_fp_t)lv_bar_animate;
|
||||
a.path = lv_anim_path_linear;
|
||||
a.end_cb = NULL;
|
||||
a.end_cb = lv_bar_anim_ready;
|
||||
a.act_time = 0;
|
||||
a.time = anim_time;
|
||||
a.playback = 0;
|
||||
@ -229,7 +248,10 @@ void lv_bar_set_style(lv_obj_t * bar, lv_bar_style_t type, lv_style_t * style)
|
||||
int16_t lv_bar_get_value(const lv_obj_t * bar)
|
||||
{
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
return ext->cur_value;
|
||||
/*If animated tell that it's already at the end value*/
|
||||
if(ext->anim_state != LV_BAR_ANIM_STATE_INV) return ext->anim_end;
|
||||
/*No animation, simple return the current value*/
|
||||
else return ext->cur_value;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -330,7 +352,7 @@ static bool lv_bar_design(lv_obj_t * bar, const lv_area_t * mask, lv_design_mode
|
||||
#endif
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
|
||||
if(ext->cur_value != ext->min_value || ext->sym) {
|
||||
if(ext->cur_value != ext->min_value || ext->sym || ext->anim_start != LV_BAR_ANIM_STATE_INV) {
|
||||
lv_style_t * style_indic = lv_bar_get_style(bar, LV_BAR_STYLE_INDIC);
|
||||
lv_area_t indic_area;
|
||||
lv_area_copy(&indic_area, &bar->coords);
|
||||
@ -344,9 +366,18 @@ static bool lv_bar_design(lv_obj_t * bar, const lv_area_t * mask, lv_design_mode
|
||||
|
||||
if(w >= h) {
|
||||
/*Horizontal*/
|
||||
indic_area.x2 = (int32_t)((int32_t)w * (ext->cur_value - ext->min_value)) / (ext->max_value - ext->min_value);
|
||||
indic_area.x2 = indic_area.x1 + indic_area.x2 - 1;
|
||||
if(ext->anim_state != LV_BAR_ANIM_STATE_INV) {
|
||||
/*Calculate the coordinates of anim. start and end*/
|
||||
lv_coord_t anim_start_x = (int32_t)((int32_t)w * (ext->anim_start - ext->min_value)) / (ext->max_value - ext->min_value);
|
||||
lv_coord_t anim_end_x = (int32_t)((int32_t)w * (ext->anim_end - ext->min_value)) / (ext->max_value - ext->min_value);
|
||||
|
||||
/*Calculate the real position based on `anim_state` (between `anim_start` and `anim_end`)*/
|
||||
indic_area.x2 = anim_start_x + (((anim_end_x - anim_start_x) * ext->anim_state) >> LV_BAR_ANIM_STATE_NORM);
|
||||
} else {
|
||||
indic_area.x2 = (int32_t)((int32_t)w * (ext->cur_value - ext->min_value)) / (ext->max_value - ext->min_value);
|
||||
}
|
||||
|
||||
indic_area.x2 = indic_area.x1 + indic_area.x2 - 1;
|
||||
if(ext->sym && ext->min_value < 0 && ext->max_value > 0) {
|
||||
/*Calculate the coordinate of the zero point*/
|
||||
lv_coord_t zero;
|
||||
@ -358,7 +389,17 @@ static bool lv_bar_design(lv_obj_t * bar, const lv_area_t * mask, lv_design_mode
|
||||
}
|
||||
}
|
||||
} else {
|
||||
indic_area.y1 = (int32_t)((int32_t)h * (ext->cur_value - ext->min_value)) / (ext->max_value - ext->min_value);
|
||||
if(ext->anim_state != LV_BAR_ANIM_STATE_INV) {
|
||||
/*Calculate the coordinates of anim. start and end*/
|
||||
lv_coord_t anim_start_y = (int32_t)((int32_t)h * (ext->anim_start - ext->min_value)) / (ext->max_value - ext->min_value);
|
||||
lv_coord_t anim_end_y = (int32_t)((int32_t)h * (ext->anim_end - ext->min_value)) / (ext->max_value - ext->min_value);
|
||||
|
||||
/*Calculate the real position based on `anim_state` (between `anim_start` and `anim_end`)*/
|
||||
indic_area.y1 = anim_start_y + (((anim_end_y - anim_start_y) * ext->anim_state) >> LV_BAR_ANIM_STATE_NORM);
|
||||
} else {
|
||||
indic_area.y1 = (int32_t)((int32_t)h * (ext->cur_value - ext->min_value)) / (ext->max_value - ext->min_value);
|
||||
}
|
||||
|
||||
indic_area.y1 = indic_area.y2 - indic_area.y1 + 1;
|
||||
|
||||
if(ext->sym && ext->min_value < 0 && ext->max_value > 0) {
|
||||
@ -426,4 +467,19 @@ static lv_res_t lv_bar_signal(lv_obj_t * bar, lv_signal_t sign, void * param)
|
||||
}
|
||||
|
||||
|
||||
static void lv_bar_animate(void * bar, int32_t value)
|
||||
{
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
ext->anim_state = value;
|
||||
lv_obj_invalidate(bar);
|
||||
}
|
||||
|
||||
static void lv_bar_anim_ready(void * bar)
|
||||
{
|
||||
lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar);
|
||||
ext->anim_state = LV_BAR_ANIM_STATE_INV;
|
||||
lv_bar_set_value(bar, ext->anim_end);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -29,6 +29,10 @@ extern "C" {
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_BAR_ANIM_STATE_START 0
|
||||
#define LV_BAR_ANIM_STATE_END 256
|
||||
#define LV_BAR_ANIM_STATE_INV -1
|
||||
#define LV_BAR_ANIM_STATE_NORM 8 /*log2(LV_BAR_ANIM_STATE_END) used to normalize data*/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@ -42,6 +46,9 @@ typedef struct
|
||||
int16_t cur_value; /*Current value of the bar*/
|
||||
int16_t min_value; /*Minimum value of the bar*/
|
||||
int16_t max_value; /*Maximum value of the bar*/
|
||||
int16_t anim_start;
|
||||
int16_t anim_end;
|
||||
int16_t anim_state;
|
||||
uint8_t sym :1; /*Symmetric: means the center is around zero value*/
|
||||
lv_style_t *style_indic; /*Style of the indicator*/
|
||||
} lv_bar_ext_t;
|
||||
|
@ -304,11 +304,10 @@ static bool lv_slider_design(lv_obj_t * slider, const lv_area_t * mask, lv_desig
|
||||
area_bg.y2 -= slider_w > slider_h ? pad_ver_bg : 0; /*Pad only for horizontal slider*/
|
||||
}
|
||||
|
||||
|
||||
#if USE_LV_GROUP == 0
|
||||
lv_draw_rect(&area_bg, mask, style_bg, lv_obj_get_opa_scale(slider));
|
||||
#else
|
||||
/* Draw the borders later if the bar is focused.
|
||||
/* Draw the borders later if the slider is focused.
|
||||
* At value = 100% the indicator can cover to whole background and the focused style won't be visible*/
|
||||
if(lv_obj_is_focused(slider)) {
|
||||
lv_style_t style_tmp;
|
||||
@ -320,7 +319,6 @@ static bool lv_slider_design(lv_obj_t * slider, const lv_area_t * mask, lv_desig
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*Draw the indicator*/
|
||||
lv_area_t area_indic;
|
||||
lv_area_copy(&area_indic, &area_bg);
|
||||
@ -349,11 +347,31 @@ static bool lv_slider_design(lv_obj_t * slider, const lv_area_t * mask, lv_desig
|
||||
if(ext->drag_value != LV_SLIDER_NOT_PRESSED) cur_value = ext->drag_value;
|
||||
|
||||
if(slider_w >= slider_h) {
|
||||
area_indic.x2 = (int32_t)((int32_t)(lv_area_get_width(&area_indic)) * (cur_value - min_value)) / (max_value - min_value);
|
||||
lv_coord_t indic_w = lv_area_get_width(&area_indic);
|
||||
if(ext->bar.anim_state != LV_BAR_ANIM_STATE_INV) {
|
||||
/*Calculate the coordinates of anim. start and end*/
|
||||
lv_coord_t anim_start_x = (int32_t)((int32_t)indic_w * (ext->bar.anim_start - min_value)) / (max_value - min_value);
|
||||
lv_coord_t anim_end_x = (int32_t)((int32_t)indic_w * (ext->bar.anim_end - min_value)) / (max_value - min_value);
|
||||
|
||||
/*Calculate the real position based on `anim_state` (between `anim_start` and `anim_end`)*/
|
||||
area_indic.x2 = anim_start_x + (((anim_end_x - anim_start_x) * ext->bar.anim_state) >> 8);
|
||||
} else {
|
||||
area_indic.x2 = (int32_t)((int32_t)indic_w * (cur_value - min_value)) / (max_value - min_value);
|
||||
}
|
||||
area_indic.x2 = area_indic.x1 + area_indic.x2 - 1;
|
||||
|
||||
} else {
|
||||
area_indic.y1 = (int32_t)((int32_t)(lv_area_get_height(&area_indic)) * (cur_value - min_value)) / (max_value - min_value);
|
||||
lv_coord_t indic_h = lv_area_get_height(&area_indic);
|
||||
if(ext->bar.anim_state != LV_BAR_ANIM_STATE_INV) {
|
||||
/*Calculate the coordinates of anim. start and end*/
|
||||
lv_coord_t anim_start_y = (int32_t)((int32_t)indic_h * (ext->bar.anim_start - min_value)) / (max_value - min_value);
|
||||
lv_coord_t anim_end_y = (int32_t)((int32_t)indic_h * (ext->bar.anim_end - min_value)) / (max_value - min_value);
|
||||
|
||||
/*Calculate the real position based on `anim_state` (between `anim_start` and `anim_end`)*/
|
||||
area_indic.y1 = anim_start_y + (((anim_end_y - anim_start_y) * ext->bar.anim_state) >> 8);
|
||||
} else {
|
||||
area_indic.y1 = (int32_t)((int32_t)indic_h * (cur_value - min_value)) / (max_value - min_value);
|
||||
}
|
||||
area_indic.y1 = area_indic.y2 - area_indic.y1 + 1;
|
||||
}
|
||||
|
||||
@ -497,10 +515,10 @@ static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * par
|
||||
}
|
||||
#endif
|
||||
if(c == LV_GROUP_KEY_RIGHT || c == LV_GROUP_KEY_UP) {
|
||||
lv_slider_set_value(slider, lv_slider_get_value(slider) + 1);
|
||||
lv_slider_set_value_anim(slider, lv_slider_get_value(slider) + 1, 200);
|
||||
if(ext->action != NULL) res = ext->action(slider);
|
||||
} else if(c == LV_GROUP_KEY_LEFT || c == LV_GROUP_KEY_DOWN) {
|
||||
lv_slider_set_value(slider, lv_slider_get_value(slider) - 1);
|
||||
lv_slider_set_value_anim(slider, lv_slider_get_value(slider) - 1, 200);
|
||||
if(ext->action != NULL) res = ext->action(slider);
|
||||
}
|
||||
} else if(sign == LV_SIGNAL_GET_EDITABLE) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user