Dzbj_ESP32-S3/main/ui/screens/ui_ScreenImg.c
Rdzleo 6711a24a68 feat: 新增ScreenChar角色动画界面 + 启用GIF解码器
- 新增ui_ScreenChar:LVGL基元绘制动漫角色(金黄头发/脸/眼/嘴/身体/胳膊)
- 序列帧动画:BOOT按键触发眨眼+说话动画,再按停止
- ScreenImg上滑导航至ScreenChar(保留原Home路径可切换)
- BOOT按键逻辑:ScreenChar界面切换动画,其他界面返回Home
- 启用CONFIG_LV_USE_GIF=y支持GIF动图显示

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

225 lines
8.5 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 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_ScreenChar, LV_SCR_LOAD_ANIM_NONE, 0, 0, &ui_ScreenChar_screen_init);
// 原有上滑返回Home如需切换回来注释上面一行取消下面一行注释
// _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();
}