multlist控件

1. 使用场景

在应用程序开发过程中,对于多个元素按行或按列顺序排列情况,很多具有相同的功能。比如:

  • 进度条实时显示滑动的进度

  • 多行排列需按弧形的路径实现变形缩放功能

  • 滑动结束后具备对齐动画

  • 滑动到头尾时具备回弹动画

  • 滑动滑动过程中需实现动态添加和删除

本控件主要对上述功能进行封装,并提供一系列接口用于统一管理item的位置、对齐、回弹,缩放、滑动删除等。所有item通过list链表管理,并提供item增、删、改、查等功能。

2. 功能介绍

2.1 接口说明

2.1.1** 基础对象操作 **

接口函数

功能说明

参数说明

lv_obj_t *lv_multlist_create(lv_obj_t *parent)

创建multlist列表对象(控件实例)

parent:父对象指针

void lv_multlist_refresh(lv_obj_t *multlist)

刷新列表项(滚动位置/属性变化时触发重绘)

multlist:multlist对象指针

void lv_multlist_on_pause(lv_obj_t *multlist)

暂停列表(移除所有显示项,停止刷新)

multlist:multlist对象指针

void lv_multlist_on_resume(lv_obj_t *multlist)

恢复列表(重新加载项,恢复刷新逻辑)

multlist:multlist对象指针

int lv_multlist_has_flag(lv_obj_t *multlist, uint32_t flag)

检查multlist是否设置指定功能标志位

multlist:对象指针;flag:待检查标志(如LV_MULTLIST_FLAG_LOOP)

void lv_multlist_add_flag(lv_obj_t *multlist, uint32_t flag)

为multlist添加指定功能标志位(使能对应功能)

multlist:对象指针;flag:要添加的标志(如LV_MULTLIST_FLAG_SCROLLBAR)

void lv_multlist_clear_flag(lv_obj_t *multlist, uint32_t flag)

清除multlist的指定功能标志位(关闭对应功能)

multlist:对象指针;flag:要清除的标志

2.1.2 滚动与位置管理

接口函数

功能说明

参数说明

lv_dir_t lv_multlist_get_gesture(lv_obj_t *multlist)

获取触摸手势方向(滑动方向)

multlist:对象指针;返回值:手势方向枚举

void lv_multlist_set_pos(lv_obj_t *multlist, int32_t position)

设置列表滚动位置(直接跳转,无动画)

multlist:对象指针;position:目标滚动位置(像素)

int32_t lv_multlist_get_pos(lv_obj_t *multlist)

获取当前列表滚动位置

multlist:对象指针;返回值:当前滚动位置(像素)

void lv_multlist_set_springback(lv_obj_t *multlist, lv_coord_t edge_head, int16_t edge_tail)

设置滚动回弹位置(滑动超出边界时的回弹区域)

multlist:对象指针;edge_head:头部回弹位置;edge_tail:尾部回弹位置

int32_t lv_multlist_get_springback_head(lv_obj_t *multlist)

获取头部回弹区域位置

multlist:对象指针;返回值:头部回弹位置(像素)

int32_t lv_multlist_get_springback_tail(lv_obj_t *multlist)

获取尾部回弹区域位置

multlist:对象指针;返回值:尾部回弹位置(像素)

void lv_multlist_set_scrl_pad(lv_obj_t *multlist, lv_coord_t head, lv_coord_t tail)

设置列表项边缘拖拽最大偏移量(滑动超出项区域的最大距离)

multlist:对象指针;head:头部最大偏移;tail:尾部最大偏移

void lv_multlist_set_show_pad(lv_obj_t *multlist, uint16_t head, uint16_t tail)

设置列表额外展示区域(超出该区域则自动移除项)

multlist:对象指针;head:头部额外区域;tail:尾部额外区域

void lv_multlist_set_gap(lv_obj_t *multlist, uint16_t gap)

设置列表项之间的间距

multlist:对象指针;gap:项间距(像素)

void lv_multlist_set_dir(lv_obj_t *multlist, lv_multlist_dir_t dir)

设置列表滚动方向(垂直/水平)

multlist:对象指针;dir:滚动方向枚举

lv_multlist_dir_t lv_multlist_get_dir(lv_obj_t *multlist)

获取列表滚动方向

multlist:对象指针;返回值:滚动方向枚举

void lv_multlist_enable_encoder(lv_obj_t *multlist, uint32_t ratio, uint32_t vect_max, uint8_t reverse)

启用编码器控制列表滚动

multlist:对象指针;ratio:每刻度速度增量;vect_max:最大速度;reverse:是否反转方向(1是/0否)

void lv_multlist_disable_encoder(lv_obj_t *multlist)

禁用编码器控制列表滚动

multlist:对象指针

2.1.3 对齐逻辑控制

接口函数

功能说明

参数说明

void lv_multlist_set_align(lv_obj_t *multlist, lv_multlist_align_t align, lv_coord_t offset)

设置列表默认对齐方式(滑动结束后自动对齐)

multlist:对象指针;align:对齐类型(NONE/CENTER/HEAD/TAIL);offset:对齐偏移量

void lv_multlist_set_first_align(lv_obj_t *multlist, lv_multlist_align_t align, lv_coord_t offset, int16_t index)

设置首次恢复时的对齐方式(初始化专用)

multlist:对象指针;align:对齐类型;offset:偏移量;index:对齐项索引

int32_t lv_multlist_get_focus_pos(lv_obj_t *multlist, lv_multlist_align_t align, lv_multlist_item_t *item)

计算指定项对齐到目标位置所需的滚动值

multlist:对象指针;align:对齐类型;item:目标项;返回值:对齐所需滚动位置

void lv_multlist_focus_near(lv_obj_t *multlist, int32_t offset, uint8_t dir_en, uint32_t time)

偏移滚动并对齐最近/指定方向的列表项

multlist:对象指针;offset:相对偏移量;dir_en:是否按偏移方向对齐(1是/0否);time:动画时长(0关闭动画)

void lv_multlist_align_head_to(lv_obj_t *multlist, int16_t index, lv_coord_t edge_offset)

主动将指定索引项对齐到列表头部(带边缘偏移)

multlist:对象指针;index:项索引;edge_offset:头部边缘偏移量

void lv_multlist_align_tail_to(lv_obj_t *multlist, int16_t index, lv_coord_t edge_offset)

主动将指定索引项对齐到列表尾部(带边缘偏移)

multlist:对象指针;index:项索引;edge_offset:尾部边缘偏移量

void lv_multlist_align_center_to(lv_obj_t *multlist, int16_t index, lv_coord_t edge_offset)

主动将指定索引项对齐到列表中心(带偏移)

multlist:对象指针;index:项索引;edge_offset:中心偏移量

void lv_multlist_align_to(lv_obj_t *multlist, lv_multlist_align_t align, int16_t index, lv_coord_t offset, uint32_t time)

动画方式将指定项对齐到目标位置(自定义时长)

multlist:对象指针;align:对齐类型;index:项索引;offset:对齐偏移量;time:动画时长

2.1.4 列表项管理

接口函数

功能说明

参数说明

lv_multlist_item_t *lv_multlist_add_info(lv_obj_t *multlist, lv_coord_t w, lv_coord_t h, void *info, void *user_data)

添加列表项(动态加载用,返回项句柄)

multlist:对象指针;w:项宽度;h:项高度;info:自定义数据;user_data:用户数据;返回值:项句柄

uint8_t lv_multlist_insert_info(lv_obj_t *multlist, lv_multlist_item_t *item, lv_multlist_item_t *ref)

插入列表项(无动画,参考项前插入)

multlist:对象指针;item:待插入项;ref:参考项;返回值:1成功/0失败

void lv_multlist_updata_element(lv_obj_t *multlist, lv_multlist_item_t *item, bool delete)

强制更新列表项(属性变化后调用)

multlist:对象指针;item:待更新项;delete:是否删除旧项后重建

uint8_t lv_multlist_item_remove(lv_obj_t *multlist, lv_multlist_item_t *delete_item, lv_multlist_anim_type_t type, uint8_t free)

移除列表项(带删除动画)

multlist:对象指针;delete_item:待删除项;type:动画类型;free:是否释放内存(1是/0否);返回值:1成功/0失败

uint8_t lv_multlist_item_move_before(lv_obj_t *multlist, lv_multlist_item_t *insert_item, lv_multlist_item_t *item_ref, uint8_t en_anim)

移动列表项(参考项前插入,带动画)

multlist:对象指针;insert_item:待移动项;item_ref:参考项;en_anim:是否启用动画(1是/0否);返回值:1成功/0失败

void lv_multlist_remove_info_all(lv_obj_t *multlist)

移除所有列表项

multlist:对象指针

void lv_multlist_load_all_item(lv_obj_t *multlist)

加载所有列表项(基于已添加的节点信息)

multlist:对象指针

uint32_t lv_multlist_get_info_cnt(lv_obj_t *multlist)

获取列表项信息节点数量

multlist:对象指针;返回值:节点数量

lv_multlist_item_t *lv_multlist_get_center_item(lv_obj_t *multlist)

获取当前居中的列表项

multlist:对象指针;返回值:居中项句柄

lv_multlist_item_t *lv_multlist_get_focus_item(lv_obj_t *multlist, lv_coord_t offset)

获取当前对齐的列表项(带偏移)

multlist:对象指针;offset:对齐点偏移量;返回值:对齐项句柄

lv_multlist_item_t *lv_multlist_get_item_by_index(lv_obj_t *multlist, int16_t index)

通过索引获取列表项句柄

multlist:对象指针;index:项索引;返回值:项句柄

2.1.5 动画效果控制

接口函数

功能说明

参数说明

lv_anim_t *lv_multlist_anim(void *multlist, int32_t start, int32_t end, uint32_t pred, lv_anim_exec_xcb_t exe_cb, lv_anim_ready_cb_t ready_cb, lv_anim_path_cb_t path_cb)

创建自定义列表动画

multlist:对象指针;start:起始值;end:结束值;pred:执行时长;exe_cb:执行回调;ready_cb:结束回调;path_cb:动画路径回调;返回值:动画句柄

void lv_multlist_fly_anim(lv_obj_t *multlist, lv_multlist_fly_type_t type, uint16_t delay, uint32_t time, uint8_t fly_in, lv_anim_ready_cb_t ready_cb)

设置列表项飞入/飞出动画

multlist:对象指针;type:飞行方向;delay:动画延迟;time:时长;fly_in:是否飞入(1是/0否);ready_cb:结束回调

void lv_multlist_set_anim_para(lv_obj_t *multlist, lv_coord_t rate, lv_coord_t min_time, lv_coord_t max_time)

设置动画基础参数(速度/时长范围)

multlist:对象指针;rate:每像素耗时;min_time:最短时长;max_time:最长时长

2.1.6 变形与特效配置

接口函数

功能说明

参数说明

void lv_multlist_set_pivot_offset(lv_obj_t *multlist, lv_coord_t offset_x, lv_coord_t offset_y)

设置列表项旋转中心偏移(相对中心)

multlist:对象指针;offset_x:X轴偏移;offset_y:Y轴偏移

void lv_multlist_set_focus_threshold(lv_obj_t *multlist, uint16_t dis, uint16_t vect)

设置对齐阈值(距离/速度,触发对齐的条件)

multlist:对象指针;dis:距离阈值;vect:速度阈值

void lv_multlist_set_angles(lv_obj_t *multlist, int16_t offset_angle, int16_t start_angle, int16_t end_angle)

设置环形列表角度参数(整体旋转/展示范围)

multlist:对象指针;offset_angle:整体旋转角度;start_angle:展示起始角;end_angle:展示结束角

void lv_multlist_set_radius(lv_obj_t *multlist, uint16_t r, uint16_t virt_r)

设置环形列表半径(布局/拖拽虚拟半径)

multlist:对象指针;r:布局半径;virt_r:拖拽虚拟半径

void lv_multlist_set_overlap_cnt(lv_obj_t *multlist, uint16_t overlap_cnt)

设置列表项重叠数量(环形布局专用)

multlist:对象指针;overlap_cnt:重叠项数

void lv_multlist_set_bezier_para(lv_obj_t *multlist, uint32_t range, float *pos_arr, float *neg_arr)

设置贝塞尔缩放参数(变形效果)

multlist:对象指针;range:对齐点最远偏移;pos_arr:正方向参数;neg_arr:负方向参数

void lv_multlist_set_ellipse_para(lv_obj_t *multlist, lv_coord_t x_axis, lv_coord_t y_axis)

设置椭圆偏移参数(弧形布局)

multlist:对象指针;x_axis:X轴轴距;y_axis:Y轴轴距

2.1.7 回调与事件配置

接口函数

功能说明

参数说明

void lv_multlist_set_snapshot(lv_obj_t *multlist, lv_event_cb_t cb, lv_img_cf_t cf)

设置列表快照配置(回调+图像格式)

multlist:对象指针;cb:快照回调;cf:图像颜色格式

void lv_multlist_set_refresh_cb(lv_obj_t *multlist, lv_multlist_refresh_cb refresh_cb)

设置自定义刷新回调(替代默认刷新逻辑)

multlist:对象指针;refresh_cb:刷新回调函数

void lv_multlist_set_page_anim_cb(lv_obj_t *multlist, lv_multlist_page_cb anim_cb)

设置分页模式动画回调(多页刷新时触发)

multlist:对象指针;anim_cb:分页动画回调

void lv_multlist_set_tranform_cb(lv_obj_t *multlist, lv_multlist_tranform_cb tranform_cb)

设置列表项变换回调(自定义变形逻辑)

multlist:对象指针;tranform_cb:变换回调

void lv_multlist_set_item_cb(lv_obj_t *multlist, lv_multlist_create_item_cb create_cb, lv_multlist_remove_item_cb remove_cb, lv_multlist_delete_info_cb delete_cb)

设置列表项生命周期回调(创建/移除/删除)

multlist:对象指针;create_cb:创建回调;remove_cb:移除回调;delete_cb:信息删除回调

2.2 标志含义

为了简化接口数量,将有关接口以标志位的形式提供。即只需使能或重置相应的标志位即可使能或清除相关功能。

enum
{
    LV_MULTLIST_FLAG_THROW                  = (1U << 0),  // 是否使能惯性滑动,默认使能
    LV_MULTLIST_FLAG_LOOP                   = (1U << 1),  // 是否使能循环模式,默认不使能
    LV_MULTLIST_FLAG_RESIDENCY              = (1U << 2),  // 剧中对齐时,是否是元素的间隔对准屏幕中心,默认不使能
    LV_MULTLIST_FLAG_BEZIER_ALG             = (1U << 3),  // 是否使能了贝塞尔变形,设置贝塞尔参数后只能使能
    LV_MULTLIST_FLAG_ELLIPSE_ALG            = (1U << 4),  // 是否使能椭圆形的偏移
    LV_MULTLIST_FLAG_EDGE                   = (1U << 5),  // 是否使能edge事件,用于与lvsf_multedge控件交互
    LV_MULTLIST_FLAG_SCROLLBAR              = (1U << 6),  // 是否使能进度条,用于与lvsf_scrilbar控件交互
    LV_MULTLIST_FLAG_BOUNDARY               = (1U << 7),  // 控件创建后时候不删除,只是隐藏,常驻与list节点内
    LV_MULTLIST_FLAG_LOCK_SCRL              = (1U << 8),  // 锁定scrl的滑动,
    LV_MULTLIST_FLAG_SNAPSHOT               = (1U << 9),  // 使能item的元素拍照功能
	LV_MULTLIST_FLAG_SNAPSHOT_ALL           = (1U << 10), // 将所有元素拍照,并不释放。
    LV_MULTLIST_FLAG_TOW_PAGE               = (1U << 11), // 使能两页的刷新模式
    LV_MULTLIST_FLAG_THREE_PAGE             = (1U << 12)  // 使能三页页的刷新模式
	LV_MULTLIST_FLAG_INFINTE                = (1U << 13), // 节点无限模式
    LV_MULTLIST_FLAG_ANIM_BUF               = (1U << 14), // 拍照复用动画buf
    LV_MULTLIST_FLAG_SHOW_ALL               = (1U << 15), // 仅限无限模式使用
    LV_MULTLIST_FLAG_ALIGN_HEAD             = (1U << 16), // 元素不足一屏时,默认头对齐
};
typedef uint32_t lv_multlist_flag_t;

//功能配置接口
int lv_multlist_has_flag(lv_obj_t *multlist, uint32_t flag);  	//查询是否开启了相关功能
void lv_multlist_add_flag(lv_obj_t *multlist, uint32_t flag);	//添加相应功能位标识
void lv_multlist_clear_flag(lv_obj_t *multlist, uint32_t flag);	//清楚相应功能位标识

2.3 事件说明

为了简化接口控件之间的交互逻辑,将有关回调函数以事件的形式提供,如进度条的刷新事件,对齐事件、滑动事件等。

//mutlist在特定状态会发送相应事件,通知应用程序处理事件逻辑,每种事件意义和用途可查阅具体应用案例
enum
{
    LV_EVENT_EDGE_DRAGE_REQ = _LV_EVENT_LAST + 1, //edge控件拖动请求事件
    LV_EVENT_EDGE_DRAGE_RES,	//edge控件拖动确认事件
    LV_EVENT_EDGE_DRAGE_BEGIN,	//edge控件拖动开始事件
    LV_EVENT_EDGE_DRAGING,		//edge控件拖动中事件
    LV_EVENT_EDGE_DRAGE_END,	//edge控件拖动结束事件
    LV_EVENT_EDGE_CHANGE_DIR, 	//开始滑动事件
    LV_EVENT_LIST_SCROLL_STRAT,  //开始滑动事件
    LV_EVENT_LIST_SCROLLING,	//滑动中事件
    LV_EVENT_LIST_SCROLL_END,	//滑动结束事件
    LV_EVENT_LIST_FOCUS,		//item对齐时发送该事件
    LV_EVENT_LIST_FOCUS_LOSS,	//item离开对齐位置时发送
    LV_EVENT_LIST_SCROLLBAR,	//更新进度条进度事件
    LV_EVENT_SWIPE_DELETE,		//有元素节点滑动删除时发送该事件
    LV_EVENT_LIST_LAST			//无效事件
};
//应用程序可用事件主要有滑动事件、焦点事件,滑动删除事件

以平铺的事件回调为例说明multlist事件使用方法:

void tlv_event_cb(lv_event_t *e)
{
    lv_obj_t *multlist = lv_event_get_current_target(e);
    lv_event_code_t code = lv_event_get_code(e);

    if (LV_EVENT_LIST_FOCUS == code)
    {
        //在平铺页面中,在对齐事件时激活当前tlv应用
        g_tlv->state = TLV_STATE_RESUME;
        tlv_resume_cur(g_tlv);
    }
    else if (LV_EVENT_LIST_FOCUS_LOSS == code)
    {
        //在平铺页面中,在丢失对齐事件时暂停当前tlv应用
        g_tlv->state = TLV_STATE_PAUSE;
        tlv_pause_cur(g_tlv);
    }
    else if (LV_EVENT_EDGE_DRAGE_RES == code)
    {
        lv_multlist_edge_t *edge_para = lv_event_get_param(e);
        {
            //接受到滑动开始事件时,pause当前tlv,将控制权让给edge悬浮窗口
            lv_multlist_disable_encoder(multlist);
            tlv_pause_cur(g_tlv);
            lv_multlist_add_flag(g_tlv->multlist, LV_MULTLIST_FLAG_LOCK_SCRL);
            lv_multlist_disable_encoder(g_tlv->multlist);
        }
    }
    else if (LV_EVENT_EDGE_DRAGE_END == code)
    {
        //接受到滑动结束事件时,resume当前tlv,将控制权激活
        lv_multlist_edge_t *edge_para = lv_event_get_param(e);
        if (0 == edge_para->process)
        {
            if (LV_EDGE_LEFT == edge_para->trige_type)
                tlv_anim_config(&nvm_sys_get(tlv_anim));
            tlv_resume_cur(g_tlv);
            lv_multlist_enable_encoder(g_tlv->multlist, 10, 100, true);
            lv_multlist_clear_flag(g_tlv->multlist, LV_MULTLIST_FLAG_LOCK_SCRL);
        }
    }
    else if (... == code)
    {

    }
}

2.4 对齐方式

对齐指滑动结束后item的对齐位置,主要有:无对齐、头对齐、剧中对齐、尾对齐。

  1. ​ 无对齐表示滑动结束后没有对齐动作;

  2. ​ 头对齐表示滑动结束后item元素对齐到屏幕的顶部;

  3. ​ 尾对齐表示滑动结束后item元素对齐到屏幕的低部;

  4. ​ 剧中对齐表示滑动结束后item元素对齐到屏幕中心;

//1、对齐类型
enum
{
    LV_MULTLIST_ALIGN_NONE,		//取消对齐
    LV_MULTLIST_ALIGN_CENTER,	//中心对齐
    LV_MULTLIST_ALIGN_HEAD,		//头对齐
    LV_MULTLIST_ALIGN_TAIL,		//尾对齐
} ;
typedef  uint8_t lv_multlist_align_t;
//通过设置对齐接口,指定multlist的对齐方式
void lv_multlist_set_align(lv_obj_t *multlist, lv_multlist_align_t align, lv_coord_t offset);

//2、主动对齐接口,主要用于初始化的时候指定对齐的位置
//主动调用头对齐,将指定的item对齐到头部
void lv_multlist_align_head_to(lv_obj_t *multlist, uint16_t index, lv_coord_t edge_offset);
//主动调用居中对齐,将指定的item居中对齐
void lv_multlist_align_tail_to(lv_obj_t *multlist, uint16_t index, lv_coord_t edge_offset);
//主动调用尾对齐,将指定的item对齐尾部
void lv_multlist_align_center_to(lv_obj_t *multlist, uint16_t index, lv_coord_t edge_offset);

2.5 缩放变形

multlist可以使能贝塞尔算法的缩放以及椭圆弧度的偏移,例如,单独使能贝塞尔变形以及两种算法都使能的情况如图所示

float para[] = { 0, 0, 0, 0.1f, 0.3f };
lv_multlist_set_bezier_para(multlist, LV_VER_RES_MAX*3.0f/2, para, para);
lv_multlist_set_ellipse_para(multlist, LV_VER_RES_MAX, LV_VER_RES_MAX+100);
fishy

2.5.1 贝塞尔变形

void lv_multlist_set_bezier_para(lv_obj_t *multlist, uint32_t range, float *pos_arr, float *neg_arr)

接口说明:用于设置item缩放的贝塞尔算法参数

  • multlist:multlist实例

  • range:贝塞尔算法的范围,超过此范围的item无效

  • pos_arr:正向偏移的缩放系数,大小为逐级递增,范围[0,1],数组长度为5

  • neg_arr:负向偏移的缩放系数,大小为逐级递增,范围[0,1],数组长度为5

2.5.2 弧形偏移

void lv_multlist_set_ellipse_para(lv_obj_t *multlist, lv_coord_t x_axis, lv_coord_t y_axis)

接口说明:用于设置item的弧形偏移

  • multlist:multlist实例

  • x_axis:椭圆弧度X轴方向的轴长

  • y_axis:椭圆弧度Y轴方向的轴长

2.6 回弹配置

回弹主要配置回弹区域大小,设置item超出头部或尾部拉出的最大位置,滑动结束后的回弹位置也需配置。

fishy
void lv_multlist_set_scrl_pad(lv_obj_t *multlist, lv_coord_t head, lv_coord_t tail)

接口说明:用于配置回弹最大区域

  • multlist:multlist实例

  • head:头部最大偏移距离,一般为multlist滑动方向一半

  • tail:尾部最大偏移距离,一般为multlist滑动方向一半

fishy
void lv_multlist_set_springback(lv_obj_t *multlist, lv_coord_t edge_head, int16_t edge_tail);

接口说明:用于设置回弹结束后的位置

  • multlist:multlist实例

  • edge_head:头部对齐后偏移multlist的头部间隔

  • edge_tail:尾部最对齐后偏移multlist的底部间隔

2.7 节点管理

multlist的节点值item链表中的元素,对于这些节点提供了增、删,改、查的功能,且对于节点的删除,可使用内置的删除动画。

2.7.1 节点信息添加

lv_multlist_item_t *lv_multlist_add_info(lv_obj_t *multlist, lv_coord_t w, lv_coord_t h, void *info, void *user_data);

接口说明:向item链表中添加节点信息,用于multlist节点管理

  • multlist:multlist实例

  • w:头部对齐后偏移multlist的头部间隔

  • h:尾部最对齐后偏移multlist的底部间隔

  • info:节点信息,标识item的信息

  • user_data:用户自定义数据

2.7.2 节点查询

lv_multlist_item_t *lv_multlist_get_item_by_index(lv_obj_t *multlist, int16_t index);

接口说明:通过索引值获取对应的item

  • multlist:multlist实例

  • index:索引值,唯一标识item

2.7.3 节点删除

uint8_t lv_multlist_item_remove(lv_obj_t *multlist, lv_multlist_item_t *delete_item, uint8_t en_anim, uint8_t free);

接口说明:删除指定的item,并指示是否开启删除动画

  • multlist:multlist实例

  • delete_item:需要产出的item

  • en_anim:是否启动删除动画

  • free:动画结束后是否释放内存

void lv_multlist_remove_info_all(lv_obj_t *multlist);

接口说明:清除所有的节点信息,一般用于pause后删除重新添加节点

  • multlist:multlist实例

2.7.4 节点交换

uint8_t lv_multlist_item_move_before(lv_obj_t *multlist, lv_multlist_item_t *insert_item, lv_multlist_item_t *item_ref, uint8_t en_anim);

接口说明:对于原始交换时,改变item在链表中的位置,即显示的排列顺序

  • multlist:multlist实例

  • insert_item:先通过lv_multlist_item_remove删除该节点信息,不要释放内存,即先将item从链表移除

  • item_ref:插入位置的后一个节点item,用于位置的标识

2.8 堆叠窗口

堆叠菜单以封装在multlist的实现中,在传统的初始化流程中需添加堆叠元素的个数,从而快速实现堆叠菜单

void lv_multlist_set_overlap_cnt(lv_obj_t *multlist, uint16_t overlap_cnt);

2.9 编码器接口

用于滚轮滑动时,控制item移动。

//1、使能滚轮
void lv_multlist_enable_encoder(lv_obj_t *multlist, uint32_t ratio, uint32_t vect_max, uint8_t reverse);
//2、移除滚轮
void lv_multlist_disable_encoder(lv_obj_t *multlist);

2.10 进出动画

enum
{
    LV_MULTLIST_FLY_LEFT_TOP,
    LV_MULTLIST_FLY_RIGHT_TOP,
    LV_MULTLIST_FLY_LEFT_MID,
    LV_MULTLIST_FLY_RIGHT_MID,
    LV_MULTLIST_FLY_LEFT_BOTTOM,
    LV_MULTLIST_FLY_RIGHT_BOTTOM,
};
typedef  uint8_t lv_multlist_fly_type_t;

void lv_multlist_fly_anim(lv_obj_t *multlist, lv_multlist_fly_type_t type, uint16_t delay, uint32_t time, uint8_t fly_in, lv_anim_ready_cb_t ready_cb);

接口说明:用于multlist中item的进出动画(可参考动画设置页面)

  • multlist:multlist实例

  • type:动画类型,分为上中下,以及左右

  • time:插入位置的后一个节点item,用于位置的标识

  • fly_in:指示时飞入动画,还是飞出动画

  • ready_cb:动画借宿回调函数

3. 案例详解

3.1 控件使用说明

控件根据使用场景的不用分为两种:节点信息改变和节点信息不变

方式1、节点信息不变的情况下,

1、初始化流程

  • 创建控件

  • 配置控件外观属性

  • 配置LIST特殊属性

  • 注册元素回调函数

  • 添加info节点信息

  • 设置初始对齐位置

  • 添加插件属性

2、激活流程

  • 控件激活

  • 使能编码器

3、暂停流程

  • 控件暂停

  • 重置编码器

4、销毁流程

  1. 删除控件

方式2、节点信息改变的情况

1、初始化流程

  • 创建控件

  • 配置控件外观属性

  • 配置LIST特殊属性

  • 注册元素回调函数

  • 添加插件属性

2、激活流程

  • 添加info节点信息

  • 设置初始对齐位置

  • 控件激活

  • 选择性是能编码器

3、暂停流程

  • 控件暂停

  • 删除info节点信息

  • 选择性暂停编码器

4、销毁流程

  • 删除控件

3.2 典型应用

主要参看app_mainmemu_list.c主菜单的实现。

1、初始化流程

//1.创建控件
lv_obj_t *multlist = lv_multlist_create(lv_scr_act());

//2.配置控件外观属性
lv_obj_remove_style_all(multlist);
lv_obj_set_size(multlist, LV_HOR_RES_MAX, LV_VER_RES_MAX);
lv_obj_set_style_bg_color(multlist, LV_COLOR_BLACK, 0);
lv_obj_set_style_bg_opa(multlist, 255, 0);
lv_obj_center(multlist);
lv_obj_refr_size(multlist);

//3.配置LIST特殊属性
float para[] = { 0, 0, 0, 0.1f, 0.3f };
lv_multlist_set_bezier_para(multlist, LV_VER_RES_MAX, para, para);
lv_multlist_add_flag(multlist, LV_MULTLIST_FLAG_BOUNDARY);
lv_multlist_set_gap(multlist, ICON_VER_GAP);
lv_multlist_set_scrl_pad(multlist, LV_VER_RES_MAX >> 1, LV_VER_RES_MAX >> 1);
lv_multlist_set_dir(multlist, LV_MULTLIST_DIR_VER);//LV_MULTLIST_DIR_HOR

//4.注册元素回调函数
lv_multlist_set_item_cb(multlist, mainmenu_list_new_item_cb, NULL, NULL);

//5.添加节点info信息
lv_multlist_add_info(menu, LV_HOR_RES_MAX, BG_BTN_HEIGHT, (void *)app, NULL);

//6.设置初始对齐位置
lv_multlist_set_springback(multlist, ICON_VER_GAP, ICON_VER_GAP);
lv_multlist_align_center_to(multlist, 2, 0);

//7.添加进度条
lv_scrollbar_create(multlist, LV_SCROLLBAR_SQUARE_TYPE);

2、激活流程

//1.控件激活
lv_multlist_on_resume(multlist);
//2.使能编码器
lv_multlist_enable_encoder(multlist, 100, 1000, false);

3、暂停流程

//1.暂停控件
lv_multlist_on_pause(multlist);
//2.停用编码器
lv_multlist_disable_encoder(multlist);

4、销毁流程

//1.框架自动销毁当前页面的控件
lv_obj_del(multlist)

3.3 堆叠实现

3.3.1 初始化流程

//1.创建list控件
    lv_obj_t *multlist = lv_multlist_create(parent);
    
//2.设置控件外观属性
lv_obj_remove_style_all(multlist);
lv_obj_add_flag(multlist, LV_OBJ_FLAG_EVENT_BUBBLE);
lv_obj_set_size(multlist, LV_HOR_RES_MAX, LV_VER_RES_MAX);
lv_obj_center(multlist);
lv_obj_refr_size(multlist);

//3.设置list的类型参数属性
float para_pos[] = { 0, 0.01f, 0.2f, 0.5f, 0.8f }; 	 //只需下半屏item有缩放效果
float para_neg[] = { 0, 0, 0, 0, 0 };				//上半屏不需缩放
lv_multlist_set_bezier_para(multlist, 80, para_pos, para_neg);
lv_multlist_set_gap(multlist, OVERLAP_GAP);
lv_multlist_set_dir(multlist, LV_MULTLIST_DIR_VER);
lv_multlist_set_scrl_pad(multlist, 0, LV_VER_RES_MAX >> 1);
lv_multlist_set_overlap_cnt(multlist, 3);			//堆叠菜单主要属性设置堆叠的个数
lv_multlist_set_align(multlist, LV_MULTLIST_ALIGN_TAIL, -OVERLAP_REF_POS); //设置堆叠位置

//4.设置动态item的回调函数,以及添加item的info信息到链表
lv_multlist_set_item_cb(multlist, overlap_item_create, overlap_item_delete, NULL);

//5.对齐位置与之前配置的参数有关,需最后配置
lv_multlist_set_springback(multlist, OVERLAP_GAP, OVERLAP_REF_POS);

3.3.2 激活流程

//1.滞后info节点
overlap_list_add_info(p_overlap->bg_list);
//2.使能控件
lv_multlist_on_resume(p_overlap->bg_list);
//3.设置对其item
lv_multlist_align_tail_to(p_overlap->bg_list, 1, 0);
//4.使能编码器
lv_multlist_enable_encoder(p_overlap->bg_list, 20, 300, true);

3.3.3 暂停流程

//1.删除items
lv_multlist_on_pause(p_overlap->bg_list);
//2.删除info节点信息,与激活流程相对应
lv_multlist_remove_info_all(p_overlap->bg_list);
//3.删除编码器
lv_multlist_disable_encoder(p_overlap->bg_list);

3.3.4 销毁流程

//1.框架自动删除

3.4 平铺实现

3.4.1 初始化流程

 //1.创建list控件
    lv_obj_t *multlist = lv_multlist_create(parent);
//2.设置控件外观属性
lv_obj_remove_style_all(multlist);
lv_obj_set_size(multlist, hor_res, ver_res);
lv_obj_set_style_bg_color(multlist, lv_color_hsv_to_rgb(0, 0, 0), 0);
lv_obj_set_style_bg_opa(multlist, 255, 0);
lv_obj_center(multlist);
lv_obj_refr_size(multlist);

//3.设置list的类型参数属性
lv_multlist_set_align(multlist, LV_MULTLIST_ALIGN_CENTER, 0);
lv_multlist_clear_flag(multlist, LV_MULTLIST_FLAG_THROW);
lv_multlist_set_gap(multlist, 0);
lv_multlist_set_dir(multlist, LV_MULTLIST_DIR_HOR);
lv_multlist_set_anim_para(multlist, 2, 20, 300);
lv_multlist_set_refresh_cb(multlist, tileview_refresh_cb);//配置自定义刷新函数

//4.设置动态item的回调函数,以及添加item的info信息到链表
lv_multlist_set_item_cb(multlist, tileview_create_item, tileview_delete_item, NULL);
lv_obj_add_event_cb(multlist, tileview_event_cb, LV_EVENT_ALL, tlv);

//5.对齐位置与之前配置的参数有关,需最后配置
lv_multlist_set_scrl_pad(multlist, LV_HOR_RES_MAX >> 1, LV_HOR_RES_MAX >> 1);
lv_multlist_set_springback(multlist, 0, 0);

3.4.2 激活流程

//1.添加节点信息
tileview_add_info(g_tlv->multlist);
//2.使能控件
lv_multlist_on_resume(g_tlv->multlist);
//3.使能编码器
lv_multlist_enable_encoder(g_tlv->multlist, 10, 300, true);
//4.配置对其位置
if (g_tlv->cur_item)
    lv_multlist_align_center_to(g_tlv->multlist, g_tlv->cur_item->index, 0);
else
    lv_multlist_align_center_to(g_tlv->multlist, 0, 0);
lv_multlist_focus_near(g_tlv->multlist, 0, false, false);

3.4.3 滑动过程

滑动过程中主要考虑是否注册了滑动动画接口回调函数。在动画回调函数中,主要根据multlist列表项的滑动偏移量(offset),结合 TLV 的运行状态(暂停 / 恢复)和配置的动画类型,完成列表项快照(snapshot)的创建 / 销毁、动画参数配置及元素位置更新,最终实现滑动切换时的缩放、淡入淡出、3D 翻转等视觉动画效果。

/*all tlv switch animation implementation interface*/
static void tlv_switch_anim(lv_obj_t *multlist, lv_multlist_item_t *item, int32_t offset)
{
    int32_t offset_abs = LV_ABS(offset);
    lv_coord_t hor_res = lv_disp_get_hor_res(NULL);
    lv_coord_t ver_res = lv_disp_get_ver_res(NULL);

    if (TLV_STATE_PAUSE == p_tlv->state)
    {
        /*Delete snapshot in pause state, when it exceeds the center position of the screen*/
        if (offset_abs > hor_res && item->snapshot)
        {
            lv_obj_del(item->snapshot);
            item->snapshot = NULL;
        }
        /*Create a snapshot in pause state and display it within the screen range*/
        if (offset_abs < hor_res && NULL == item->snapshot)
        {
            lv_img_dsc_t *dsc = p_tlv->img_dsc;
            lv_multlist_item_t *cent = lv_multlist_get_center_item(multlist);
            if (cent && cent->snapshot)
                dsc = (dsc == lv_img_get_src(cent->snapshot)) ? (dsc + 1) : dsc;
            tlv_item_take_snapshot(item, dsc);
        }
        if (item->snapshot)
            lv_obj_clear_flag(item->snapshot, LV_OBJ_FLAG_HIDDEN);
    }
    /*Hide snapshot for all resume statuses*/
    if (TLV_STATE_RESUME == p_tlv->state && item->snapshot)
    {
        lv_obj_del(item->snapshot);
        item->snapshot = NULL;
        lv_obj_clear_flag(item->element, LV_OBJ_FLAG_HIDDEN);
    }

    if (item->snapshot)
    {
        /*Select the corresponding multanim animation for the type with more TLV configuration animation*/
        uint8_t anim_type = TLV_ANIM_TYPE_FIRST;
        uint32_t target_anim = LV_MULTANIM_ZOOM;
        switch (p_tlv->anim_cfg.trans)
        {
        case TLV_ANIM_TRANS_ZOOM:
            target_anim = LV_MULTANIM_ZOOM;
            break;
        case TLV_ANIM_TRANS_FADE:
            target_anim = LV_MULTANIM_FADE;
            anim_type = TLV_ANIM_TYPE_SECOND;
            break;
        case TLV_ANIM_TRANS_TURN_3D_HOR:
            target_anim = LV_MULTANIM_3D;
            break;
        case TLV_ANIM_TRANS_TURN_Y:
            target_anim = LV_MULTANIM_SCALE;
            break;
        case TLV_ANIM_TRANS_DRAG:
            target_anim = LV_MULTANIM_TURN;
            break;
        default:
            break;
        }

        if (NULL == p_tlv->multanim)
        {
            p_tlv->multanim = lv_multanim_create(p_tlv->multlist);
            lv_obj_add_flag(p_tlv->multanim, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_EVENT_BUBBLE | LV_OBJ_FLAG_CLICKABLE);
        }

        if (target_anim != lv_multanim_set_type(p_tlv->multanim, target_anim))
        {
            /*For types that use mask animations, the corresponding mask resources need to be loaded and released when switching out*/

            if (LV_MULTANIM_FADE == target_anim || LV_MULTANIM_OPEN == target_anim)
            {
                if (NULL == p_tlv->mask_l)
                    p_tlv->mask_l = lv_multanim_create_mask(APP_GET_IMG_FROM_APP(trans_anim, img_mask_left));
                if (NULL == p_tlv->mask_r)
                    p_tlv->mask_r = lv_multanim_create_mask(APP_GET_IMG_FROM_APP(trans_anim, img_mask_right));
                lv_multanim_set_mask(p_tlv->multanim, p_tlv->mask_l, p_tlv->mask_r);
            }
            else
            {
                lv_img_dsc_t *mask_l = (lv_img_dsc_t *)APP_GET_IMG_FROM_APP(trans_anim, img_mask_left);
                lv_img_dsc_t *mask_r = (lv_img_dsc_t *)APP_GET_IMG_FROM_APP(trans_anim, img_mask_right);

                if (p_tlv->mask_l && mask_l != p_tlv->mask_l)
                    lv_multanim_free_mask(p_tlv->mask_l);
                if (p_tlv->mask_r && mask_r != p_tlv->mask_r)
                    lv_multanim_free_mask(p_tlv->mask_r);
                p_tlv->mask_l = NULL;
                p_tlv->mask_r = NULL;
            }
            /*For scaling animations, it is necessary to configure appropriate zoom parameters*/
            if (LV_MULTANIM_ZOOM == target_anim)
                lv_multanim_set_zoom(p_tlv->multanim, APP_TRANS_ANIM_ZOOM_NONE, APP_TRANS_ANIM_ZOOM_NONE >> 1);
            else if (LV_MULTANIM_3D == target_anim)
                lv_multanim_set_zoom(p_tlv->multanim, APP_TRANS_ANIM_ZOOM_NONE + 2, APP_TRANS_ANIM_ZOOM_NONE * 0.7f);
            else if (LV_MULTANIM_SCALE == target_anim)
                lv_multanim_set_zoom(p_tlv->multanim, APP_TRANS_ANIM_ZOOM_NONE + 2, APP_TRANS_ANIM_ZOOM_NONE + 2);
            else
                lv_multanim_set_zoom(p_tlv->multanim, APP_TRANS_ANIM_ZOOM_NONE, APP_TRANS_ANIM_ZOOM_NONE);
        }

        if (LV_MULTANIM_ZOOM != target_anim)
            lv_obj_center(item->snapshot);
        int32_t proc = (offset << 10) / hor_res;
        if (anim_type == TLV_ANIM_TYPE_FIRST)
        {
            //animation type 1:
            if (offset_abs <= (hor_res * 3 / 4))
            {
                if (offset_abs <= (hor_res >> 2))
                {
                    if (LV_MULTANIM_ZOOM != target_anim)
                        lv_img_set_zoom(item->snapshot, APP_TRANS_ANIM_ZOOM_NONE);
                    lv_multanim_set_major_img(p_tlv->multanim, item->snapshot);
                }
                if (item->snapshot == lv_multanim_get_minor_img(p_tlv->multanim))
                    proc = proc > 0 ? (proc - 1024) : (proc + 1024);
                lv_multanim_set_process(p_tlv->multanim, proc);
            }
            else
            {
                lv_obj_move_background(item->snapshot);
                lv_multanim_set_minor_img(p_tlv->multanim, item->snapshot);
            }
        }
        else
        {
            if (offset_abs <= (hor_res >> 1))
            {
                lv_obj_center(item->snapshot);
                lv_multanim_set_major_img(p_tlv->multanim, item->snapshot);
                lv_multanim_set_process(p_tlv->multanim, proc);
            }
            else
            {
                lv_obj_move_background(item->snapshot);
                lv_multanim_set_minor_img(p_tlv->multanim, item->snapshot);
            }
        }
    }
    if (item->element)
    {
        lv_obj_align(item->element, LV_ALIGN_CENTER, offset, 0);
    }

}

3.4.4 暂停流程

//1.删除所有items
lv_multlist_on_pause(g_tlv->multlist);
//2.删除节点info信息
lv_multlist_remove_info_all(g_tlv->multlist);
//3.删除编码器
lv_multlist_disable_encoder(g_tlv->multlist);

3.4.5 销毁流程

//1、框架自动删除

3.5 Demo实现

Demo App位于solution\examples\_app_demo\application\multlist,包含了multlist典型应用场景,案例主要介绍了水平和竖直方向两种类别、常规滑动列表以及按页滑动方式的实现,之外对于复杂的场景需要用到的自定义刷新回调的情况也有案例。

  1. 普通列表显示方式,可带有贝塞尔变形的。 变形后点击事件可按区域识别

参考代码solution\examples\_app_demo\application\multlist\demo_multlist_list.c

水平方向滑动场景

fishy

竖直方向滑动场景

fishy
  1. 按页翻转方式

参考代码solution\examples\_app_demo\application\multlist\demo_multlist_page.c

水平方向翻页场景

fishy

竖直方向翻页场景

fishy
  1. 主要应用于小图标的切换显示,需自定义图片的透明度,缩放系数等

参考代码solution\examples\_app_demo\application\multlist\demo_multlist_anim.c

自定义水平方向场景

fishy

自定义竖直方向场景

fishy
  1. 对话场景,适用于节点信息动态添加和删除的情况

参考代码solution\examples\_app_demo\application\multlist\demo_multlist_dialog.c

fishy

4. 贝塞尔参数调节

4.1 核心概念:曲率与缩放效果的对应关系

  • 贝塞尔曲率:由5个递增数组元素(索引0固定为0)拟合出的曲线弯曲程度,是决定item缩放幅度的核心;

  • 曲率大小 → 缩放效果

    • 曲率越大 → 曲线越“弯” → item缩放幅度越大(比如从0到1.0的突变,缩放感极强);

    • 曲率越小 → 曲线越“平” → item缩放幅度越小(比如从0到0.2的缓慢递增,缩放感极弱);

    • 曲率为0 → 曲线为直线 → 无缩放(所有item缩放系数一致)。

曲率与数组的映射逻辑: 数组元素的差值大小直接决定曲率:

  • 相邻元素差值大 → 曲率大 → 缩放效果强;

  • 相邻元素差值小 → 曲率小 → 缩放效果弱;

  • 所有元素差值相等 → 曲率为0 → 线性缩放(无曲线效果)。

4.2 常用参数分析

以常用场景4的参数{0,0,0,0.1f,0.3f}为例分析,下表展示曲率和缩放效果:

数组段

相邻元素差值

曲率大小

缩放效果

0→0(索引0-1)

0

0

无缩放

0→0(索引1-2)

0

0

无缩放

0→0.1(索引2-3)

0.1

轻微缩放

0.1→0.3(索引3-4)

0.2

中等缩放

整体效果:该数组的曲率整体偏小,仅在后两段有轻微曲率,表现为“起始元素几乎无缩放,偏移越远item越小。

4.3 场景分析

场景1:曲率为0(无线性缩放)

  • 调节思路:所有相邻元素差值相等,曲线变为直线,无曲率;

  • 示例参数(零曲率):

    float pos_arr[5] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
    float neg_arr[5] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
    
  • 曲率&效果分析:

    • 差值一致 → 曲率为0 → 无曲线效果;

    • 视觉效果:item滑动无缩放,等同于未使能贝塞尔变形。

fishy

场景2:曲率固定(非0)(固定缩放)

  • 调节思路:缩小相邻元素的差值,让曲线更“平”,缩放效果更柔和;

  • 示例参数(低曲率):

      float pos_arr[5] = { 0.0f, 0.05f, 0.1f, 0.15f, 0.2f };
      float neg_arr[5] = { 0.0f, 0.05f, 0.1f, 0.15f, 0.2f };
    
  • 曲率&效果分析:

    • 所有相邻差值0.05→ 曲率为0(固定不变);

    • 视觉效果:所有item相同的缩放系数,过渡无突变。

fishy

场景3:曲率递增(缩放系数递增)

  • 调节思路:固定相邻元素的差值递增,让曲线更“平”,缩放效果更柔和;

  • 示例参数(低曲率):

      float pos_arr[5] = { 0.0f, 0.05f, 0.15f, 0.3f, 0.5f };
      float neg_arr[5] = { 0.0f, 0.05f, 0.15f, 0.3f, 0.5f };
    
  • 曲率&效果分析:

    • 所有相邻差值0.05 → 0.1 → 0.15 → 0.2 曲率递增0.05(曲线近乎直线);

    • 视觉效果:随着偏移越大,缩放系数越大,缩放系数递增近视固定。

fishy

场景4:局部调节曲率(差异化缩放) 调节思路:仅调整某一段的差值,实现“前半段弱缩放,后半段强缩放”;

  • 示例参数(低曲率):

      float pos_arr[5] = { 0 , 0 , 0 , 0.1f , 0.3f };
      float neg_arr[5] = { 0 , 0 , 0 , 0.1f , 0.3f };
    
  • 曲率&效果分析:

    • 索引0-2差值0 / 0(没有曲率)→ 前半段几乎无缩放;

    • 索引2-4差值0.1/0.2(大曲率)→ 后半段快速放大;

    • 视觉效果:item先“保持原样”,再“快速缩小”。

fishy

场景5:非对称曲率 调节思路:上下曲率配置为非对称的情况;

  • 示例参数(低曲率):

      float pos_arr[5] = { 0 , 0 , 0 , 0 , 0 };
      float neg_arr[5] = { 0 , 0 , 0 , 0.1f , 0.4f };
    
  • 曲率&效果分析:

    • pos_arr上半部分曲率固定为0;

    • neg_arr下半部分曲率逐渐变大;

    • 该方式需保证上下过度的曲率大小一样,否则会有跳变;

fishy

场景6:曲率异常跳变 调节思路:差值时正时负,为负数时显示为放大效果

  • 示例参数(低曲率):

      float pos_arr[5] = { 0.0f,0.15f,0.1f,0.05f,0.1f };
      float neg_arr[5] = { 0.0f,0.15f,0.1f,0.05f,0.1f };
    
  • 曲率&效果分析:

    • 当曲率为正时,元素逐渐缩小,

    • 当曲率为负时,元素逐渐放大,

fishy

4.4 曲率调节的关键注意事项

  1. 递参数调节本质贝塞尔曲率由数组相邻元素的差值决定:差值越大曲率越大,缩放效果越明显;差值越小曲率越小,缩放越柔和;

  2. 递增规则优先:无论调节曲率大小,必须保证数组索引n 索引n+1,比如不能为了增大曲率设置{0,0,0.5,0.3,1.0}(索引3 < 索引2),否则曲率计算异常,缩放效果乱跳;

  3. 合适的range配置:range设置太小时,元素可能超过该区域而无法缩放,太大可能只用了曲线的部分区域,一般配置为multlist的长度,避免效果异常。;

  4. 参数调整方法:将5个参数全配置为0,从后向前调整参数,如{0,0,0,0,0.5f} -> {0,0,0,0.3f,0.5f} -> {0,0,0.5,0.3f,0.5f} 。只有确定最后一个参数后,再依次微调前面的参数。

5. 注意事项

5.1 功能模块化设计(插件化封装)

将核心功能拆解为独立插件并基于multlist主体实现事件交互,插件支持按需配置使能,保障功能逻辑的独立性与场景适配性:

  • lvsf_multswipe:实现滑动删除功能,涵盖左滑/上滑删除两种操作方式,内置两类删除风格样式;

  • lvsf_multedge:提供侧边栏、上下拉等交互能力,效果类似可自动显隐的悬浮窗口;

  • lvsf_scrollbar:实现进度条功能,支持圆形、长条形两种视觉样式。

5.2 核心回调函数注意事项(3类关键回调)

5.2.1 元素(element)创建/删除回调

  • 创建回调lv_multlist_create_item_cb 用于element的动态创建,返回值需为item->element对应的元素对象;

  • 删除回调lv_multlist_remove_item_cbelement删除前触发,禁止在回调内直接删除element元素,核心用途为数据订阅退订、上层应用通知等资源清理操作。

5.2.2 信息(info)节点删除回调

  • 接口背景:lv_multlist_add_info中传入的infouser_data可能为动态分配内存,需在item节点删除时释放回收;

  • 回调函数:lv_multlist_delete_info_cb

  • 关键注意:该回调在lv_multlist_remove_item_cb之后执行,此时element已释放,禁止访问element相关数据

5.3 节点宽高配置注意事项

通过lv_multlist_add_info(menu, LV_HOR_RES_MAX, BG_BTN_HEIGHT, (void *)app, NULL);添加节点时,需指定item的宽高:

  • 若应用场景无法提前确定准确值,可先预估宽高;

  • 宽高值偏差会直接导致元素对齐位置偏移进度条显示进度不准,需尽可能贴近实际尺寸。

5.4 节点清空后的位置复位规则

multlist默认会保留历史位置信息,若直接删除所有节点后调用对齐操作,可能因历史pos超出最大偏移量导致item显示不全:

  • 操作要求:清空节点前,需先将multlist的位置重置为指定pos(如初始位置),再执行节点删除操作,避免对齐时位置异常。