Baji_Rtc_Toy/main/ui/screens/ui_ScreenImg.c
Rdzleo 32c3dc69bc fix: 滑动切换图片时自动跳过解码失败的无效图片
1、update_ui_ImgBle 返回类型 void → bool,解码成功返回 true,失败返回 false;
2、左滑/右滑手势回调添加 for 循环,解码失败自动跳到下一张(最多尝试 10 张防死循环);
3、更新最新设备运行日志;

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:22:53 +08:00

228 lines
8.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 bool 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());
// 解码失败时自动跳过,最多尝试全部图片避免死循环
for(int try = 0; try < 10; try++) {
const char *next_img = get_next_image();
if(!next_img) break;
if(update_ui_ImgBle(next_img)) break;
ESP_LOGW("ScreenImg", "跳过无效图片,继续下一张");
}
}
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());
// 解码失败时自动跳过,最多尝试全部图片避免死循环
for(int try = 0; try < 10; try++) {
const char *prev_img = get_prev_image();
if(!prev_img) break;
if(update_ui_ImgBle(prev_img)) break;
ESP_LOGW("ScreenImg", "跳过无效图片,继续上一张");
}
}
}
// 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();
}