feat(switch): add vertical switch function (#6786)

Co-authored-by: lizhaoming <13678462+lizhao-ming@user.noreply.gitee.com>
Co-authored-by: 100ask <support@100ask.net>
Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
lizhaoming19980614 2024-09-14 12:04:51 +08:00 committed by GitHub
parent 7f57f37560
commit a37f84f34c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 196 additions and 20 deletions

View File

@ -10,6 +10,8 @@ Overview
The Switch looks like a little slider and can be used to turn something
on and off.
Vertical Switch can be created if the width of the object is smaller than its height.
.. _lv_switch_parts_and_styles:
Parts and Styles
@ -43,6 +45,12 @@ To get the current state of the switch (with ``true`` being on), use
Call :cpp:expr:`lv_obj_add_state(obj, LV_STATE_CHECKED)` to turn it on, or
:cpp:expr:`lv_obj_remove_state(obj, LV_STATE_CHECKED)` to turn it off.
Change orientation
------------------
:cpp:expr:`lv_switch_set_orientation(obj, LV_SWITCH_ORIENTATION_VERTICAL)` change orientation, default orientation is :cpp:enumerator:`LV_SWITCH_ORIENTATION_AUTO`, adaptive based on the width and height of the object.
.. _lv_switch_events:
Events

View File

@ -136,6 +136,7 @@ void lv_example_spinbox_1(void);
void lv_example_spinner_1(void);
void lv_example_switch_1(void);
void lv_example_switch_2(void);
void lv_example_table_1(void);
void lv_example_table_2(void);

View File

@ -5,3 +5,10 @@ Simple Switch
.. lv_example:: widgets/switch/lv_example_switch_1
:language: c
Switch Orientation
-------------------
.. lv_example:: widgets/switch/lv_example_switch_2
:language: c

View File

@ -0,0 +1,32 @@
#include "../../lv_examples.h"
#if LV_USE_SWITCH && LV_BUILD_EXAMPLES
static void event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
if(code == LV_EVENT_VALUE_CHANGED) {
LV_UNUSED(obj);
LV_LOG_USER("State: %s\n", lv_obj_has_state(obj, LV_STATE_CHECKED) ? "On" : "Off");
}
}
void lv_example_switch_2(void)
{
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t * sw;
sw = lv_switch_create(lv_screen_active());
lv_obj_set_size(sw, 30, 60);
lv_obj_add_event_cb(sw, event_handler, LV_EVENT_ALL, NULL);
sw = lv_switch_create(lv_screen_active());
lv_obj_set_size(sw, 30, 60);
lv_switch_set_orientation(sw, LV_SWITCH_ORIENTATION_VERTICAL);
lv_obj_add_state(sw, LV_STATE_CHECKED);
lv_obj_add_event_cb(sw, event_handler, LV_EVENT_ALL, NULL);
}
#endif

View File

@ -49,6 +49,7 @@ static void draw_main(lv_event_t * e);
static void lv_switch_anim_exec_cb(void * sw, int32_t value);
static void lv_switch_trigger_anim(lv_obj_t * obj);
static void lv_switch_anim_completed(lv_anim_t * a);
/**********************
* STATIC VARIABLES
**********************/
@ -80,6 +81,31 @@ lv_obj_t * lv_switch_create(lv_obj_t * parent)
return obj;
}
/*=====================
* Setter functions
*====================*/
void lv_switch_set_orientation(lv_obj_t * obj, lv_switch_orientation_t orientation)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_switch_t * sw = (lv_switch_t *)obj;
sw->orientation = orientation;
lv_obj_invalidate(obj);
}
/*=====================
* Getter functions
*====================*/
lv_switch_orientation_t lv_switch_get_orientation(lv_obj_t * obj)
{
LV_ASSERT_OBJ(obj, MY_CLASS);
lv_switch_t * sw = (lv_switch_t *)obj;
return sw->orientation;
}
/**********************
* STATIC FUNCTIONS
**********************/
@ -92,6 +118,7 @@ static void lv_switch_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj
lv_switch_t * sw = (lv_switch_t *)obj;
sw->anim_state = LV_SWITCH_ANIM_STATE_INV;
sw->orientation = LV_SWITCH_ORIENTATION_AUTO;
lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_add_flag(obj, LV_OBJ_FLAG_CHECKABLE);
@ -163,28 +190,67 @@ static void draw_main(lv_event_t * e)
lv_draw_rect(layer, &draw_indic_dsc, &indic_area);
/*Draw the knob*/
int32_t anim_value_x = 0;
int32_t knob_size = lv_obj_get_height(obj);
int32_t anim_length = lv_area_get_width(&obj->coords) - knob_size;
if(LV_SWITCH_IS_ANIMATING(sw)) {
/* Use the animation's coordinate */
anim_value_x = (anim_length * sw->anim_state) / LV_SWITCH_ANIM_STATE_END;
}
else {
/* Use LV_STATE_CHECKED to decide the coordinate */
bool chk = lv_obj_get_state(obj) & LV_STATE_CHECKED;
anim_value_x = chk ? anim_length : 0;
}
if(LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN)) {
anim_value_x = anim_length - anim_value_x;
}
lv_area_t knob_area;
lv_area_copy(&knob_area, &obj->coords);
knob_area.x1 += anim_value_x;
knob_area.x2 = knob_area.x1 + (knob_size > 0 ? knob_size - 1 : 0);
int32_t switch_w = lv_area_get_width(&obj->coords);
int32_t switch_h = lv_area_get_height(&obj->coords);
bool hor = false;
switch(sw->orientation) {
case LV_SWITCH_ORIENTATION_HORIZONTAL:
hor = true;
break;
case LV_SWITCH_ORIENTATION_VERTICAL:
hor = false;
break;
case LV_SWITCH_ORIENTATION_AUTO:
default:
hor = (switch_w >= switch_h);
break;
}
if(hor) {
int32_t anim_value_x = 0;
int32_t knob_size = lv_obj_get_height(obj);
int32_t anim_length = lv_area_get_width(&obj->coords) - knob_size;
if(LV_SWITCH_IS_ANIMATING(sw)) {
/* Use the animation's coordinate */
anim_value_x = (anim_length * sw->anim_state) / LV_SWITCH_ANIM_STATE_END;
}
else {
/* Use LV_STATE_CHECKED to decide the coordinate */
bool chk = lv_obj_get_state(obj) & LV_STATE_CHECKED;
anim_value_x = chk ? anim_length : 0;
}
if(LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN)) {
anim_value_x = anim_length - anim_value_x;
}
knob_area.x1 += anim_value_x;
knob_area.x2 = knob_area.x1 + (knob_size > 0 ? knob_size - 1 : 0);
}
else {
int32_t anim_value_y = 0;
int32_t knob_size = lv_obj_get_width(obj);
int32_t anim_length = lv_area_get_height(&obj->coords) - knob_size;
if(LV_SWITCH_IS_ANIMATING(sw)) {
/* Use the animation's coordinate */
anim_value_y = (anim_length * sw->anim_state) / LV_SWITCH_ANIM_STATE_END;
}
else {
/* Use LV_STATE_CHECKED to decide the coordinate */
bool chk = lv_obj_get_state(obj) & LV_STATE_CHECKED;
anim_value_y = chk ? anim_length : 0;
}
if(LV_BASE_DIR_RTL == lv_obj_get_style_base_dir(obj, LV_PART_MAIN)) {
anim_value_y = anim_length - anim_value_y;
}
knob_area.y2 -= anim_value_y;
knob_area.y1 = knob_area.y2 - (knob_size > 0 ? knob_size - 1 : 0);
}
int32_t knob_left = lv_obj_get_style_pad_left(obj, LV_PART_KNOB);
int32_t knob_right = lv_obj_get_style_pad_right(obj, LV_PART_KNOB);

View File

@ -28,6 +28,16 @@ extern "C" {
LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_switch_class;
/**********************
* TYPEDEFS
**********************/
typedef enum {
LV_SWITCH_ORIENTATION_AUTO,
LV_SWITCH_ORIENTATION_HORIZONTAL,
LV_SWITCH_ORIENTATION_VERTICAL
} lv_switch_orientation_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
@ -39,6 +49,28 @@ LV_ATTRIBUTE_EXTERN_DATA extern const lv_obj_class_t lv_switch_class;
*/
lv_obj_t * lv_switch_create(lv_obj_t * parent);
/*=====================
* Setter functions
*====================*/
/**
* Set the orientation of switch.
* @param obj pointer to switch object
* @param orientation switch orientation from `lv_switch_orientation_t`
*/
void lv_switch_set_orientation(lv_obj_t * obj, lv_switch_orientation_t orientation);
/*=====================
* Getter functions
*====================*/
/**
* Get the orientation of switch.
* @param obj pointer to switch object
* @return switch orientation from ::lv_switch_orientation_t
*/
lv_switch_orientation_t lv_switch_get_orientation(lv_obj_t * obj);
/**********************
* MACROS
**********************/

View File

@ -34,6 +34,7 @@ extern "C" {
struct _lv_switch_t {
lv_obj_t obj;
int32_t anim_state;
lv_switch_orientation_t orientation : 3; /**< Orientation of switch*/
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -133,4 +133,33 @@ void test_switch_should_state_change_when_event_bubbling_is_enabled(void)
TEST_ASSERT(lv_obj_has_state(sw, LV_STATE_CHECKED));
}
void test_screeshots(void)
{
lv_obj_set_flex_flow(lv_screen_active(), LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(lv_screen_active(), LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_clean(scr);
sw = lv_switch_create(lv_screen_active());
sw = lv_switch_create(lv_screen_active());
lv_obj_add_state(sw, LV_STATE_CHECKED);
sw = lv_switch_create(lv_screen_active());
sw = lv_switch_create(lv_screen_active());
lv_obj_add_state(sw, LV_STATE_CHECKED | LV_STATE_DISABLED);
sw = lv_switch_create(lv_screen_active());
lv_switch_set_orientation(sw, LV_SWITCH_ORIENTATION_VERTICAL);
lv_obj_set_size(sw, 50, 100);
sw = lv_switch_create(lv_screen_active());
lv_switch_set_orientation(sw, LV_SWITCH_ORIENTATION_VERTICAL);
lv_obj_add_state(sw, LV_STATE_CHECKED);
lv_obj_set_size(sw, 50, 100);
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/switch_1.png");
}
#endif