弹窗

1. 简介

弹窗是建立在system(lv_layer_sys())层的独立页面组,由popup_fwk进行管理,与app_fwk相互独立。

  • 弹窗功能通过APP_POPUP_USED宏使能,配置路径:menuconfig (Top) Product Applicaiton Config

  • 支持优先级配置(数值越大优先级越高)

  • 可配置自动生命周期(自动退出时间)

  • 支持自定义背景色

  • 支持设置不同透明度

2. 注册弹窗

2.1 注册内置弹窗

    POPUP_REGISTER(id, priority, time, ptr_size)

参数说明:

  • id:弹窗唯一标识符(名称)

  • priority:优先级,数字越大优先级越高

  • time:弹窗自动退出时间(毫秒)

  • ptr_size:弹窗全局内存大小,由框架统一管理

2.2 注册动态弹窗

动态弹窗注册步骤:

  • 重新定义POPUP_REGISTER(id, priority, time, ptr_size)宏

  • 指定弹窗类型为POPUP_DYNAMIC

    POPUP_REGISTER(id, priority, time, ptr_size)

3. 处理弹窗消息

POPUP_MSG_HANDLER 中popup_msg_t 类型如下

消息类型

触发时机

核心用途与处理要点

POPUP_MSG_ONSTART

弹窗启动时

可进行数据初始化及背景页面创建,此消息仅接收一次

POPUP_MSG_ONRESUME

弹窗激活时

仅在弹窗处于暂停(pause)状态时可被使用,用于恢复弹窗的正常运行状态

POPUP_MSG_ONPAUSE

弹窗暂停时

仅在弹窗处于启动、激活或重新刷新状态时可被调用,用于暂停弹窗的运行

POPUP_MSG_ONREFR

弹窗刷新时

当收到重复的弹窗消息时被调用,用于更新弹窗内容

POPUP_MSG_ONSTOP

弹窗销毁时

需释放用户申请的内存及删除创建的任务,当前屏幕上的对象无需主动删除
(框架会在发送此消息后自动清理屏幕及控件)

POPUP_MSG_ONDESTROY

弹窗摧毁时

不会立即执行,在应用涉及列表嵌套时设置,将在退出列表循环后执行

POPUP_MSG_ONSUSPEND

弹窗挂起时

触发时不会创建新的弹窗消息,用于临时挂起弹窗

4. 弹窗使用流程

4.1 注册弹窗

/**
 * @brief  Register a new popup to section.
 * @param  id popup name.
 * @param  priority popup priority.
 * @param  time popup countdown timer.
 * @param  ptr_size popup global memory size.
 */

#define POPUP_REGISTER(id, priority, time, ptr_size)    \
    POPUP_MSG_HANDLER;  \
    SECTION_ITEM_REGISTER(POPUP_SECTION_NAME, static const popup_desc_t app_popup) =  \
    {                                        \
        .id_str         = id,     \
        .handler        = msg_handler,       \
        .prio           = priority,          \
        .running_time   = time,         \
        .mem_size       = ptr_size           \
    }

#define POPUP_REGISTER_EXT(id, priority, time, ptr_size, val)    \
        POPUP_REGISTER(id, priority, time, ptr_size)


#if defined(BUILD_DLMODULE) && !defined(BSP_USING_PC_SIMULATOR) //compile as dynamic popup

#undef POPUP_REGISTER_EXT
#undef POPUP_REGISTER

#define POPUP_REGISTER_EXT(id, priority, time, ptr_size, val)     \
    POPUP_MSG_HANDLER;  \
    void _popup_init_func_##val(void) \
    {   \
        LOG_I("%s:%s",__func__, id);    \
        popup_register_for_app(STRINGIFY(MODULE_NAME), id, priority, time, msg_handler, ptr_size, POPUP_DYNAMIC); \
    }


#define POPUP_REGISTER(id, priority, time, ptr_size)    \
        POPUP_REGISTER_EXT(id, priority, time, ptr_size, 0)

#endif

4.2 运行弹窗

使用以下接口运行已注册的弹窗:

    popup_run(const char *id, void *user_data)

参数说明:

  • id:弹窗名称(注册时指定的 id)

  • user_data:自定义数据,可通过POPUP_GET_NODE_PARAM接口在msg_handle中获取

5. 示例:注册一个remind弹窗

// 定义弹窗数据结构
typedef struct {
    lv_obj_t *bg_page;          // 背景页面对象
    alarm_node_t *alarm;        // 闹钟数据节点
    lv_timer_t *timer;          // 定时器
    void *gif_anim;             // GIF动画对象
} popup_alarm_t;

// 全局指针
static popup_alarm_t *p_alarm = NULL;

/**
 * 弹窗启动处理函数
 * 在弹窗启动时调用,进行初始化操作
 */
static void on_start(void *param)
{
    // 获取框架申请的内存
    p_alarm = (popup_alarm_t *)POPUP_GET_NODE_MEM_PTR;
    RT_ASSERT(p_alarm);  // 确保内存获取成功

    // 获取背景对象,作为父控件
    p_alarm->bg_page = POPUP_GET_NODE_PARENT;
    
    // 获取自定义数据(运行弹窗时传入的数据)
    p_alarm->alarm = (alarm_node_t *)POPUP_GET_NODE_PARAM;
    
    // 设置背景属性
    lv_ext_set_local_bg_opa(p_alarm->bg_page, LV_OPA_100, LV_PART_MAIN);
    lv_ext_set_local_bg(p_alarm->bg_page, LV_COLOR_BLACK, LV_OPA_COVER);
    app_screen_lock_enable(false);

    // 构建页面内容
    popup_alarm_page(p_alarm->bg_page);
}

/**
 * 弹窗刷新处理函数
 * 当收到重复弹窗消息时调用
 */
static void on_refr(void *param)
{
    if (NULL != p_alarm->bg_page)
    {
        // 更新自定义数据
        p_alarm->alarm = (alarm_node_t *)POPUP_GET_NODE_PARAM;
        
        // 停止并释放GIF动画
        if (p_alarm->gif_anim)
        {
            lvsf_gif_anim_pause(p_alarm->gif_anim);
            lvsf_gif_anim_deinit(p_alarm->gif_anim);
            p_alarm->gif_anim = NULL;
        }
        
        // 清除当前页面子对象并重新构建
        lv_obj_clean(p_alarm->bg_page);
        popup_alarm_page(p_alarm->bg_page);
    }
}

/**
 * 弹窗销毁处理函数
 * 在弹窗即将销毁时调用
 */
static void on_stop(void *param)
{
    // 启用屏幕锁定
    app_screen_lock_enable(true);

    // 清理闹钟相关资源
    popup_alarm_delete();

    // 全局指针置空,防止悬空引用
    p_alarm = NULL;
}

// 注册alarm弹窗
// 优先级:5,自动退出时间:10000ms,内存大小:sizeof(popup_alarm_t)
POPUP_REGISTER("alarm", 5, 10000, sizeof(popup_alarm_t));

具体例程可以参见solution\examples\watch\application\popup\find_phone