Dzbj_ESP32-S3_Key/main/ui/screens/ui_ScreenImg.c
Rdzleo 75586b3744 ESP32-S3按键版电子吧唧功能完整实现
1、按键驱动重构:从GPIO中断改为iot_button组件,支持BOOT/KEY2的单击/双击/长按6种事件;
2、新增按键导航管理器(key_nav):9种上下文状态机,统一分发按键事件到对应界面业务逻辑;
3、BLE模块改造:广播默认关闭由按键触发,新增设备间图片传输(GATT Client),支持扫描配对→MTU协商→分包发送;
4、新增6个UI界面:配对(Peiwang)、更新(Update)、发送等待(ImageShar)、接收等待(ImageReception)、发送中(Sharing)、接收中(Receiving);
5、新增电池指示器组件(battery_ui):支持多界面真实电量显示,3秒渐隐效果;
6、Home界面重构:移除手势事件,改为airhub背景图+电池指示器;
7、Img界面重构:移除触摸事件,新增删除二次确认边框机制;
8、禁用ScreenSet/ScreenChar界面(保留文件),禁用触摸初始化(保留代码可恢复);
9、sleep_mgr简化:移除ScreenSet亮度UI依赖,按键唤醒由key_nav统一处理;
10、新增9张图片资源(airhub背景、配对、传输状态、电池图标等);

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 17:35:05 +08:00

162 lines
5.8 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.

// Img界面 - 图片浏览
// 按键导航BOOT单击→下一张BOOT双击→上一张BOOT长按→删除确认
// KEY2单击→返回HomeKEY2双击→接收KEY2长按→分享
#include "../ui.h"
#include "../battery_ui.h"
#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;
// 标志:是否需要显示 ContainerDle
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);
}
// 重置边框为隐藏
if (ui_ImageDel) {
lv_obj_set_style_border_width(ui_ImageDel, 0, LV_PART_MAIN);
}
}
// 隐藏 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);
}
if (ui_ImageDel) {
lv_obj_set_style_border_width(ui_ImageDel, 0, LV_PART_MAIN);
}
}
// 显示白色圆角边框(二次确认状态)
void ui_ScreenImg_show_delete_confirm_border(void) {
if (ui_ImageDel) {
lv_obj_set_style_border_width(ui_ImageDel, 2, LV_PART_MAIN);
}
}
// 隐藏白色圆角边框
void ui_ScreenImg_hide_delete_confirm_border(void) {
if (ui_ImageDel) {
lv_obj_set_style_border_width(ui_ImageDel, 0, LV_PART_MAIN);
}
}
// 界面加载事件:每次进入都显示当前图片
static 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();
// 每次进入界面都显示当前图片
const char *current_img = get_current_image();
if (current_img) {
update_ui_ImgBle(current_img);
} else {
ESP_LOGI("ScreenImg", "SPIFFS无可用图片显示默认UI图片");
}
// 确保删除容器默认隐藏
ui_ScreenImg_hide_delete_container();
// 进入Img界面时显示电池指示器3秒
battery_ui_show_briefly();
}
}
// 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);
// 不设置默认占位图,延迟到 SCREEN_LOADED 事件中加载 SPIFFS 图片
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
// === 删除确认容器220x220屏幕底部半透明圆形 ===
// 容器向下偏移120px可见高度 = 220-120 = 100px
ui_ContainerDle = lv_obj_create(ui_ScreenImg);
lv_obj_remove_style_all(ui_ContainerDle);
lv_obj_set_size(ui_ContainerDle, 220, 220);
lv_obj_set_align(ui_ContainerDle, LV_ALIGN_BOTTOM_MID);
lv_obj_set_y(ui_ContainerDle, 120); // 向下偏移120px露出顶部约100px
lv_obj_clear_flag(ui_ContainerDle, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_style_radius(ui_ContainerDle, 110, LV_PART_MAIN); // 正圆220/2
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); // 半透明 70%
lv_obj_add_flag(ui_ContainerDle, LV_OBJ_FLAG_HIDDEN); // 默认隐藏
// 删除图标容器60x60正圆在可见区域内垂直居中
// 可见区域高度约100px容器60px → y = (100-60)/2 = 20px距容器顶部
ui_ImageDel = lv_obj_create(ui_ContainerDle);
lv_obj_remove_style_all(ui_ImageDel);
lv_obj_set_size(ui_ImageDel, 68, 68);
lv_obj_set_align(ui_ImageDel, LV_ALIGN_TOP_MID);
lv_obj_set_y(ui_ImageDel, 16); // (100-68)/2 = 16
lv_obj_clear_flag(ui_ImageDel, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_style_bg_opa(ui_ImageDel, LV_OPA_TRANSP, LV_PART_MAIN);
lv_obj_set_style_radius(ui_ImageDel, 34, LV_PART_MAIN); // 正圆68/2
// 白色正圆边框默认宽度为0二次确认时显示
lv_obj_set_style_border_color(ui_ImageDel, lv_color_hex(0xFFFFFF), LV_PART_MAIN);
lv_obj_set_style_border_width(ui_ImageDel, 0, LV_PART_MAIN);
lv_obj_set_style_border_opa(ui_ImageDel, LV_OPA_COVER, LV_PART_MAIN);
// S13图片48x48在容器内居中图片尺寸不变
lv_obj_t *del_icon = lv_img_create(ui_ImageDel);
lv_img_set_src(del_icon, &ui_img_s13_png);
lv_obj_set_align(del_icon, LV_ALIGN_CENTER);
lv_obj_clear_flag(del_icon, LV_OBJ_FLAG_SCROLLABLE);
// 注册界面加载事件图片切换和删除由key_nav按键导航处理
lv_obj_add_event_cb(ui_ScreenImg, ui_event_ScreenImg, LV_EVENT_ALL, NULL);
// 注意:不在此处加载图片,延迟到 LV_EVENT_SCREEN_LOADED 事件中加载
// 这样避免ui_init()时触发渲染导致开机闪烁
// 电池指示器 - 测试100%电量(绿色满格)
battery_ui_add_to_screen(ui_ScreenImg, 100);
}
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;
free_spiffs_image_list();
}