【LVGL】roller选项列表问题

       在实际应用中,可能会使用roller控件实现时间选择功能,选项列表只有24小时的时候,界面显示是正常的。但当选项列表是60分钟的时候,由于列表过长,显示就会出现问题。如众多帖子描述,只需要在lv_conf.h中打开宏 LV_USE_LARGE_COORD 即可。

【LVGL】roller选项列表问题_第1张图片

       虽然解决了显示问题,却发现在roller控件创建的时候耗时严重,尤其是当程序运行在资源有限的嵌入式设备上,问题更加明显,进而导致页面打开卡顿,影响体验。

        换一种思路,如果每次只设置5个选项给roller控件,在每次滚动时重新计算并设置选项列表……

#define OPTION_FMT       "%02d\n%02d\n%02d\n%02d\n%02d"    // 选项列表格式
#define MASTER_INDEX     2                                 // 列表为5项,中间项索引为2
#define OPTION_LEN       32                                // 列表字符串buffer长度

/**
 * @brief 选项列表最大值最小值
*/
typedef struct {
    int min;
    int max;
} roller_range_t;

/**
 * @brief 计算选项列表
 * @param val 当前选中的值
 * @param buf 选项列表字符串buffer
 * @param len 选项列表字符串buffer长度
 * @param min 控件选项列表最小值
 * @param max 控件选项列表最大值
*/
static void calc_roller_option( int val, char* buf, int len, int min, int max )
{
    int left1  = val - 1;
    int left2  = val - 2;
    int right1 = val + 1;
    int right2 = val + 2;
    int range = max - min + 1;

    if ( left1 < min ) {
        left1 += range;
    }

    if ( left2 < min ) {
        left2 += range;
    }

    if ( right1 > max ) {
        right1 -= range;
    }

    if ( right2 > max ) {
        right2 -= range;
    }

    snprintf( buf, len, OPTION_FMT, left2, left1, val, right1, right2 );

    return;
}

/**
 * @brief roller控件事件回调函数
 * @param e 
*/
static void roller_event_cb( lv_event_t* e )
{
    if ( LV_EVENT_VALUE_CHANGED == lv_event_get_code( e ) ) {
        lv_obj_t* obj = lv_event_get_target( e );

        roller_range_t* range = (roller_range_t*)(obj->user_data);

        char buf[OPTION_LEN] = "\0";
        int val = 0;
        lv_roller_get_selected_str( obj, buf, OPTION_LEN );
        val = atoi( buf );

        calc_roller_option( val, buf, OPTION_LEN, range->min, range->max );
        lv_roller_set_options( obj, buf, LV_ROLLER_MODE_NORMAL );    // 这里不需要设置无限模式,计算列表时已处理列表循环
        lv_roller_set_selected( obj, MASTER_INDEX, LV_ANIM_OFF );
    }

    return;
}

/**
 * @brief 创建roller控件
 * @param parent 父窗体
 * @param def_val 默认值
 * @param min_val 最小值
 * @param max_val 最大值
 * @return 已创建的roller对象指针
*/
static lv_obj_t* create_roller( lv_obj_t* parent, int def_val, int min_val, int max_val )
{
    lv_obj_t* roller = lv_roller_create( parent );
    roller_range_t* range = (roller_range_t*)malloc( sizeof( roller_range_t ) );

    if ( NULL != range ) {
        range->min = min_val;
        range->max = max_val;
    }

    roller->user_data = (void*)range;

    char option[OPTION_LEN] = "\0";
    calc_roller_option( def_val, option, OPTION_LEN, min_val, max_val );

    lv_roller_set_options( roller, option, LV_ROLLER_MODE_NORMAL );
    lv_roller_set_selected( roller, MASTER_INDEX, LV_ANIM_OFF );
    lv_obj_add_event_cb( roller, roller_event_cb, LV_EVENT_VALUE_CHANGED, NULL );

    return roller;
}

/**
 * @brief 设置roller当前值
 * @param roller 控件对象
 * @param val 当前值
*/
static void set_roller_cur_val( lv_obj_t* roller, int val )
{
    roller_range_t* range = (roller_range_t*)(roller->user_data);
    char buf[OPTION_LEN] = "\0";

    calc_roller_option( val, buf, OPTION_LEN, range->min, range->max );
    lv_roller_set_options( roller, buf, LV_ROLLER_MODE_NORMAL );
    lv_roller_set_selected( roller, MASTER_INDEX, LV_ANIM_OFF );
}

void main( void )
{
    lv_obj_t* roller1 = create_roller( lv_scr_act(), 0, 0, 59 );
    lv_roller_set_visible_row_count( roller1, 3 );
    lv_obj_center( roller1 );
    set_roller_cur_val( roller1, 24 );

    return;
}

        轻松实现超长选项列表的roller控件,不仅分散了创建roller时设置option的耗时,避免页面创建时卡顿,同时也可以不需要 LV_USE_LARGE_COORD 的支持。

你可能感兴趣的:(LVGL,LVGL,roller)