实现思路

  • 通过数组索引表示状态图标or文字的位置
  • 定时更新图标在数组的位置,然后再进行图标对齐,数组第n个元素向第n-1个元素对齐

具体实现

1、数据结构

struct state_prompts_pos {
    lv_obj_t* prompts;
};

static struct state_prompts_pos _state_prompts_pos[5] = {
    {.prompts = NULL},
    {.prompts = NULL},
    {.prompts = NULL},
    {.prompts = NULL},
    {.prompts = NULL},
};

#define STATE_PROMPTS_SIZE(_state_prompts)    (sizeof(_state_prompts)/sizeof(_state_prompts[0]))

  • lvgl用lv_obj_t表示元素,所以数组元素类型定义为lv_obj_t
  • 数组的每一位表示一个状态。

2、向数组插入状态图标

static void state_prompts_set_prompts(lv_obj_t* prompts)
{
     /* There has been a prompts */
    for (char i = 0; i < STATE_PROMPTS_SIZE(_state_prompts_pos); i++)
    {
       if (_state_prompts_pos[i].prompts == prompts)  
        {
            return; 
        }
    }
    
    for (char i = 0; i < STATE_PROMPTS_SIZE(_state_prompts_pos); i++)
    {
        if (_state_prompts_pos[i].prompts == NULL)    /* find a free place */
        {
            _state_prompts_pos[i].prompts = prompts;
            lv_obj_set_hidden(prompts, false);
            //printf("set %d\r\n", i);
            break;
        }
    }
}
  • 需要保持obj在数组中的唯一性,插入的obj前是否已经在数组中
  • lv_obj_set_hidden(prompts, false),图标已经提前创建好,所以直接取消隐藏显示出来

3、从数组中删除obj

static void state_prompts_reset_prompts(lv_obj_t* prompts)
{
    for (char i = 0; i < STATE_PROMPTS_SIZE(_state_prompts_pos); i++)
    {
        if (_state_prompts_pos[i].prompts == prompts)
        {
            _state_prompts_pos[i].prompts = NULL;
            lv_obj_set_hidden(prompts, true);
            //printf("reset %d\r\n", i);
            break;
        }
    }
}
  • if (_state_prompts_pos[i].prompts == prompts) 在数据找到了要删除的obj
  • lv_obj_set_hidden(prompts, true);,将图标隐藏,不显示
  • _state_prompts_pos[i].prompts = NULL;,将当前数组元素指针置NULL表示当前位置没有图标

4、更新状态图标位置

static void state_prompts_align_not_0(lv_obj_t* obj, lv_obj_t *base, lv_coord_t x, lv_coord_t y)
{
    lv_obj_align(obj, base, LV_ALIGN_OUT_LEFT_MID, x, y);
}

void lv_update_state_prompts_pos_change(void)
{
    for (char i = 0; i < (STATE_PROMPTS_SIZE(_state_prompts_pos)); i++)
    {
        if (_state_prompts_pos[i].prompts == NULL)  /* if current obj is NULL */
        {
            char y = 0;
            for (y = i; y < STATE_PROMPTS_SIZE(_state_prompts_pos)-1; y++)   
            {
                if (_state_prompts_pos[y].prompts) break;     
            }
            _state_prompts_pos[i].prompts = _state_prompts_pos[y].prompts;
            _state_prompts_pos[y].prompts = NULL;
        }
    }
    
    if (_state_prompts_pos[0].prompts)
    {
        lv_obj_t* par = lv_scr_act();
        lv_obj_align(_state_prompts_pos[0].prompts, par, LV_ALIGN_IN_TOP_RIGHT, -10, 30);
    }

    for (char i = 1; i < STATE_PROMPTS_SIZE(_state_prompts_pos); i++)
    {
        if (_state_prompts_pos[i].prompts == NULL) continue;
        
        state_prompts_align_not_0(_state_prompts_pos[i].prompts, _state_prompts_pos[i-1].prompts, -10, 0);
    }
}
  • 先更新数组元素,在进行对齐;当数组当前元素为NULL,就向上查找不为NULL的,将其移到到当前位置,然后将从图标的位置置NULL
  • if (_state_prompts_pos[0].prompts) ,特殊处理第1个图标位置
  • state_prompts_align_not_0(_state_prompts_pos[i].prompts, _state_prompts_pos[i-1].prompts, -10, 0);其他图标向前一个图标对齐

5、使用

  • 创建1个定时lvgl task,在task回调函数中调用lv_update_state_prompts_pos_change
  • 在状态的条件触发时,调用state_prompts_set_prompts插入obj
  • 在状态条件取消时,调用state_prompts_reset_prompts删除obj

实现效果

在这里插入图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐