平铺(TLV)¶
1. 创建一个平铺应用¶
1.1. 简介¶
平铺应用是智能穿戴设备(如手表)中由主应用框架管理的核心交互界面集合,包含表盘、上下快捷页面及左右子应用,作为用户日常操作的主要入口,支持展示各类功能模块(如活动记录、心率监测等)并提供便捷的切换交互。
平铺功能通过
APP_TLV_USED使能,配置路径为:menuconfig (Top) → Gui Framwork Config → Tileview Config。使能平铺相关的宏之后,Solution 框架将提供自动注册以及调度机制
支持最少一个子应用,没有最大数量限制(视内存情况而定)
支持切换动画平移、缩放、弧形旋转,水平 3d 翻转、绕 Y 轴翻转,以及用户自定义动画
他的调度与主应用框架类似,通过 msg_handle 进行,msg 中的参数是该应用的节点信息,其结构是
tlv_node_t
注:有的用户也习惯将平铺应用称作一级页面
1.2. 注册平铺应用¶
注册平铺应用需使用TLV_REGISTER宏,语法如下:
TLV_REGISTER(priority, id, name, thumb_img, ptr_size)
参数说明:
priority:应用优先级,数值越小优先级越高,应用按优先级排序,支持动态调整(如编辑页面拖动排序)
id:应用标识字符串,框架调度时使用,需在平铺框架中保持唯一
name:应用显示标题,多语言字符串,仅用于显示
thumb_img:应用缩略图,用于编辑模式
ptr_size:应用全局内存大小,由框架统一申请和释放,页面可直接使用
1.3. 平铺应用实现¶
平铺应用的实现主要围绕生命周期函数和事件处理,核心包括以下几个部分:
1.3.1 生命周期函数¶
平铺应用有四个主要的生命周期函数,用于管理应用的创建、显示、隐藏和销毁:
on_start():应用初始化时调用,用于创建基本 UI 元素
on_resume():应用即将显示时调用,用于初始化动态元素和启动动画
on_pause():应用即将隐藏时调用,用于暂停动画和释放临时资源
on_stop():应用销毁时调用,用于释放所有资源
1.3.2 事件处理¶
应用需要处理各种用户交互事件和系统事件,如触摸、滑动、按键等,确保应用能够正确响应用户操作。
1.3.3 核心功能模块¶
平铺页面主要包含四部分核心功能:
TLV 应用管理
显示已设定的 TLV 应用和表盘
长按进入 TLV 编辑页面,支持 TLV 的添加、删除和排序操作
表盘管理
提供表盘的编辑与选择功能
支持将指定表盘设为 TLV 应用
包含六扇门表盘选择页面
辅助窗口
下拉消息框:显示通知和系统消息
上拉堆叠菜单:提供快捷功能入口
右滑侧边栏:展示附加信息或功能
快捷页面:快速访问常用功能
所有辅助框均通过lv_multegde控件封装了拖拽交互,简化开发
切换动画
TLV 滑动切换动画配置
上下拉页面切换动画管理
1.3.4 开发注意事项¶
帧率优化 平铺页面同时存在左、中、右三个子应用,为保证高刷新率,需注意:
页面设计尽量简洁,避免大长页
复杂页面考虑使用进场动画,延迟复杂元素初始化,既提高帧率又增加动感
禁止在平铺页面中进行 flash 读写和 delay 操作,历史数据应提前读取到内存
避免直接使用大尺寸的圆或弧,建议使用图片替代;若图片无法满足,可考虑使用绘制功能
状态机差异 平铺应用的状态机切换与普通应用不同,需特别注意:
普通应用:start->resume->pause->stop(顺序切换)
平铺应用可能的状态切换:
start->resume->pause->stop
start->pause->stop
start->stop
这种设计旨在提高状态切换效率,省去非必要过程,因此开发时需兼容以上所有场景。
1.3.5 示例代码¶
以下是一个活动记录应用的实现示例,使用进场动画来提高帧率:
static void on_start(void *param)
{
/* 获取该应用的parent obj */
lv_obj_t *parent = TLV_GET_NODE_PARENT;
/* 获取框架申请的全局内存 */
p_activity = TLV_GET_NODE_MEM_PTR;
LV_ASSERT_NULL(p_activity);
/* 创建背景图片 */
lv_obj_t *bg_img = lv_img_create(parent);
lv_img_set_src(bg_img, APP_GET_IMG(img_activity_bg_tlv));
lv_obj_center(bg_img);
lv_obj_add_flag(bg_img, LV_OBJ_FLAG_EVENT_BUBBLE);
/* 创建透明背景容器,其他子控件均创建在该容器上 */
lv_obj_t *bg_cont = lv_obj_create(bg_img);
lv_obj_remove_style_all(bg_cont);
lv_obj_set_size(bg_cont, 400, 210);
lv_obj_set_style_bg_color(bg_cont, LV_COLOR_YELLOW, LV_PART_MAIN);
lv_obj_set_style_bg_opa(bg_cont, 0, LV_PART_MAIN);
lv_obj_refr_size(bg_cont);
lv_obj_align(bg_cont, LV_ALIGN_TOP_MID, 0, 0);
lv_obj_refr_pos(bg_cont);
lv_obj_add_flag(bg_cont, LV_OBJ_FLAG_EVENT_BUBBLE);
lv_obj_clear_flag(bg_cont, LV_OBJ_FLAG_SCROLLABLE);
}
static void on_resume(void *param)
{
/* 初始化其他子控件 */
app_activity_init(0);
/* 启动进场动画,将arc页面初始化放在动画中,提高帧率并增加动感 */
lv_anim_t n_anim;
lv_anim_init(&n_anim);
lv_anim_set_values(&n_anim, 0, 1024);
lv_anim_set_time(&n_anim, 5000);
lv_anim_set_exec_cb(&n_anim, arc_anim_cb);
lv_anim_set_repeat_count(&n_anim, 500);
lv_anim_set_var(&n_anim, p_activity);
lv_anim_start(&n_anim);
}
static void on_pause(void *param)
{
/* 删除页面上的动画,防止页面停止时动画仍在运行引发异常 */
for (uint16_t i = 0; i < 3; i++)
{
lv_anim_del(&p_activity->arc_arr[i], NULL);
}
}
static void on_stop(void *param)
{
/* 指针变量置空 */
p_activity = NULL;
}
/* 注册活动记录的平铺应用 */
TLV_REGISTER(APP_PRIO_ACTIVITY, tlv_activity, app_get_strid(key_tlv_activity, "activity"),
img_activity_thum, sizeof(app_activity_t));
具体例程可以参见solution\examples\watch\application\tileview\tlv_sleep。
1.4. 平铺应用管理¶
1.4.1. 删除平铺应用¶
平铺应用节点结构定义如下:
typedef struct
{
tlv_desc_t desc; // TLV描述信息
lv_obj_t *scr; // 平铺应用父对象
void *mem_ptr; // 平铺应用全局内存指针
uint32_t mem_size; // 平铺应用全局内存大小
void *user_data; // 平铺应用用户数据
rt_list_t list; // 链表节点
tlv_state_t state; // 应用状态
bool installed; // 应用是否已安装,true表示已安装
bool updated; // 是否已更新,true表示已更新并将在关机时写入flash
} tlv_node_t;
删除方法: 将对应节点的installed属性设为false,系统在读取显示时会跳过该节点。 注意: 删除平铺应用时,该应用不能处于运行状态。
1.4.2. 编辑(排序)平铺应用¶
排序 TLV 应用的主要思路是调整 TLV 链表的节点顺序,以下是实现示例:
void tlv_edit_drage_item_cb(lv_event_t *e)
{
lv_obj_t *snapshot = lv_event_get_current_target(e);
lv_obj_t *multlist = lv_obj_get_parent(snapshot);
lv_event_code_t code = lv_event_get_code(e);
if (LV_EVENT_RELEASED == code)
{
rt_list_t *list = tlv_list_get();
if (NULL == item_ref)
{
// 将节点调整到链表最后面:移除节点后添加到最后
tlv_node_t *node = (tlv_node_t *)item->info;
rt_list_remove(&node->list);
rt_list_insert_before(list, &node->list);
}
else
{
// 将节点调整到参考节点前面:删除节点后插入到参考节点前
tlv_node_t *node = (tlv_node_t *)item->info;
tlv_node_t *node_ref = (tlv_node_t *)item_ref->info;
rt_list_remove(&node->list);
rt_list_insert_before(&node_ref->list, &node->list);
}
// 开启multlist调整动画
lv_multlist_item_move_before(multlist, item, item_ref, true);
item->major_pos = item->org_x;
int32_t target_x = lv_multlist_get_focus_pos(multlist, LV_MULTLIST_ALIGN_CENTER, item);
item->anim_pos_start = pos_x + snapshot->coords.x1 - (item->org_w >> 1);
lv_multlist_anim(item, 0, 1024, 300, wf_edit_recover_anim_exe, wf_edit_recover_anim_ready, NULL);
lv_multlist_anim(multlist, pos_x, target_x, 300, (lv_anim_exec_xcb_t)lv_multlist_set_pos, NULL, NULL);
edit->drage_item = NULL;
edit->focus_item = item;
}
// ...
}
排序功能通常在编辑模式中通过拖拽实现,提供直观的用户体验。
通过以上指南,开发者可以快速理解和实现平铺应用,为智能穿戴设备构建高效、美观的用户界面。
2. 平铺快捷组件¶
2.1. 快捷组件介绍¶
快捷组件框架是一套动态可裁剪的组件管理机制,实现对消息模块、堆叠功能、快捷栏及侧边导航栏等核心组件的高效管理, 旨在提升配置管理效率与项目适配灵活性。通过统一的标准化接口,实现对各类核心组件的高效管理,使系统能够根据项目需求灵活增减组件配置,显著增强系统的可扩展性与适配能力,满足不同项目场景的多样化需求。
2.2. 快捷组件框架¶
快捷组件框架已在 solution\framework\gui_fwk\tlv_fwk.c 实现,主要接口及说明如下:
2.2.1 组件状态管理¶
组件状态:用于状态机转换,状态改变需遵循指定的状态机规则(与平铺状态机一致)
enum
{
TLV_STATE_STARTED, /**< 启动tileview应用 */
TLV_STATE_RESUMED, /**< 激活tileview应用 */
TLV_STATE_PAUSED, /**< 暂停tileview应用 */
TLV_STATE_STOPED, /**< 销毁tileview应用 */
};
状态机切换函数
int tlv_comp_change_state(const char *id, lv_obj_t *parent, tlv_state_t state);
功能:切换指定组件的状态
参数:
id:组件唯一标识符
parent:父级对象
state:目标状态
2.2.2 组件注册机制¶
// 组件启动时调用
static void on_start(void *param)
{
p_notify = (notification_t *)app_calloc(1, sizeof(notification_t));
RT_ASSERT(p_notify);
p_notify->parent = TLV_COMP_GET_PARENT;
}
// 组件恢复时调用
static void on_resume(void *param)
{
// 恢复组件显示和交互
}
// 组件暂停时调用
static void on_pause(void *param)
{
// 暂停组件活动
}
// 组件停止时调用
static void on_stop(void *param)
{
// 释放资源
p_notify = NULL;
}
// 注册组件到TLV框架
TLV_COMPONENT_REGISTER(notify);
2.3. 内置快捷组件¶
TLV 组件框架已适配以下核心组件,项目可根据需求进行个性化配置,不需要的组件可直接删除相应目录或移除宏配置:
2.3.1 消息模块¶
功能:提供系统消息通知功能
2.3.2 堆叠功能¶
功能:实现组件的层叠显示与管理
2.3.3 快捷栏¶
功能:提供快速访问常用功能的界面
2.3.4 侧边导航栏¶
功能:实现侧边式导航菜单,提供主要功能入口
2.4. 组件使用与配置建议¶
组件裁剪:不需要的组件可直接删除对应目录或通过宏定义#undef移除
状态管理:组件状态切换应遵循状态机规则,避免非法状态转换
个性化适配:可基于现有组件进行二次开发,通过重写生命周期函数实现定制化需求
资源管理:在on_stop回调中确保释放所有已分配资源,避免内存泄漏
通过以上机制,快捷组件框架能够高效管理各类 UI 组件,为不同项目场景提供灵活的适配能力。