• lvgl 页面管理器


    lv_scr_mgr

    lvgl 界面管理器

    适配 lvgl 8.3

    • 降低界面之间的耦合
    • 使用较小的内存,界面切换后会自动释放内存
    • 内存泄漏检测
      请添加图片描述

    使用方法

    1. 在lv_scr_mgr_port.h 中创建一个枚举,用于界面ID
    2. 为每个界面创建一个页面管理器句柄
    3. 将界面句柄添加到 lv_scr_mgr_port.c 数组中
    4. 在 lv_init() 后,对页面管理器进行初始化 lv_scr_mgr_init(NULL);
    5. 使用 lv_scr_mgr_switch 设置初始根界面
    6. 使用 lv_scr_mgr_push lv_scr_mgr_pop 对界面进行操作

    git地址

    git地址
    gitee

    • lv_scr_mgr.c
    /**
      *******************************CopyRight  ************************************
      * @file    lv_scr_mgr.c
      * @author  zyf
      * @date    2023-10-11 13:4:36
      * @brief   lvgl 页面管理器
      *          
      ******************************************************************************
      */
    
    /* Includes ------------------------------------------------------------------*/
    #include "lvgl.h"
    #include "lv_scr_mgr.h"
    
    typedef struct
    {
        uint32_t                     scr_cnt; 
        void*                        param;
        const lv_scr_mgr_handle_t    **handles;
    #if LV_SCR_MGR_PRINTF_MEM
        uint32_t                     *max_mem;
    #endif
    }scr_mgr_list_handle_t;
    
    
    static scr_mgr_list_handle_t     mgr_list;
    static lv_scr_mgr_stack_node_t*      mgr_stack_top = NULL;
    static lv_scr_mgr_stack_node_t*      mgr_stack_root = NULL;
    
    static const lv_scr_mgr_handle_t* find_handle_by_id(uint32_t id)
    {
        for (int i = 0; i < mgr_list.scr_cnt; i++)
        {
            if (mgr_list.handles[i]->scr_id == id)
            {
                return mgr_list.handles[i];
            }
        }
        return NULL;
    }
    #if LV_SCR_MGR_PRINTF_MEM
    static uint32_t* find_mem_addr_by_id(uint32_t id)
    {
        for (int i = 0; i < mgr_list.scr_cnt; i++)
        {
            if (mgr_list.handles[i]->scr_id == id)
            {
                return &mgr_list.max_mem[i];
            }
        }
        return NULL;
    }
    
    static void mem_max_printf(uint32_t id)
    {
        static uint32_t mem_max = 0;
        lv_mem_monitor_t mon;
        lv_mem_monitor(&mon);
        if (mon.total_size - mon.free_size > mem_max)
        {
            mem_max = mon.total_size - mon.free_size;
            LV_LOG_USER("used: %d (%d %%), frag: %d %%, biggest free: %d\n", mem_max,
                mon.used_pct,
                mon.frag_pct,
                (int)mon.free_biggest_size);
        }
    }
    
    static void page_mem_max_printf(uint32_t id)
    {
        lv_mem_monitor_t mon;
        lv_mem_monitor(&mon);
        /* 当前界面最大使用内存 */
        uint32_t* page_max_mem = find_mem_addr_by_id(id);
        if (mon.total_size - mon.free_size > *page_max_mem)
        {
            *page_max_mem = mon.total_size - mon.free_size;
            LV_LOG_USER("page id %d, used: %d (%d %%), frag: %d %%, biggest free: %d\n", id, *page_max_mem,
                mon.used_pct,
                mon.frag_pct,
                (int)mon.free_biggest_size);
        }
    }
    
    
    static void anim_mem_max_printf(lv_event_t* e)
    {
        lv_event_code_t event_code = lv_event_get_code(e);
        if (event_code == LV_EVENT_SCREEN_LOADED)
        {
            page_mem_max_printf((uint32_t)lv_event_get_user_data(e));
        }
    }
    #endif
    
    static void scr_mgr_stack_free(void)
    {
        lv_scr_mgr_stack_node_t* stack_node = NULL;
    
        /* 释放界面栈 */
        while (NULL != mgr_stack_top)
        {
            stack_node = mgr_stack_top->prev;
            if(mgr_stack_top->handle->scr_destroy)
                mgr_stack_top->handle->scr_destroy();
            lv_mem_free((void*)mgr_stack_top);
            mgr_stack_top = stack_node;
        }
        mgr_stack_root = NULL;
    }
    
    /**
     * @brief 入栈
     * @param tag 要入栈的句柄
     * @return 栈顶句柄
    */
    static lv_scr_mgr_stack_node_t* scr_mgr_stack_push(const lv_scr_mgr_handle_t* tag)
    {
        lv_scr_mgr_stack_node_t* stack_node = NULL;
        stack_node = lv_mem_alloc(sizeof(lv_scr_mgr_stack_node_t));
        LV_ASSERT_MALLOC(stack_node);
        stack_node->handle = tag;
        stack_node->next = NULL;
        if (stack_node->handle->scr_first_create)
        {
            stack_node->handle->scr_first_create();
        }
    
        if (tag->scr_create)
        {
            stack_node->scr = tag->scr_create(stack_node->handle->scr_id, mgr_list.param);
        }
        else
        {
            LV_LOG_ERROR("no create fun!");
        }
    
        if (NULL == mgr_stack_top)
        {
            stack_node->prev = NULL;
            mgr_stack_root = stack_node;
        }
        else
        {
            stack_node->prev = mgr_stack_top;
            mgr_stack_top->next = stack_node;
        }
        mgr_stack_top = stack_node;
        return stack_node;
    }
    
    static int32_t scr_mgr_stack_pop(int32_t n)
    {
        lv_scr_mgr_stack_node_t* stack_node = NULL;
        int32_t i = n;
    
        if ((NULL == mgr_stack_top) || (NULL == mgr_stack_top->prev))
        {
            return 0;
        }
    
        while (i)
        {
            if ((NULL == mgr_stack_top) || (NULL == mgr_stack_top->prev))
            {
                break;
            }
    
            stack_node = mgr_stack_top->prev;
            if (mgr_stack_top->handle->scr_destroy)
            {
                mgr_stack_top->handle->scr_destroy();
            }
            lv_mem_free((void*)mgr_stack_top);
            mgr_stack_top = stack_node;
            i--;
        }
    
        if (NULL != mgr_stack_top->handle->scr_create)
        {
            mgr_stack_top->scr = mgr_stack_top->handle->scr_create(mgr_stack_top->handle->scr_id, mgr_list.param);
        }
        else
        {
            LV_LOG_ERROR("no create fun!");
        }
    
        if (i)
        {
            LV_LOG_WARN("stack pop %d, but stack is %d", n, n-i);
        }
        return n - i;
    }
    
    /**
     * @brief 切换界面
     * @param cur_scr 当前界面
     * @param stack_node 目标界面句柄
     * @param anim 切换界面动画开关
     *             关闭界面切换动画,切换界面时会先创建一个新的空界面,切换到空界面后,
     *             删除之前的界面,然后再创建切换到新界面,最后再删除中间界面。会节省内存。
     *             关闭界面切换动画,切换界面时直接创建新界面,然后再用动画切换到新界面。
     *
     * @return true
    */
    bool scr_mgr_switch(lv_obj_t* cur_scr, lv_scr_mgr_stack_node_t* stack_node, bool anim)
    {
        lv_scr_load_anim_t load_anim = LV_SCR_MGR_LOAD_ANIM_DEFAULT;
        lv_obj_t* tmp_scr = NULL;
    
        if (anim)
        {
            if ((stack_node->handle->anim_type != LV_SCR_LOAD_ANIM_NONE) && (LV_SCR_LOAD_ANIM_OUT_BOTTOM >= stack_node->handle->anim_type))
            {
                load_anim = stack_node->handle->anim_type;
            }
    
    #if LV_SCR_MGR_PRINTF_MEM
            mem_max_printf(stack_node->handle->scr_id);
            lv_obj_add_event_cb(stack_node->scr, anim_mem_max_printf, LV_EVENT_SCREEN_LOADED, (void*)stack_node->handle->scr_id);
    #endif
    
            lv_scr_load_anim(stack_node->scr, load_anim, LV_SCR_MGR_LOAD_ANIM_TIME, LV_SCR_MGR_LOAD_ANIM_DELAY, true);
        }
        else
        {
            if (NULL != cur_scr)
            {
                tmp_scr = lv_obj_create(NULL);
                lv_scr_load(tmp_scr);
                lv_obj_del(cur_scr);
                cur_scr = NULL;
            }
    
            lv_scr_load(stack_node->scr);
    
    #if LV_SCR_MGR_PRINTF_MEM
            mem_max_printf(stack_node->handle->scr_id);
            page_mem_max_printf(stack_node->handle->scr_id);
    #endif
            if (NULL != tmp_scr)
            {
                lv_obj_del(tmp_scr);
            }
        }
        return true;
    }
    
    /**
     * @brief 初始化界面管理器
     * @param param 创建界面时的参数
     * @return 
    */
    bool lv_scr_mgr_init(void* param)
    {
        mgr_list.param = param;
    #if LV_SCR_MGR_REG_ENABLE
        extern const lv_scr_mgr_handle_t* scr_mgr_scr_mgr_start;
        extern const lv_scr_mgr_handle_t* scr_mgr_scr_mgr_end;
        const lv_scr_mgr_handle_t** item = &scr_mgr_scr_mgr_start;
        item++;
        mgr_list.handles = item;
        mgr_list.scr_cnt = 0;
        for(;item < &scr_mgr_scr_mgr_end; item++)
        {
            mgr_list.scr_cnt++;  
        }
    #else
        mgr_list.scr_cnt = lv_scr_mgr_get_cnt();
        mgr_list.handles  = lv_scr_mgr_get_handles();
    #endif    
    
        if (0 == mgr_list.scr_cnt)
        {
            LV_LOG_ERROR("no screen!");
            return false;
        }
    
    #if LV_SCR_MGR_PRINTF_MEM
        mgr_list.max_mem = lv_mem_alloc(mgr_list.scr_cnt * sizeof(uint32_t*));
        LV_ASSERT(mgr_list.max_mem);
        memset(mgr_list.max_mem, 0, mgr_list.scr_cnt * sizeof(uint32_t*));
    #endif
        return true;
    }
    
    void lv_scr_mgr_deinit(void)
    {
        mgr_list.param = NULL;
    #if LV_SCR_MGR_PRINTF_MEM
        lv_mem_free(mgr_list.max_mem);
    #endif
        scr_mgr_stack_free();
    }
    
    void lv_scr_mgr_param_set(void* param)
    {
        mgr_list.param = param;
    }
    
    void* lv_scr_mgr_param_get(void)
    {
        return mgr_list.param;
    }
    
    /**
     * @brief 设置根界面
     * @param id 根界面序号
     * @param anim 动画开关
     * @return 
    */
    bool lv_scr_mgr_switch(uint32_t id, bool anim)
    {
        const lv_scr_mgr_handle_t* tag_handle = find_handle_by_id(id);
        const lv_scr_mgr_handle_t* cur_handle = NULL;
        lv_scr_mgr_stack_node_t* stack_node = NULL;
        lv_obj_t* cur_scr = NULL;
        
        
        if (NULL == tag_handle)
        {
            LV_LOG_ERROR("no screen, id %d", id);
            return false;
        }
    
    
        if (NULL != mgr_stack_top)
        {
            /* 栈内有界面 */
            cur_handle = mgr_stack_top->handle;
            cur_scr = mgr_stack_top->scr;
        }
        else
        {
            cur_scr = lv_scr_act();
        }
    
        scr_mgr_stack_free();
    
        if ((NULL == cur_handle) || (tag_handle->scr_id == cur_handle->scr_id))
        {
            /* 没有界面切换,不使用动画效果 */
            anim = false;
        }
        stack_node = scr_mgr_stack_push(tag_handle);
    
        return scr_mgr_switch(cur_scr, stack_node, anim);
    }
    
    /**
     * @brief 入栈一个新的界面
     * @param id 
     * @param anim 
     * @return 
    */
    bool lv_scr_mgr_push(uint32_t id, bool anim)
    {
        const lv_scr_mgr_handle_t* tag_handle = find_handle_by_id(id);
        lv_scr_mgr_stack_node_t* stack_node = NULL;
        lv_obj_t* cur_scr = NULL;
    
        if (NULL == tag_handle)
        {
            LV_LOG_ERROR("no screen, id %d", id);
            return false;
        }
    
        if ((NULL == mgr_stack_top) || (NULL == mgr_stack_root))
        {
            LV_LOG_ERROR("no root screen, please use lv_scr_mgr_switch create root screen");
            return false;
        }
        cur_scr = mgr_stack_top->scr;
        stack_node = scr_mgr_stack_push(tag_handle);
    
        return scr_mgr_switch(cur_scr, stack_node, anim);
    }
    
    /**
     * @brief 出栈n个界面
     * @param n 如果栈内界面没有n个,则返回根界面
     * @param anim 
     * @return 
    */
    bool lv_scr_mgr_popn(uint32_t n, bool anim)
    {
        lv_obj_t* cur_scr = NULL;
    
        if ((mgr_stack_top == NULL) || (mgr_stack_top->prev == NULL))
        {
            return false;
        }
        cur_scr = mgr_stack_top->scr;
    
        scr_mgr_stack_pop(n);
    
        return scr_mgr_switch(cur_scr, mgr_stack_top, anim);
    }
    
    /**
     * @brief 出栈一个界面
     * @param anim 
     * @return 
    */
    bool lv_scr_mgr_pop(bool anim)
    {
        return lv_scr_mgr_popn(1, anim);
    }
    
    
    /**
     * @brief 退回到根界面
     * @param anim 
     * @return 
    */
    bool lv_scr_mgr_pop_root(bool anim)
    {
        lv_scr_mgr_stack_node_t* stack_node = NULL;
        lv_scr_mgr_stack_node_t* stack_top = NULL;
        uint32_t cnt = 0;
        if (NULL == mgr_stack_root || NULL == mgr_stack_top)
        {
            return false;
        }
    
        stack_top = mgr_stack_top;
    
        while (stack_top != NULL)
        {
            cnt++;
            stack_node = stack_top->prev;
            stack_top = stack_node;
        }
    
        return lv_scr_mgr_popn(cnt-1, anim);
    }
    
    /**
     * @brief 获取当前界面id
     * @param  
     * @return 
    */
    int32_t lv_scr_mgr_get_cur_id(void)
    {
        if (NULL != mgr_stack_top && NULL != mgr_stack_top->handle)
        {
            return mgr_stack_top->handle->scr_id;
        }
        else
        {
            return -1;
        }
    }
    
    /**
     * @brief 获取根界面id
     * @param
     * @return
    */
    int32_t lv_scr_mgr_get_root_id(void)
    {
        if (NULL != mgr_stack_root && NULL != mgr_stack_root->handle)
        {
            return mgr_stack_root->handle->scr_id;
        }
        else
        {
            return -1;
        }
    }
    /************************ (C) COPYRIGHT ***********END OF FILE*****************/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • lv_scr_mgr.h
    /**
      *******************************CopyRight  ************************************
      * @file    lv_scr_mgr.h
      * @author  zyf
      * @date    2023-10-11 9:31:49
      * @brief   lvgl 页面管理器
      *          
      ******************************************************************************
      */
    #ifndef _LV_SCR_MGR_H_
    #define _LV_SCR_MGR_H_
    
    /* Includes ------------------------------------------------------------------*/
    #include "stdint.h"
    #include "lvgl.h"
    
    #ifdef __cplusplus
    extern "C" {
    #endif
     
    /*!<  界面切换动画默认值
     */
    #define LV_SCR_MGR_LOAD_ANIM_DEFAULT   LV_SCR_LOAD_ANIM_MOVE_LEFT
    #define LV_SCR_MGR_LOAD_ANIM_TIME      500
    #define LV_SCR_MGR_LOAD_ANIM_DELAY     0
    
    /*!< 内存泄漏检测 注意,页面管理器的push操作也会申请动态内存
     * 如果使用动画,则需要将 lv_disp.c 中的 scr_anim_ready 改为如下
        static void scr_anim_ready(lv_anim_t * a)
        {
            lv_disp_t * d = lv_obj_get_disp(a->var);
    
            lv_event_send(d->prev_scr, LV_EVENT_SCREEN_UNLOADED, NULL);
    
            if(d->prev_scr && d->del_prev) lv_obj_del(d->prev_scr);
            d->prev_scr = NULL;
            d->draw_prev_over_act = false;
            d->scr_to_load = NULL;
            lv_event_send(d->act_scr, LV_EVENT_SCREEN_LOADED, NULL);
            lv_obj_remove_local_style_prop(a->var, LV_STYLE_OPA, 0);
            lv_obj_invalidate(d->act_scr);
        }
     */
    #define LV_SCR_MGR_PRINTF_MEM          1   
    
    /* 使用分散加载的方式 将 lv_scr_mgr_handle_t 存放在特定段,
     * 用户创建 lv_scr_mgr_handle_t 后可以在后面直接 使用 LV_SCR_MGR_REG() 对界面句柄进行注册
     * 而不用将 界面句柄 添加到 lv_scr_mgr_port.c 数组中
     */
    #define LV_SCR_MGR_REG_ENABLE          0
    
    
    
    
    
    typedef struct
    {
        uint32_t scr_id;                       /*!< id */
        lv_scr_load_anim_t      anim_type;     /*!< 切换动画类型 如果为空,则使用 LV_SCR_MGR_LOAD_ANIM_DEFAULT */
        void (*scr_first_create)(void);        /*!< lv_scr_mgr_switch  lv_scr_mgr_push 函数会调用该创建函数 pop则不会调用 可以方便实现pop记住焦点 而push使用默认焦点 */
        lv_obj_t* (*scr_create) (const uint32_t id, void* param); /*!< 创建界面,创建界面时不要使用 lv_scr_mgr_xxx 函数 */
        void (*scr_destroy)(void);             /*!< 删除界面的回调函数,一般用于删除如 lv_timer 等不会随界面自动删除的资源 */
    }lv_scr_mgr_handle_t;
    
    typedef struct _lv_scr_mgr_stack_node_t
    {
        const lv_scr_mgr_handle_t* handle;
        lv_obj_t* scr;
        struct _lv_scr_mgr_stack_node_t* prev;
        struct _lv_scr_mgr_stack_node_t* next;
    }lv_scr_mgr_stack_node_t;
    
    #include "lv_scr_mgr_port.h"
    #if LV_SCR_MGR_REG_ENABLE
    #define  ANONY_CONN(type, var)   type  var
    #define  ANONY_DEF(type,prefix)  ANONY_CONN(type, prefix)
    #define  ANONY_TYPE(type,prefix) ANONY_DEF(type, prefix)
    
    #if defined(__CC_ARM) || defined(__GNUC__) /* ARM,GCC*/
    #define SECTION(x)                  __attribute__((section(x)))
    #define USED                        __attribute__((used))
    #elif defined (__ICCARM__)              /*IAR */
    #define SECTION(x)                  @ x
    #define USED                        __root
    #else
    #error "Current tool chain haven't supported yet!"
    #endif
    
    
    #define _LV_SCR_MGR_REG(handle, level)           \
        USED ANONY_TYPE(const lv_scr_mgr_handle_t*, scr_mgr_##handle)\
        SECTION("scr_mgr."level) = &(handle)
        
    #define LV_SCR_MGR_REG(handle)  _LV_SCR_MGR_REG(handle, "1") 
    #else
    #define LV_SCR_MGR_REG(handle)     
    #endif
        
    
    bool lv_scr_mgr_init(void* param);
    void lv_scr_mgr_deinit(void);
    void lv_scr_mgr_param_set(void* param);
    void* lv_scr_mgr_param_get(void);
    
    bool lv_scr_mgr_switch(uint32_t id, bool anim);
    bool lv_scr_mgr_push(uint32_t id, bool anim);
    bool lv_scr_mgr_popn(uint32_t n, bool anim);
    bool lv_scr_mgr_pop(bool anim);
    bool lv_scr_mgr_pop_root(bool anim);
    int32_t lv_scr_mgr_get_cur_id(void);
    int32_t lv_scr_mgr_get_root_id(void);
    #ifdef __cplusplus
    }
    #endif
    
    #endif /* _LV_SCR_MGR_H_ */
    
    /************************ (C) COPYRIGHT *****END OF FILE*****************/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • lv_scr_mgr_port.c
    /**
      *******************************CopyRight  ************************************
      * @file    lv_scr_mgr_port.c
      * @author  zyf
      * @date    2023-10-11 13:51:24
      * @brief   lvgl 页面管理器 接口
      *          
      ******************************************************************************
      */
    
    /* Includes ------------------------------------------------------------------*/
    #include "lv_scr_mgr.h"
    #include "lv_scr_mgr_port.h"
    
    
    #if LV_SCR_MGR_REG_ENABLE
    
    /* 无需用户修改 */
    const lv_scr_mgr_handle_t  scr_mgr_start = {0};
    _LV_SCR_MGR_REG(scr_mgr_start, "0");
    const lv_scr_mgr_handle_t  scr_mgr_end = {0};
    _LV_SCR_MGR_REG(scr_mgr_end, "2");
    
    #else
    
    /* 需要用户添加自己的界面句柄 */
    extern const lv_scr_mgr_handle_t s_scr_mgr_handle_test1;
    extern const lv_scr_mgr_handle_t s_scr_mgr_handle_test2;
    extern const lv_scr_mgr_handle_t s_scr_mgr_handle_test3;
    static const lv_scr_mgr_handle_t* scr_mgr_handles[] = {
        & s_scr_mgr_handle_test1,
        & s_scr_mgr_handle_test2,
        & s_scr_mgr_handle_test3,
    };
    
    uint32_t lv_scr_mgr_get_cnt(void)
    {
        return sizeof(scr_mgr_handles) / sizeof(scr_mgr_handles[0]);
    }
    
    const lv_scr_mgr_handle_t** lv_scr_mgr_get_handles(void)
    {
        return scr_mgr_handles;
    }
    
    #endif
    
    /************************ (C) COPYRIGHT ***********END OF FILE*****************/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • lv_scr_mgr_port.h
    /**
      *******************************CopyRight  ************************************
      * @file    lv_scr_mgr_port.h
      * @author  zyf
      * @date    2023-10-11 13:51:23
      * @brief   lvgl 页面管理器 接口
      *          
      ******************************************************************************
      */
    
    /* Define to prevent recursive inclusion -------------------------------------*/
    #ifndef _LV_SCR_MGR_PORT_H_
    #define _LV_SCR_MGR_PORT_H_
    
    /* Includes ------------------------------------------------------------------*/
    #include "lvgl.h"
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    typedef enum
    {
        eScreenUITest1 = 0,
        eScreenUITest2,
        eScreenUITest3
    }lv_scr_mgr_id_e;
    
    #if !LV_SCR_MGR_REG_ENABLE
    uint32_t lv_scr_mgr_get_cnt(void);
    const lv_scr_mgr_handle_t** lv_scr_mgr_get_handles(void);
    #endif
    #ifdef __cplusplus
    }
    #endif
    
    #endif /* _LV_SCR_MGR_PORT_H_ */
    
    /************************ (C) COPYRIGHT ***********END OF FILE*****************/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
  • 相关阅读:
    unittest框架
    可以从以下几点着手选择期货开户公司
    Android系统10 RK3399 init进程启动(三十七) 属性代码编程
    华为实习总结xkh
    保姆级快速搭建一套基于Linux环境下的MQTT开发程序模版(基于腾讯云IoT Explorer)...
    ES6-箭头函数-this指向-rest参数(三点运算符)
    8、多进程之间的通信
    Kruskal算法求最小生成树
    【梳理】第一章 浅谈物体检测与PyTorch
    TypeScript学习笔记
  • 原文地址:https://blog.csdn.net/weixin_42378319/article/details/133802869