一、BLE 蓝牙优化 - 设备名称改为动态名称 Airhub_MAC(基于BLE MAC地址) - 广播数据拆分为 ADV + Scan Response 两包 - 图片接收完成后数据直通显示(跳过SPIFFS重读,减少200-500ms延迟) - BLE耗时操作(NVS写入+导航显示)转移到独立FreeRTOS任务,避免BTC_TASK栈溢出 - 缩短BLE连接间隔(min=7.5ms, max=20ms),提升传输吞吐量 - 减少传输日志输出(每100包打印一次),提升传输速度 二、显示性能优化 - LVGL绘制缓冲区从DMA 30行改为PSRAM 120行大缓冲,减少flush次数 - CPU最大频率从160MHz提升到240MHz,提升解码性能 三、GIF动图支持(条件编译,当前默认关闭) - 实现自定义GIF播放器:Palette LUT查表 + TRUE_COLOR无Alpha + 后台线程解码流水线 - 使用 #if LV_USE_GIF 条件编译包裹所有GIF代码,sdkconfig中CONFIG_LV_USE_GIF=n时零开销 - 启用GIF时需设置 CONFIG_LV_USE_GIF=y 即可 四、图片管理优化 - BLE接收新图片后直接追加到列表(避免重扫SPIFFS目录) - SPIFFS图片扫描支持.gif扩展名(条件编译控制) 五、文档更新 - 设备运行日志:GIF性能瓶颈分析与优化方案 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
222 lines
8.2 KiB
C
222 lines
8.2 KiB
C
// This file was generated by SquareLine Studio
|
||
// SquareLine Studio version: SquareLine Studio 1.6.0
|
||
// LVGL version: 8.3.11
|
||
// Project name: Lcd_Pro
|
||
|
||
#include "../ui.h"
|
||
#include "ui_ScreenSet.h" // 引入ScreenSet的函数声明
|
||
#include "../../pages/include/pages.h" // 引入图片管理函数
|
||
#include "esp_log.h" // 用于日志输出
|
||
|
||
extern void init_spiffs_image_list(void);
|
||
extern void update_ui_ImgBle(const char *img_name);
|
||
extern void free_spiffs_image_list(void);
|
||
extern const char* get_next_image(void);
|
||
extern const char* get_prev_image(void);
|
||
|
||
lv_obj_t *ui_ScreenImg = NULL;
|
||
lv_obj_t *ui_ImgBle = NULL;
|
||
lv_obj_t *ui_ContainerDle = NULL;
|
||
lv_obj_t *ui_ImageDel = NULL;
|
||
lv_obj_t *ui_ImageReturn = NULL;
|
||
|
||
// 标志:是否首次加载
|
||
static bool first_load = true;
|
||
// 标志:是否需要显示 ContainerDle(只有从 ScreenSet 点击 ImgDelete 时才为 true)
|
||
static bool should_show_container = false;
|
||
|
||
// 显示 ContainerDle
|
||
void ui_ScreenImg_show_delete_container(void) {
|
||
should_show_container = true; // 设置标志,表示需要显示
|
||
if (ui_ContainerDle) {
|
||
lv_obj_clear_flag(ui_ContainerDle, LV_OBJ_FLAG_HIDDEN);
|
||
}
|
||
}
|
||
|
||
// 隐藏 ContainerDle
|
||
void ui_ScreenImg_hide_delete_container(void) {
|
||
should_show_container = false; // 清除标志
|
||
if (ui_ContainerDle) {
|
||
lv_obj_add_flag(ui_ContainerDle, LV_OBJ_FLAG_HIDDEN);
|
||
}
|
||
}
|
||
|
||
// ImageReturn 点击事件:隐藏容器
|
||
void ui_event_ImageReturn(lv_event_t * e) {
|
||
lv_event_code_t event_code = lv_event_get_code(e);
|
||
if (event_code == LV_EVENT_CLICKED) {
|
||
ui_ScreenImg_hide_delete_container();
|
||
}
|
||
}
|
||
|
||
// ImageDel 点击事件:删除当前图片
|
||
void ui_event_ImageDel(lv_event_t * e) {
|
||
lv_event_code_t event_code = lv_event_get_code(e);
|
||
if (event_code == LV_EVENT_CLICKED) {
|
||
// 删除当前图片
|
||
if (delete_current_image()) {
|
||
// 删除成功,隐藏容器
|
||
ui_ScreenImg_hide_delete_container();
|
||
|
||
// 获取下一张图片(内部已更新索引)
|
||
const char *next_img = get_current_image();
|
||
if (next_img) {
|
||
// 显示下一张图片
|
||
update_ui_ImgBle(next_img);
|
||
} else {
|
||
// 没有图片了,可以显示提示信息
|
||
// 这里暂不处理,保持当前界面
|
||
}
|
||
} else {
|
||
// 删除失败,仍然隐藏容器
|
||
ui_ScreenImg_hide_delete_container();
|
||
}
|
||
}
|
||
}
|
||
|
||
// event funtions
|
||
void ui_event_ScreenImg( lv_event_t * e) {
|
||
lv_event_code_t event_code = lv_event_get_code(e);
|
||
|
||
// 界面加载完成事件:每次进入都显示当前图片
|
||
if ( event_code == LV_EVENT_SCREEN_LOADED ) {
|
||
// 初始化图片列表(内部有guard,不会重复初始化)
|
||
init_spiffs_image_list();
|
||
|
||
// 每次进入界面都显示当前图片(支持BLE导航和手势切换回来)
|
||
const char *current_img = get_current_image();
|
||
if (current_img) {
|
||
update_ui_ImgBle(current_img);
|
||
} else {
|
||
ESP_LOGI("ScreenImg", "SPIFFS无可用图片,显示默认UI图片");
|
||
}
|
||
|
||
// 每次加载界面时检查是否需要显示 ContainerDle
|
||
// 只有从 ScreenSet 点击 ImgDelete 时 should_show_container 才为 true
|
||
if (should_show_container) {
|
||
// 需要显示,保持显示状态(已在 ui_ScreenImg_show_delete_container 中显示)
|
||
should_show_container = false; // 清除标志(下次进入默认不显示)
|
||
} else {
|
||
// 不需要显示,确保隐藏
|
||
ui_ScreenImg_hide_delete_container();
|
||
}
|
||
}
|
||
|
||
if ( event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_get_act()) == LV_DIR_TOP ) {
|
||
lv_indev_wait_release(lv_indev_get_act());
|
||
// 离开界面前清理资源和隐藏容器
|
||
#if LV_USE_GIF
|
||
pages_cleanup_gif();
|
||
#endif
|
||
ui_ScreenImg_hide_delete_container();
|
||
_ui_screen_change( &ui_ScreenHome, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_ScreenHome_screen_init);
|
||
}
|
||
if ( event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_get_act()) == LV_DIR_BOTTOM ) {
|
||
lv_indev_wait_release(lv_indev_get_act());
|
||
// 离开界面前清理资源和隐藏容器
|
||
#if LV_USE_GIF
|
||
pages_cleanup_gif();
|
||
#endif
|
||
ui_ScreenImg_hide_delete_container();
|
||
// 设置返回到Img界面
|
||
ui_ScreenSet_set_previous(&ui_ScreenImg, &ui_ScreenImg_screen_init);
|
||
_ui_screen_change( &ui_ScreenSet, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_ScreenSet_screen_init);
|
||
}
|
||
if ( event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_get_act()) == LV_DIR_LEFT ) {
|
||
lv_indev_wait_release(lv_indev_get_act());
|
||
const char *next_img = get_next_image();
|
||
if(next_img) {
|
||
update_ui_ImgBle(next_img);
|
||
}
|
||
}
|
||
if ( event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_get_act()) == LV_DIR_RIGHT ) {
|
||
lv_indev_wait_release(lv_indev_get_act());
|
||
const char *prev_img = get_prev_image();
|
||
if(prev_img) {
|
||
update_ui_ImgBle(prev_img);
|
||
}
|
||
}
|
||
}
|
||
|
||
// build funtions
|
||
|
||
void ui_ScreenImg_screen_init(void)
|
||
{
|
||
ui_ScreenImg = lv_obj_create(NULL);
|
||
lv_obj_clear_flag( ui_ScreenImg, LV_OBJ_FLAG_SCROLLABLE ); /// Flags
|
||
|
||
ui_ImgBle = lv_img_create(ui_ScreenImg);
|
||
lv_img_set_src(ui_ImgBle, &ui_img_s1_png);
|
||
lv_obj_set_width( ui_ImgBle, 360);
|
||
lv_obj_set_height( ui_ImgBle, 360);
|
||
lv_obj_set_align( ui_ImgBle, LV_ALIGN_CENTER );
|
||
lv_obj_set_flex_flow(ui_ImgBle,LV_FLEX_FLOW_ROW);
|
||
lv_obj_set_flex_align(ui_ImgBle, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
|
||
lv_obj_add_flag( ui_ImgBle, LV_OBJ_FLAG_ADV_HITTEST ); /// Flags
|
||
lv_obj_clear_flag( ui_ImgBle, LV_OBJ_FLAG_SCROLLABLE ); /// Flags
|
||
|
||
ui_ContainerDle = lv_obj_create(ui_ScreenImg);
|
||
lv_obj_remove_style_all(ui_ContainerDle);
|
||
lv_obj_set_width( ui_ContainerDle, 360);
|
||
lv_obj_set_height( ui_ContainerDle, 360); // 圆形容器
|
||
lv_obj_set_x( ui_ContainerDle, 0 );
|
||
lv_obj_set_y( ui_ContainerDle, 240 ); // 向下偏移 240px(显示顶部 1/3)
|
||
lv_obj_set_align( ui_ContainerDle, LV_ALIGN_CENTER );
|
||
lv_obj_clear_flag( ui_ContainerDle, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE );
|
||
// 设置圆形和裁剪
|
||
lv_obj_set_style_radius(ui_ContainerDle, 180, LV_PART_MAIN); // 圆角半径 180
|
||
lv_obj_set_style_clip_corner(ui_ContainerDle, true, LV_PART_MAIN); // 裁剪圆角外内容
|
||
lv_obj_set_style_bg_color(ui_ContainerDle, lv_color_hex(0x000000), LV_PART_MAIN);
|
||
lv_obj_set_style_bg_opa(ui_ContainerDle, 180, LV_PART_MAIN); // 半透明(180/255 约 70%)
|
||
lv_obj_add_flag( ui_ContainerDle, LV_OBJ_FLAG_HIDDEN ); // 默认隐藏
|
||
|
||
ui_ImageDel = lv_img_create(ui_ContainerDle);
|
||
lv_img_set_src(ui_ImageDel, &ui_img_s13_png);
|
||
lv_obj_set_width( ui_ImageDel, LV_SIZE_CONTENT);
|
||
lv_obj_set_height( ui_ImageDel, LV_SIZE_CONTENT);
|
||
lv_obj_set_x( ui_ImageDel, -60 ); // 左侧位置
|
||
lv_obj_set_y( ui_ImageDel, -120 ); // 容器顶部区域(屏幕底部可见区域)
|
||
lv_obj_set_align( ui_ImageDel, LV_ALIGN_CENTER );
|
||
lv_obj_add_flag( ui_ImageDel, LV_OBJ_FLAG_CLICKABLE ); // 可点击
|
||
lv_obj_clear_flag( ui_ImageDel, LV_OBJ_FLAG_SCROLLABLE );
|
||
|
||
ui_ImageReturn = lv_img_create(ui_ContainerDle);
|
||
lv_img_set_src(ui_ImageReturn, &ui_img_s14_png);
|
||
lv_obj_set_width( ui_ImageReturn, LV_SIZE_CONTENT);
|
||
lv_obj_set_height( ui_ImageReturn, LV_SIZE_CONTENT);
|
||
lv_obj_set_x( ui_ImageReturn, 60 ); // 右侧位置
|
||
lv_obj_set_y( ui_ImageReturn, -120 ); // 容器顶部区域(屏幕底部可见区域)
|
||
lv_obj_set_align( ui_ImageReturn, LV_ALIGN_CENTER );
|
||
lv_obj_add_flag( ui_ImageReturn, LV_OBJ_FLAG_CLICKABLE ); // 可点击
|
||
lv_obj_clear_flag( ui_ImageReturn, LV_OBJ_FLAG_SCROLLABLE );
|
||
|
||
// 添加点击事件回调
|
||
lv_obj_add_event_cb(ui_ImageDel, ui_event_ImageDel, LV_EVENT_ALL, NULL);
|
||
lv_obj_add_event_cb(ui_ImageReturn, ui_event_ImageReturn, LV_EVENT_ALL, NULL);
|
||
|
||
lv_obj_add_event_cb(ui_ScreenImg, ui_event_ScreenImg, LV_EVENT_ALL, NULL);
|
||
|
||
// 注意:不在此处加载图片,延迟到 LV_EVENT_SCREEN_LOADED 事件中加载
|
||
// 这样避免ui_init()时触发渲染导致开机闪烁
|
||
}
|
||
|
||
void ui_ScreenImg_screen_destroy(void)
|
||
{
|
||
#if LV_USE_GIF
|
||
pages_cleanup_gif();
|
||
#endif
|
||
if (ui_ScreenImg) lv_obj_del(ui_ScreenImg);
|
||
|
||
// NULL screen variables
|
||
ui_ScreenImg= NULL;
|
||
ui_ImgBle= NULL;
|
||
ui_ContainerDle= NULL;
|
||
ui_ImageDel= NULL;
|
||
ui_ImageReturn= NULL;
|
||
|
||
// 重置首次加载标志,下次进入时重新初始化
|
||
first_load = true;
|
||
|
||
free_spiffs_image_list();
|
||
}
|