multlist控件
一、使用场景
在应用程序开发过程中,对于多个元素按行或按列顺序排列情况,很多具有相同的功能。比如:
进度条实时显示滑动的进度
多行排列需按弧形的路径实现变形缩放功能
滑动结束后具备对齐动画
滑动到头尾时具备回弹动画
滑动滑动过程中需实现动态添加和删除
本控件主要对上述功能进行封装,并提供一系列接口用于统一管理item的位置、对齐、回弹,缩放、滑动删除等。所有item通过list链表管理,并提供item增、删、改、查等功能。
二、功能介绍
1、功能配置
为了简化接口数量,将有关接口以标志位的形式提供。即只需使能或重置相应的标志位即可使能或清除相关功能。
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_TOW_PAGE = (1U << 10), // 使能两页的刷新模式
LV_MULTLIST_FLAG_THREE_PAGE = (1U << 11) // 使能三页页的刷新模式
};
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、事件说明
为了简化接口控件之间的交互逻辑,将有关回调函数以事件的形式提供,如进度条的刷新事件,对齐事件、滑动事件等。
//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)
{
}
}
3、对齐方式
对齐指滑动结束后item的对齐位置,主要有:无对齐、头对齐、剧中对齐、尾对齐。
无对齐表示滑动结束后没有对齐动作;
头对齐表示滑动结束后item元素对齐到屏幕的顶部;
尾对齐表示滑动结束后item元素对齐到屏幕的低部;
剧中对齐表示滑动结束后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);
4、缩放变形
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);

贝塞尔变形
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
弧形偏移
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轴方向的轴长
5、回弹配置
回弹主要配置回弹区域大小,设置item超出头部或尾部拉出的最大位置,滑动结束后的回弹位置也需配置。

void lv_multlist_set_scrl_pad(lv_obj_t *multlist, lv_coord_t head, lv_coord_t tail)
接口说明:用于配置回弹最大区域
multlist:multlist实例
head:头部最大偏移距离,一般为multlist滑动方向一半
tail:尾部最大偏移距离,一般为multlist滑动方向一半

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的底部间隔
6、节点管理
multlist的节点值item链表中的元素,对于这些节点提供了增、删,改、查的功能,且对于节点的删除,可使用内置的删除动画。
节点信息添加
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:用户自定义数据
节点查询
lv_multlist_item_t *lv_multlist_get_item_by_index(lv_obj_t *multlist, int16_t index);
接口说明:通过索引值获取对应的item
multlist:multlist实例
index:索引值,唯一标识item
节点删除
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实例
节点交换
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,用于位置的标识
7、堆叠窗口
堆叠菜单以封装在multlist的实现中,在传统的初始化流程中需添加堆叠元素的个数,从而快速实现堆叠菜单
void lv_multlist_set_overlap_cnt(lv_obj_t *multlist, uint16_t overlap_cnt);
8、编码器接口
用于滚轮滑动时,控制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);
9、进出动画
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:动画借宿回调函数
三、案例详解
1、控件使用说明
控件根据使用场景的不用分为两种:节点信息改变和节点信息不变
方式1、节点信息不变的情况下,
1、初始化流程
创建控件
配置控件外观属性
配置LIST特殊属性
注册元素回调函数
添加info节点信息
设置初始对齐位置
添加插件属性
2、激活流程
控件激活
使能编码器
3、暂停流程
控件暂停
重置编码器
4、销毁流程
删除控件
方式2、节点信息改变的情况
1、初始化流程
创建控件
配置控件外观属性
配置LIST特殊属性
注册元素回调函数
添加插件属性
2、激活流程
添加info节点信息
设置初始对齐位置
控件激活
选择性是能编码器
3、暂停流程
控件暂停
删除info节点信息
选择性暂停编码器
4、销毁流程
删除控件
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、堆叠实现
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);
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、暂停流程
//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);
4、销毁流程
//1.框架自动删除
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);
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)滑动过程
滑动过程中主要考虑是否注册了滑动动画接口回调函数。在动画回调函数中,根据item元素的位置实现所有动画播放。
1、滑动结束时,隐藏拍照
2、滑动开始,拍照当前tlv
3、获取当前的动画类型
4、创建multanim实例,
5、设置当前动画类型,并初始化相关参数
5、配置主、次动画图片
6、设置当前的动画进度
static void tlv_switch_anim(lv_obj_t *multlist, lv_multlist_item_t *item, int32_t offset)
{
int32_t offset_abs = LV_ABS(offset);
if (TLV_STATE_PAUSE == p_tlv->state)
{
/*Delete snapshot in pause state, when it exceeds the center position of the screen*/
if (offset_abs > LV_HOR_RES_MAX && 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 < LV_HOR_RES_MAX && 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);
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 defined(SOLUTION_RES_USING_NAND) || defined(EX_RES_USING_FILE_MODE)
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
{
if (p_tlv->mask_l)
lv_multanim_free_mask(p_tlv->mask_l);
if (p_tlv->mask_r)
lv_multanim_free_mask(p_tlv->mask_r);
p_tlv->mask_l = NULL;
p_tlv->mask_r = NULL;
}
#else
lv_multanim_set_mask(p_tlv->multanim, APP_GET_IMG_FROM_APP(trans_anim, img_mask_left), APP_GET_IMG_FROM_APP(switch_anim, img_mask_right));
#endif
/*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) / LV_HOR_RES_MAX;
if (anim_type == TLV_ANIM_TYPE_FIRST)
{
//animation type 1:
if (offset_abs <= (LV_HOR_RES_MAX >> 1))
{
if (offset_abs <= (LV_HOR_RES_MAX >> 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 <= (LV_HOR_RES_MAX >> 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);
}
}
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);
5、销毁流程
//1、框架自动删除
5、Demo实现
Demo App位于solution\examples\_app_demo\application\multlist
,包含了multlist典型应用场景,案例主要介绍了水平和竖直方向两种类别、常规滑动列表以及按页滑动方式的实现,之外对于复杂的场景需要用到的自定义刷新回调的情况也有案例。
1、普通列表显示方式,可带有贝塞尔变形的。 变形后点击事件可按区域识别。参考代码solution\examples\_app_demo\application\multlist\demo_multlist_list.c
水平方向滑动场景

竖直方向滑动场景

2、按页翻转方式,参考代码solution\examples\_app_demo\application\multlist\demo_multlist_page.c
水平方向翻页场景

竖直方向翻页场景

3、主要应用于小图标的切换显示,需自定义图片的透明度,缩放系数等,参考代码solution\examples\_app_demo\application\multlist\demo_multlist_anim.c
自定义水平方向场景

自定义竖直方向场景

4、对话场景,适用于节点信息动态添加和删除的情况,参考代码solution\examples\_app_demo\application\multlist\demo_multlist_dialog.c

四、注意事项
1、在进行功能划分时,将有关的功能以插件的形式进行了封装,便于逻辑功能的独立性。由于插件与multlist通过相应的事件交互,插件是配配置的,即可根据实际场景,对某些插件进行使能。multist为所有插件的主体,插件如下:
1) lvsf_multswipe:主要负责滑动删除的功能,包括左滑删除和上滑删除,以及两种内置的删除风格样式
2) lvsf_multedge:主要实现侧边栏、上下拉等。类似于自动显示和隐藏的悬浮窗口
3) lvsf_scrollbar:主要实现进度条功能,包括圆形和长条形。
2、回调函数主要有3个需要注意
element的动态创建与删除,创建时的返回值为item->element的元素,删除回调为element元素在删除前调用,回调里不能删除element元素,该回调的主要目的是进行数据订阅的退订、上层应用的通知等。
typedef lv_obj_t *(*lv_multlist_create_item_cb)(lv_obj_t *parent, lv_multlist_item_t *item);
typedef void (*lv_multlist_remove_item_cb)(lv_multlist_item_t *);
info节点信息的删除回调,考虑到添加info函数lv_multlist_add_info中的info和user_data有可能是动态分配的情况,所以在item节点被删除时,需对该内存进行释放回收,由于该接口在调用lv_multlist_remove_item_cb之后,所以在该回调函数处理过程中element已经释放,不能访问。
`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);`
`typedef void (*lv_multlist_delete_info_cb)(lv_multlist_item_t *);`
3、通过lv_multlist_add_info(menu, LV_HOR_RES_MAX, BG_BTN_HEIGHT, (void *)app, NULL);
添加的节点信息包含了item的宽度和高度,对于某些应用场景事先不能确认的,可以预估item的宽高。该值的偏差会影响对齐的位置,以及进度条的进度偏差。
4、由于multlist默认会保持之前的位置,所以在删除所有节点信息后位置信息还保持之前的pos。如果再次调用对齐时,会时一次的移动位置超过最大的偏移,有可能item显示不全。所以在清楚节点前,需先将位置置到指定pos。