使用LVGL仿手机界面

1.介绍

使用LVGL仿手机界面

如上图所示,模拟手机界面

分辨率:240*320

在esp32c3中能运行

在stm32中编译后,内存消耗如下图所示,我没有那么大rom的板子,无法验证

2.代码

.h文件

#pragma once
#include "lvgl.h"
#include <iostream>
namespace zxc {
    extern "C" const lv_font_t zxc_font_siyuan;
    constexpr int TOP_MARGIN = 20;
    // extern "C" const lv_image_dsc_t zxc_bg;
    extern "C" const lv_image_dsc_t ble_label;
    extern "C" const lv_image_dsc_t img_label;
    extern "C" const lv_image_dsc_t music_label;
    extern "C" const lv_image_dsc_t rl_label;
    extern "C" const lv_image_dsc_t set_label;

    class ZxcMenu;

    class ZxcStatusBar {

    private:
        lv_obj_t* status_bar;
        lv_obj_t* main_screen;
        lv_obj_t* place1;
        ZxcMenu* ctrl_obj;
        
        lv_obj_t* add_status_icon(lv_obj_t* parent, const char* text, lv_align_t align, int32_t x_ofs);
        lv_obj_t* add_scroll_page(lv_obj_t* parent);
        static void on_scroll_event(lv_event_t* e);
        lv_obj_t* add_bar_switch(lv_obj_t* parent, int32_t w, int32_t h, const char* icon, const char* text,bool is_circle=false);

        static void wifi_button_cb(lv_event_t* e);
        static void ble_button_cb(lv_event_t* e);

    public:
        lv_obj_t* time_label;
        lv_obj_t* battery_icon;
        lv_obj_t* wifi_icon;
        lv_obj_t* ble_icon;
        lv_obj_t* wifi_swtich2;
        lv_obj_t* ble_swtich2;
        void init();
        void set_visable(lv_obj_t* obj);
        void set_hidden(lv_obj_t* obj);
        void set_ctrl_obj(ZxcMenu* obj);
    };
    class ZxcMain {
    private:
        static lv_obj_t* setting_screen;
        lv_obj_t* _parent;
        lv_obj_t* tv;
        lv_obj_t* base;
        

        lv_obj_t* add_cell(lv_obj_t* parent, const void* icon, const char* text, const lv_font_t* font = NULL, int32_t size = 46, lv_event_cb_t event_cb=NULL, void* user_data=NULL);

    public:

        void init(lv_obj_t*);
        void add_app_icon(const void* icon, const char* text, int32_t pos_x, int32_t pos_y, lv_event_cb_t event_cb = NULL, void* user_data = NULL, const lv_font_t* font=&zxc_font_siyuan);
        void load_screen();
        lv_obj_t* get_parent() {
            return _parent;
        }
        

    };

    class ZxcMenu {

    private:

        lv_obj_t* menu;
        ZxcMain* main_screen;
        
        ZxcStatusBar* sb;
        static void back_event_handler(lv_event_t* e);
        static void dark_switch_cb(lv_event_t* e);
        lv_obj_t* setting_page();
        lv_obj_t* dark_model_page();
        lv_obj_t* info_page();
        lv_obj_t* info_bb_page();
        lv_obj_t* info_creater_page();
        lv_obj_t* net_page();
        lv_obj_t* store_page();
        lv_obj_t* elect_page();
        lv_obj_t* add_arc_only_bg(lv_obj_t* parent, lv_value_precise_t angle_start,
            lv_value_precise_t angle_end, lv_color_t color, int32_t width, int32_t size);
        lv_obj_t* add_page();
        lv_obj_t* add_page_text(lv_obj_t* parent_page, const char* icon, const char* txt, const lv_font_t* font = NULL, lv_obj_t* sub_page = NULL, bool double_pavk = false);
        lv_obj_t* add_slider(lv_obj_t* parent, const char* icon, const char* txt, const lv_font_t* font, int32_t min, int32_t max, int32_t val);
        lv_obj_t* add_switch(lv_obj_t* parent, const char* icon, const char* txt, const lv_font_t* font, lv_event_cb_t event_cb = NULL, void* user_data = NULL, bool check = false);
        lv_obj_t* add_dot(lv_obj_t* parent, int32_t size, lv_color_t color);

        static void main_icon_button_cb(lv_event_t* e);
        static void wifi_button_cb(lv_event_t* e);
        static void ble_button_cb(lv_event_t* e);
    public:
        lv_obj_t* wifi_switch;
        lv_obj_t* ble_switch;
        //在嵌入式系统中new是不安全,所以提供空参构造,然后使用init初始化
        ZxcMenu(){
        };
        void init(lv_obj_t* parent);
        ZxcMenu(lv_obj_t* parent);
        void create_menu_default();
        void set_bg_color();
        void set_status_bar_obj(ZxcStatusBar* b);

        

        void add_to_main_icon(ZxcMain& m);

        void load_screen();

    };

    
}

#include "ZxcLvglUtils.h"

namespace zxc {

    
    //extern "C" const lv_font_t zxc_font_demo;
    void ZxcMenu::init(lv_obj_t* parent)
    {
        menu = lv_menu_create(parent);//创建菜单
        create_menu_default();
    }
    ZxcMenu::ZxcMenu(lv_obj_t* parent) {

        init(parent);

    }

    void ZxcMenu::create_menu_default() {
        
        lv_obj_set_style_bg_color(menu, lv_color_darken(lv_obj_get_style_bg_color(menu, 0), TOP_MARGIN), 0);//使背景变暗
        lv_menu_set_mode_root_back_button(menu, LV_MENU_ROOT_BACK_BUTTON_ENABLED);
        
        /*lv_display_get_horizontal_resolution(NULL);
        lv_display_get_vertical_resolution(NULL);*/
        lv_obj_set_size(menu, lv_display_get_horizontal_resolution(NULL), lv_display_get_vertical_resolution(NULL));//设置大小填整个父对象
        lv_obj_center(menu);//中心

        lv_obj_t* page;
        lv_obj_t* sub_page;
        lv_obj_t* main_page = add_page();
        lv_obj_t* section  = lv_menu_section_create(main_page);//添加外圈包围
        page = add_page_text(section,LV_SYMBOL_SETTINGS, "设置",&zxc_font_siyuan);
        sub_page = setting_page();//创建子页面
        lv_menu_set_load_page_event(menu, page, sub_page);//关联子页面
        page = add_page_text(section, LV_SYMBOL_SETTINGS, "模式", &zxc_font_siyuan);
        sub_page = dark_model_page();
        lv_menu_set_load_page_event(menu, page, sub_page);//关联子页面
        page = add_page_text(section, LV_SYMBOL_SETTINGS, "信息", &zxc_font_siyuan);
        sub_page = info_page();
        lv_menu_set_load_page_event(menu, page, sub_page);//关联子页面
        page = add_page_text(section, LV_SYMBOL_SETTINGS, "网络", &zxc_font_siyuan);
        sub_page = net_page();
        lv_menu_set_load_page_event(menu, page, sub_page);//关联子页面
        page = add_page_text(section, LV_SYMBOL_SETTINGS, "电量", &zxc_font_siyuan);
        sub_page = elect_page();
        lv_menu_set_load_page_event(menu, page, sub_page);//关联子页面
        page = add_page_text(section, LV_SYMBOL_SETTINGS, "存储", &zxc_font_siyuan);

        sub_page = store_page();
        lv_menu_set_load_page_event(menu, page, sub_page);//关联子页面

        
        
        lv_menu_set_sidebar_page(menu, main_page);
    }

    void ZxcMenu::set_bg_color()
    {

    }

    void ZxcMenu::set_status_bar_obj(ZxcStatusBar* b)
    {
        sb = b;
        lv_obj_add_event_cb(wifi_switch, wifi_button_cb, LV_EVENT_VALUE_CHANGED, b);
        lv_obj_add_event_cb(ble_switch, ble_button_cb, LV_EVENT_VALUE_CHANGED, b);
        b->set_ctrl_obj(this);

    }



    lv_obj_t* ZxcMenu::add_page()
    {

        lv_obj_t* sub_page = lv_menu_page_create(menu, NULL);
        lv_obj_set_style_pad_hor(sub_page, lv_obj_get_style_pad_left(lv_menu_get_main_header(menu), 0), 0);
        lv_menu_separator_create(sub_page);
        return sub_page;
    }

    lv_obj_t* ZxcMenu::add_page_text(lv_obj_t* parent_page, const char* icon, const char* txt, const lv_font_t* font, lv_obj_t* sub_page, bool double_pavk)
    {
        lv_obj_t* cnt = lv_menu_cont_create(parent_page);
        lv_obj_t* label = NULL;
        lv_obj_t* img = NULL;
        if (icon)
        {
            img = lv_image_create(cnt);
            lv_image_set_src(img, icon);
        }

        
        if (sub_page)
        {
            lv_menu_set_load_page_event(menu, cnt, sub_page);
        }
        
        if (txt)
        {
            label = lv_label_create(cnt);
            lv_label_set_text(label, txt);
            lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR);//设置字体滚动
            lv_obj_set_flex_grow(label, 1);//设置滑块在其父容器中的 flex 属性,1 表示滑块会扩展以填满父容器中剩余的空间。
            if (font)
            {
                lv_obj_set_style_text_font(label, font, 0);
            }
        }

        if (double_pavk&& img && label)
        {
            lv_obj_add_flag(img, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK);//在新的行/列
            lv_obj_swap(img, label);//交换布局位置
        }
           
        
        return cnt;

        
    }

    lv_obj_t* ZxcMenu::add_slider(lv_obj_t* parent, const char* icon, const char* txt, const lv_font_t* font, int32_t min, int32_t max,int32_t val)
    {


        lv_obj_t* obj = add_page_text(parent, icon, txt,font,NULL,true);

        lv_obj_t* slider = lv_slider_create(obj);
        lv_obj_set_flex_grow(slider, 1);
        lv_slider_set_range(slider, min, max);
        lv_slider_set_value(slider, val, LV_ANIM_OFF);

        if (icon == NULL) {
            lv_obj_add_flag(slider, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK);
        }

        return obj;
    }

    lv_obj_t* ZxcMenu::add_switch(lv_obj_t* parent, const char* icon, const char* txt,  const lv_font_t* font, lv_event_cb_t event_cb, void* user_data, bool check)
    {
        lv_obj_t* obj = add_page_text(parent, icon, txt, font, NULL, false);

        lv_obj_t* sw = lv_switch_create(obj);
        lv_obj_add_state(sw, check ? LV_STATE_CHECKED : 0);
        if (event_cb)
        {
            lv_obj_add_event_cb(sw, event_cb, LV_EVENT_VALUE_CHANGED, user_data);
        }
        

        return sw;
    }

    lv_obj_t* ZxcMenu::add_dot(lv_obj_t* parent, int32_t size, lv_color_t color)
    {
        lv_obj_t* dot = lv_obj_create(parent);
        lv_obj_set_size(dot, size, size);
        lv_obj_remove_style(dot, NULL, LV_PART_SCROLLBAR);
        lv_obj_set_style_border_width(dot, 0, 0);
        lv_obj_set_style_radius(dot, LV_RADIUS_CIRCLE, 0);
        lv_obj_set_style_bg_color(dot, color, 0);
        
        

        return dot;
    }

    void ZxcMenu::main_icon_button_cb(lv_event_t* e)
    {
        ZxcMenu* m = (ZxcMenu*)lv_event_get_user_data(e);
        m->load_screen();
    }

    void ZxcMenu::wifi_button_cb(lv_event_t* e)
    {
        lv_event_code_t code = lv_event_get_code(e);//获取事件触发码
        lv_obj_t* obj = (lv_obj_t*)lv_event_get_target(e);//获取触发事件的目标
        ZxcStatusBar* data = (ZxcStatusBar*)lv_event_get_user_data(e);//获取用户数据

        if (code == LV_EVENT_VALUE_CHANGED)
        {
            if (lv_obj_has_state(obj, LV_STATE_CHECKED))//如果开启,则显示
            {
                data->set_visable(data->wifi_icon);
                lv_obj_add_state(data->wifi_swtich2, LV_STATE_CHECKED);
                
            }
            else
            {
                data->set_hidden(data->wifi_icon);
                lv_obj_remove_state(data->wifi_swtich2, LV_STATE_CHECKED);
            }
        }
    }

    void ZxcMenu::ble_button_cb(lv_event_t* e)
    {
        lv_event_code_t code = lv_event_get_code(e);
        lv_obj_t* obj = (lv_obj_t*)lv_event_get_target(e);
        ZxcStatusBar* data = (ZxcStatusBar*)lv_event_get_user_data(e);

        if (code == LV_EVENT_VALUE_CHANGED)
        {
            if (lv_obj_has_state(obj, LV_STATE_CHECKED))
            {
                data->set_visable(data->ble_icon);
                lv_obj_add_state(data->ble_swtich2, LV_STATE_CHECKED);
            }
            else
            {
                data->set_hidden(data->ble_icon);
                lv_obj_remove_state(data->ble_swtich2, LV_STATE_CHECKED);
            }
        }
    }


    void ZxcMenu::add_to_main_icon(ZxcMain& m)
    {
        main_screen = &m;
        m.add_app_icon(&set_label, "设置", 1, 2, main_icon_button_cb,this);
        lv_obj_add_event_cb(menu, back_event_handler, LV_EVENT_CLICKED, this);
    }

    void ZxcMenu::load_screen()
    {
        lv_screen_load(menu);
    }

    void ZxcMenu::back_event_handler(lv_event_t* e)
    {
        lv_obj_t* obj = (lv_obj_t*)lv_event_get_target(e);
        ZxcMenu* menu = (ZxcMenu*)lv_event_get_user_data(e);
        

        if (lv_menu_back_button_is_root(menu->menu, obj)) {
            menu->main_screen->load_screen();
        }
        
    }

    void ZxcMenu::dark_switch_cb(lv_event_t* e)
    {
        lv_event_code_t code = lv_event_get_code(e);
        lv_obj_t* obj = (lv_obj_t*)lv_event_get_target(e);
        if (code == LV_EVENT_VALUE_CHANGED) {
            lv_obj_t* mbox1 = lv_msgbox_create(NULL);
            lv_msgbox_add_title(mbox1, "callback");
            if (lv_obj_has_state(obj, LV_STATE_CHECKED)) {

                lv_msgbox_add_text(mbox1, "dark switch checked");
                lv_msgbox_add_close_button(mbox1);
            }
            else {

                lv_msgbox_add_text(mbox1, "dark switch not check");
                lv_msgbox_add_close_button(mbox1);
            }
            
        }
        
    }

    lv_obj_t* ZxcMenu::setting_page()
    {
        lv_obj_t* page = lv_menu_page_create(menu, NULL);
        lv_obj_set_style_pad_hor(page, lv_obj_get_style_pad_left(lv_menu_get_main_header(menu), 0), 0);
        lv_menu_separator_create(page);
        lv_obj_t* section = lv_menu_section_create(page);//添加底色
        lv_obj_set_style_margin_top(section, TOP_MARGIN, 0);//设置外边距  
        add_slider(section, LV_SYMBOL_VOLUME_MAX, "音量", &zxc_font_siyuan, 0, 100, 50);
        add_slider(section, LV_SYMBOL_SETTINGS, "速度", &zxc_font_siyuan, 0, 100, 30);
        add_slider(section, LV_SYMBOL_SETTINGS, "控制", &zxc_font_siyuan, 0, 100, 80);



        return page;
    }

    lv_obj_t* ZxcMenu::dark_model_page()
    {
        lv_obj_t* page = lv_menu_page_create(menu, NULL);
        lv_obj_set_style_pad_hor(page, lv_obj_get_style_pad_left(lv_menu_get_main_header(menu), 0), 0);
        lv_menu_separator_create(page);
        lv_obj_t* section = lv_menu_section_create(page);//添加底色
        lv_obj_set_style_margin_top(section, TOP_MARGIN, 0);//设置外边距
        add_switch(section, LV_SYMBOL_SETTINGS, "测试", &zxc_font_siyuan, dark_switch_cb);
        return page;
    }

    lv_obj_t* ZxcMenu::info_page()
    {
        lv_obj_t* page = lv_menu_page_create(menu, NULL);
        lv_obj_set_style_pad_hor(page, lv_obj_get_style_pad_left(lv_menu_get_main_header(menu), 0), 0);
        lv_menu_separator_create(page);
        lv_obj_t* section = lv_menu_section_create(page);//添加底色
        lv_obj_set_style_margin_top(section, TOP_MARGIN, 0);//设置外边距

        lv_obj_t* cnt = add_page_text(section, NULL, "版本", &zxc_font_siyuan, NULL);
        lv_obj_t* sub_page = info_bb_page();
        lv_menu_set_load_page_event(menu, cnt, sub_page);
        
        cnt = add_page_text(section, NULL, "开发者", &zxc_font_siyuan, NULL);
        sub_page = info_creater_page();
        lv_menu_set_load_page_event(menu, cnt, sub_page);
        return page;
    }

    lv_obj_t* ZxcMenu::info_bb_page()
    {
        lv_obj_t* page = add_page();
        lv_obj_t* section = lv_menu_section_create(page);//添加底色
        lv_obj_set_style_margin_top(section, TOP_MARGIN, 0);//设置外边距
        add_page_text(section, NULL, "Version 0.0.0");

        return page;
    }

    lv_obj_t* ZxcMenu::info_creater_page()
    {
        lv_obj_t* page = add_page();
        lv_obj_t* section = lv_menu_section_create(page);//添加底色
        lv_obj_set_style_margin_top(section, TOP_MARGIN, 0);//设置外边距
        add_page_text(section, NULL, "作者:ZXC", &lv_font_simsun_16_cjk);
        
        return page;
    }

    lv_obj_t* ZxcMenu::net_page()
    {
        lv_obj_t* page = add_page();
        lv_obj_t* section = lv_menu_section_create(page);//添加底色
        lv_obj_set_style_margin_top(section, TOP_MARGIN, 0);//设置外边距
        wifi_switch = add_switch(section, LV_SYMBOL_WIFI, "WIFI", NULL, NULL);
        ble_switch = add_switch(section, LV_SYMBOL_BLUETOOTH, "蓝牙", &zxc_font_siyuan, NULL);

        return page;
    }

    lv_obj_t* ZxcMenu::store_page()
    {
        lv_obj_t* page = add_page();
        lv_obj_t* section = lv_menu_section_create(page);//添加底色
        lv_obj_set_flex_align(section, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
        lv_obj_set_style_margin_top(section, TOP_MARGIN, 0);//设置外边距
        lv_obj_t* content = lv_obj_create(section);
        lv_obj_set_style_border_width(content, 0, LV_PART_MAIN);

        add_arc_only_bg(content, 0, 80, lv_palette_main(LV_PALETTE_BLUE), 10, 100);
        lv_obj_t* dot1 = add_dot(section, 10, lv_palette_main(LV_PALETTE_BLUE));
        lv_obj_t* label1 = lv_label_create(section);
        lv_label_set_text(label1, "文件");
        lv_obj_set_style_text_font(label1, &zxc_font_siyuan, 0);
        add_arc_only_bg(content, 80, 240, lv_palette_main(LV_PALETTE_GREEN), 13, 100);
        lv_obj_t* dot2 = add_dot(section, 10, lv_palette_main(LV_PALETTE_GREEN));
        lv_obj_t* label2 = lv_label_create(section);
        lv_label_set_text(label2, "视频");
        lv_obj_set_style_text_font(label2, &zxc_font_siyuan, 0);
        add_arc_only_bg(content, 240, 360, lv_palette_main(LV_PALETTE_RED), 16, 100);
        lv_obj_t* dot3 = add_dot(section, 10, lv_palette_main(LV_PALETTE_RED));
        lv_obj_t* label3 = lv_label_create(section);
        lv_label_set_text(label3, "图片");
        lv_obj_set_style_text_font(label3, &zxc_font_siyuan, 0);

        // 定义列和行的描述数组
        static lv_coord_t col_dsc[] = { LV_GRID_FR(1), LV_GRID_CONTENT,LV_GRID_CONTENT, LV_GRID_FR(4), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST };  // 3列,第二列宽度是第一、三列的2倍
        static lv_coord_t row_dsc[] = { LV_GRID_FR(1),LV_GRID_CONTENT,LV_GRID_CONTENT, LV_GRID_FR(1),LV_GRID_FR(1),LV_GRID_FR(1),LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST };  // 3行
        lv_obj_set_grid_dsc_array(section, col_dsc, row_dsc);
        lv_obj_set_grid_cell(content, LV_GRID_ALIGN_CENTER, 3, 1, LV_GRID_ALIGN_CENTER, 3, 1);
        lv_obj_set_grid_cell(dot1, LV_GRID_ALIGN_CENTER, 1, 1, LV_GRID_ALIGN_CENTER, 1, 1);
        lv_obj_set_grid_cell(dot2, LV_GRID_ALIGN_CENTER, 1, 1, LV_GRID_ALIGN_CENTER, 2, 1);
        lv_obj_set_grid_cell(dot3, LV_GRID_ALIGN_CENTER, 1, 1, LV_GRID_ALIGN_CENTER, 3, 1);

        lv_obj_set_grid_cell(label1, LV_GRID_ALIGN_CENTER, 2, 1, LV_GRID_ALIGN_CENTER, 1, 1);
        lv_obj_set_grid_cell(label2, LV_GRID_ALIGN_CENTER, 2, 1, LV_GRID_ALIGN_CENTER, 2, 1);
        lv_obj_set_grid_cell(label3, LV_GRID_ALIGN_CENTER, 2, 1, LV_GRID_ALIGN_CENTER, 3, 1);

        return page;
    }

    lv_obj_t* ZxcMenu::elect_page()
    {
        lv_obj_t* page = add_page();
        lv_obj_t* section = lv_menu_section_create(page);//添加底色
        lv_obj_set_flex_align(section, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
        lv_obj_set_style_margin_top(section, TOP_MARGIN, 0);//设置外边距
        lv_obj_t* cnt = lv_menu_cont_create(section);

        lv_obj_t* bar = lv_bar_create(cnt);
        lv_obj_remove_style_all(bar);
        lv_obj_set_style_border_width(bar, 2, 0);
        lv_obj_set_style_border_color(bar, lv_palette_main(LV_PALETTE_BLUE), 0);
        lv_obj_set_style_pad_all(bar, 4, 0);
        lv_obj_set_style_radius(bar, 5, 0);
        lv_obj_set_style_bg_opa(bar, LV_OPA_COVER, LV_PART_INDICATOR);
        lv_obj_set_style_bg_color(bar, lv_palette_main(LV_PALETTE_BLUE), LV_PART_INDICATOR);
        lv_obj_set_style_radius(bar, 3, LV_PART_INDICATOR);
        lv_obj_set_flex_grow(bar, 1);
        lv_obj_set_height(bar, 20);
        lv_bar_set_value(bar, 80, LV_ANIM_ON);
        

        add_switch(section, NULL, "省电模式", &zxc_font_siyuan);

        return page;
    }

    lv_obj_t* ZxcMenu::add_arc_only_bg(lv_obj_t* parent, lv_value_precise_t angle_start,
        lv_value_precise_t angle_end, lv_color_t color, int32_t width, int32_t size)
    {

        lv_obj_t* arc = lv_arc_create(parent);
        lv_arc_set_bg_angles(arc, angle_start, angle_end);
        lv_obj_remove_style(arc, NULL, LV_PART_KNOB); // 移除旋钮
        lv_obj_remove_style(arc, NULL, LV_PART_INDICATOR);//移除移动部分
        lv_obj_remove_flag(arc, LV_OBJ_FLAG_CLICKABLE);//去掉点击
        lv_obj_set_style_arc_rounded(arc, false, 0);//移除两端的半圆
        lv_obj_set_style_arc_color(arc, color, 0);  // 设置文件部分的颜色
        lv_obj_set_style_arc_width(arc, width, 0);  // 设置文件部分的宽度
        lv_obj_set_size(arc, size, size);  // 确保大小一致
        lv_obj_align(arc, LV_ALIGN_CENTER, 0, 0);  // 居中对齐
        return arc;
    }


    lv_obj_t* ZxcMain::setting_screen = NULL;
    lv_obj_t* ZxcMain::add_cell(lv_obj_t* parent, const void* icon, const char* text, const lv_font_t* font, int32_t size, lv_event_cb_t event_cb, void* user_data)
    {
        lv_obj_t* cell = lv_obj_create(parent);
        lv_obj_remove_style_all(cell);
        lv_obj_set_flex_flow(cell, LV_FLEX_FLOW_COLUMN);//设置子元素垂直排列。
        lv_obj_set_size(cell, size, size+16);
        lv_obj_set_flex_align(cell, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
        lv_obj_t* btn1 = lv_button_create(cell);
        lv_obj_set_style_radius(btn1, 8, 0);  // 设置圆角为 20
        lv_obj_set_style_clip_corner(btn1, true, 0);  // 开启剪裁,确保图片的角被圆角裁剪
        lv_obj_set_style_bg_opa(btn1, 0, 0);//去掉背景颜色
        lv_obj_set_style_shadow_width(btn1, 0, 0);//去掉阴影
        lv_obj_set_size(btn1, size, size);
        if (event_cb)
        {
            lv_obj_add_event_cb(btn1, event_cb, LV_EVENT_CLICKED, user_data);
        }
        
        lv_obj_t* img1 = lv_image_create(btn1);
        lv_image_set_scale(img1, 140);
        lv_image_set_src(img1, icon);
        lv_obj_align(img1, LV_ALIGN_CENTER, 0, 0);
        lv_obj_t* label = lv_label_create(cell);
        lv_label_set_text(label,text );
        lv_obj_set_style_text_color(label, lv_color_white(), 0);
        if (font)
        {
            lv_obj_set_style_text_font(label, font, 0);
        }
        
        
        return cell;
    }

    void ZxcMain::init(lv_obj_t* parent)
    {
        _parent = parent;
        tv = lv_tileview_create(parent);
        lv_obj_set_style_pad_top(tv, 30, 0);
        lv_obj_set_style_bg_opa(tv, 0, 0);//去掉背景颜色
        //lv_obj_clear_flag(tv, LV_OBJ_FLAG_SCROLLABLE);//去掉滚动条
        lv_obj_set_scrollbar_mode(tv, LV_SCROLLBAR_MODE_OFF);//去掉滚动条,但还可以滑动
        lv_obj_t* tile1 = lv_tileview_add_tile(tv, 0, 0, LV_DIR_RIGHT);
        lv_obj_t* tile2 = lv_tileview_add_tile(tv, 1, 0, LV_DIR_LEFT);

        base = lv_obj_create(tile1);
        lv_obj_center(base);
        lv_obj_set_size(base, lv_obj_get_width(tile1), lv_obj_get_height(tile1));
        lv_obj_set_style_bg_opa(base, 0, 0);//去掉背景颜色
        lv_obj_set_style_border_width(base, 0, 0);

        // 定义列和行的描述数组
        static lv_coord_t col_dsc[] = { LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1),LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST };  // 4列,第二列宽度是第一、三列的2倍
        static lv_coord_t row_dsc[] = { LV_GRID_FR(1), LV_GRID_FR(1),LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST };  // 3行,行宽相等

        // 设置网格布局
        lv_obj_set_grid_dsc_array(base, col_dsc, row_dsc);
        lv_obj_t* cell1;
        /*lv_obj_t* cell1 = add_cell(base, &set_label,"设置", &zxc_font_siyuan);
        lv_obj_set_grid_cell(cell1, LV_GRID_ALIGN_CENTER, 1, 1, LV_GRID_ALIGN_START, 0, 1);*/
        cell1 = add_cell(base, & img_label, "图片", &zxc_font_siyuan);
        lv_obj_set_grid_cell(cell1, LV_GRID_ALIGN_CENTER, 0, 1, LV_GRID_ALIGN_START, 1, 1);
        cell1 = add_cell(base, &music_label, "音乐", &zxc_font_siyuan);
        lv_obj_set_grid_cell(cell1, LV_GRID_ALIGN_CENTER, 2, 1, LV_GRID_ALIGN_START, 0, 1);
        cell1 = add_cell(base, &rl_label, "日历", &zxc_font_siyuan);
        lv_obj_set_grid_cell(cell1, LV_GRID_ALIGN_CENTER, 3, 1, LV_GRID_ALIGN_START, 0, 1);
        
        base = lv_obj_create(tile2);
        lv_obj_center(base);
        lv_obj_set_size(base, lv_obj_get_width(tile2), lv_obj_get_height(tile2));
        lv_obj_set_style_bg_opa(base, 0, 0);//去掉背景颜色
        lv_obj_set_style_border_width(base, 0, 0);

        // 设置网格布局
        lv_obj_set_grid_dsc_array(base, col_dsc, row_dsc);
        cell1 = add_cell(base, &ble_label, "蓝牙", &zxc_font_siyuan);
        lv_obj_set_grid_cell(cell1, LV_GRID_ALIGN_CENTER, 1, 1, LV_GRID_ALIGN_START, 1, 1);

        
    }

    void ZxcMain::add_app_icon(const void* icon, const char* text, int32_t pos_x, int32_t pos_y,lv_event_cb_t event_cb, void* user_data, const lv_font_t* font )
    {
        lv_obj_t* cell1 = add_cell(base, icon, text, font,46, event_cb, user_data);
        lv_obj_set_grid_cell(cell1, LV_GRID_ALIGN_CENTER, pos_y, 1, LV_GRID_ALIGN_START, pos_x, 1);
    }

    void ZxcMain::load_screen()
    {
        lv_screen_load(_parent);
    }

    lv_obj_t* ZxcStatusBar::add_status_icon(lv_obj_t* parent, const char* text, lv_align_t align, int32_t x_ofs)
    {
        lv_obj_t* icon = lv_label_create(parent);
        lv_label_set_text(icon, text); // WiFi图标
        lv_obj_align(icon, align, x_ofs, 0); // 位于电池图标右侧
        lv_obj_set_style_text_color(icon, lv_color_white(), 0);
        lv_obj_set_style_text_opa(icon, LV_OPA_80, 0);
        return icon;
    }

    lv_obj_t* ZxcStatusBar::add_scroll_page(lv_obj_t* parent)
    {
        main_screen = lv_obj_create(parent);
        lv_obj_remove_flag(main_screen, LV_OBJ_FLAG_CLICKABLE);
        lv_obj_remove_flag(main_screen, LV_OBJ_FLAG_SCROLL_ELASTIC);
        lv_obj_remove_style_all(main_screen);
        lv_obj_set_size(main_screen, lv_pct(100), lv_pct(100));//大小为父对象尺寸的100%
        lv_obj_set_scroll_snap_y(main_screen, LV_SCROLL_SNAP_CENTER);//滑动时自动捕捉子对象的中心

        place1 = lv_obj_create(main_screen);
        lv_obj_remove_style_all(place1);//去掉所有样式
        lv_obj_set_size(place1, lv_pct(100), lv_pct(100));
        lv_obj_set_y(place1, 0);
        lv_obj_set_style_bg_color(place1, lv_color_hex(0x252526), 0);
        lv_obj_set_style_bg_opa(place1, LV_OPA_COVER, 0);  // 使背景颜色完全不透明

        wifi_swtich2 = add_bar_switch(place1, 120, 60,LV_SYMBOL_WIFI, "WIFI");
        lv_obj_add_event_cb(wifi_swtich2, wifi_button_cb, LV_EVENT_VALUE_CHANGED, this);
        lv_obj_align(wifi_swtich2, LV_ALIGN_TOP_MID, -75, 20);
        ble_swtich2 = add_bar_switch(place1, 120, 60, LV_SYMBOL_BLUETOOTH, "BLE");
        lv_obj_align(ble_swtich2, LV_ALIGN_TOP_MID, 75, 20);
        lv_obj_add_event_cb(ble_swtich2, ble_button_cb, LV_EVENT_VALUE_CHANGED, this);

        lv_obj_t* abs = add_bar_switch(place1, 60, 60, LV_SYMBOL_GPS, NULL,true);
        lv_obj_align(abs, LV_ALIGN_TOP_MID, -105, 100);
        abs = add_bar_switch(place1, 60, 60, LV_SYMBOL_CALL, NULL, true);
        lv_obj_align(abs, LV_ALIGN_TOP_MID, -35, 100);
        abs = add_bar_switch(place1, 60, 60, LV_SYMBOL_CUT, NULL, true);
        lv_obj_align(abs, LV_ALIGN_TOP_MID, 105, 100);
        abs = add_bar_switch(place1, 60, 60, LV_SYMBOL_BELL, NULL, true);
        lv_obj_align(abs, LV_ALIGN_TOP_MID, 35, 100);


        lv_obj_t* place2 = lv_obj_create(main_screen);
        lv_obj_remove_style_all(place2);//去掉所有样式
        lv_obj_remove_flag(place2, LV_OBJ_FLAG_CLICKABLE);//去掉点击
        lv_obj_set_size(place2, lv_pct(100), lv_pct(100));
        lv_obj_set_y(place2, lv_pct(100)-8);
        lv_obj_scroll_to_view(place2, LV_ANIM_OFF);
        lv_obj_add_event_cb(main_screen, on_scroll_event, LV_EVENT_SCROLL, this);
        return place1;
    }

    void ZxcStatusBar::on_scroll_event(lv_event_t* e)
    {
        ZxcStatusBar* sb = (ZxcStatusBar*)lv_event_get_user_data(e);
        int32_t y = lv_obj_get_scroll_y(sb->main_screen);
        if (y!=220)
        {
            lv_obj_add_flag(sb->status_bar, LV_OBJ_FLAG_HIDDEN);
        }
        else
        {
            lv_obj_clear_flag(sb->status_bar, LV_OBJ_FLAG_HIDDEN);
        }
    }

    lv_obj_t* ZxcStatusBar::add_bar_switch(lv_obj_t* parent, int32_t w, int32_t h, const char* icon,const char* text,bool is_circle)
    {
        // 创建一个开关
        lv_obj_t* wifi_switch = lv_switch_create(parent);
        lv_obj_set_flex_flow(wifi_switch, LV_FLEX_FLOW_ROW);
        lv_obj_set_flex_align(wifi_switch, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
        // 设置开关大小
        lv_obj_set_size(wifi_switch, w, h);
        // 设置关闭状态下的样式(灰色)
        lv_obj_set_style_bg_color(wifi_switch, lv_color_hex(0xAAAAAA), LV_PART_INDICATOR | LV_STATE_DEFAULT);  // 灰色背景
        lv_obj_set_style_bg_opa(wifi_switch, LV_OPA_COVER, LV_PART_INDICATOR | LV_STATE_DEFAULT);  // 完全不透明

        // 设置开启状态下的样式(蓝色)
        lv_obj_set_style_bg_color(wifi_switch, lv_palette_main(LV_PALETTE_BLUE), LV_PART_INDICATOR | LV_STATE_CHECKED);  // 蓝色背景
        lv_obj_set_style_bg_opa(wifi_switch, LV_OPA_COVER, LV_PART_INDICATOR | LV_STATE_CHECKED);  // 完全不透明
        lv_obj_remove_style(wifi_switch, NULL, LV_PART_KNOB);
        if (is_circle)
        {
            lv_obj_set_style_radius(wifi_switch, LV_RADIUS_CIRCLE, LV_PART_INDICATOR);
        }
        else
        {
            lv_obj_set_style_radius(wifi_switch, 12, LV_PART_INDICATOR);
        }
        if (icon)
        {
            lv_obj_t* _icon = lv_label_create(wifi_switch);
            lv_label_set_text(_icon, icon);
            lv_obj_set_style_text_font(_icon, &lv_font_montserrat_24, 0);  // 使用 28 号字体放大图标
            lv_obj_set_style_text_color(_icon, lv_color_white(), 0);
            if (text)
            {
                lv_obj_set_style_pad_right(_icon, 10, 0);
            }
            
        }

        if (text)
        {
            lv_obj_t* label = lv_label_create(wifi_switch);
            lv_label_set_text(label, text);
            lv_obj_set_style_text_color(label, lv_color_white(), 0);
        }
        
        return wifi_switch;
    }

    void ZxcStatusBar::wifi_button_cb(lv_event_t* e)
    {
        lv_event_code_t code = lv_event_get_code(e);//获取事件触发码
        lv_obj_t* obj = (lv_obj_t*)lv_event_get_target(e);//获取触发事件的目标
        ZxcStatusBar* data = (ZxcStatusBar*)lv_event_get_user_data(e);//获取用户数据

        
        if (code == LV_EVENT_VALUE_CHANGED)
        {
            if (lv_obj_has_state(obj, LV_STATE_CHECKED))//如果开启,则显示
            {
                data->set_visable(data->wifi_icon);
                //lv_obj_add_state(data->wifi_swtich2, LV_STATE_CHECKED);

                if (data->ctrl_obj != NULL)
                {
                    lv_obj_add_state(data->ctrl_obj->wifi_switch, LV_STATE_CHECKED);
                }

            }
            else
            {
                data->set_hidden(data->wifi_icon);
                //lv_obj_remove_state(data->wifi_swtich2, LV_STATE_CHECKED);
                if (data->ctrl_obj != NULL)
                {
                    lv_obj_remove_state(data->ctrl_obj->wifi_switch, LV_STATE_CHECKED);
                }
            }
        }
    }

    void ZxcStatusBar::ble_button_cb(lv_event_t* e)
    {

        lv_event_code_t code = lv_event_get_code(e);//获取事件触发码
        lv_obj_t* obj = (lv_obj_t*)lv_event_get_target(e);//获取触发事件的目标
        ZxcStatusBar* data = (ZxcStatusBar*)lv_event_get_user_data(e);//获取用户数据


        if (code == LV_EVENT_VALUE_CHANGED)
        {
            if (lv_obj_has_state(obj, LV_STATE_CHECKED))//如果开启,则显示
            {
                data->set_visable(data->ble_icon);

                if (data->ctrl_obj != NULL)
                {
                    lv_obj_add_state(data->ctrl_obj->ble_switch, LV_STATE_CHECKED);
                }

            }
            else
            {
                data->set_hidden(data->ble_icon);

                if (data->ctrl_obj != NULL)
                {
                    lv_obj_remove_state(data->ctrl_obj->ble_switch, LV_STATE_CHECKED);
                }
            }
        }

    }

    void ZxcStatusBar::init()
    {
        lv_obj_t*  scp = add_scroll_page(lv_scr_act());
        status_bar = lv_obj_create(scp);
        lv_obj_remove_style_all(status_bar);
        lv_obj_set_size(status_bar, lv_pct(100), 20); // 设置高度为20px
        lv_obj_set_style_bg_color(status_bar, lv_color_black(), 0); // 背景色为黑色
        lv_obj_align(status_bar, LV_ALIGN_BOTTOM_MID, 0, 0); // 顶部对齐
        lv_obj_set_style_border_width(status_bar, 0, 0);
        lv_obj_set_style_bg_opa(status_bar, LV_OPA_50, 0);

        // 添加时间标签
        time_label = add_status_icon(status_bar, "12:34", LV_ALIGN_LEFT_MID, 10);
        battery_icon = add_status_icon(status_bar, LV_SYMBOL_BATTERY_FULL, LV_ALIGN_RIGHT_MID, -10);
        wifi_icon = add_status_icon(status_bar, LV_SYMBOL_WIFI, LV_ALIGN_RIGHT_MID, -40);
        ble_icon = add_status_icon(status_bar, LV_SYMBOL_BLUETOOTH, LV_ALIGN_RIGHT_MID, -70);

        set_hidden(wifi_icon);
        set_hidden(ble_icon);
    }

    void ZxcStatusBar::set_visable(lv_obj_t* obj)
    {
        lv_obj_clear_flag(obj, LV_OBJ_FLAG_HIDDEN);
    }

    void ZxcStatusBar::set_hidden(lv_obj_t* obj)
    {
        lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN);
    }

    void ZxcStatusBar::set_ctrl_obj(ZxcMenu* obj)
    {
        ctrl_obj = obj;
    }

}

调用

void zxc_exec_label(lv_indev_t* indev)
{

   lv_obj_set_style_bg_img_src(lv_screen_active(), &zxc_bg, 0);
    menu.init(NULL);
    main_page.init(lv_screen_active());
    sb.init();

    menu.add_to_main_icon(main_page);
    menu.set_status_bar_obj(&sb);


}

3.总结

写一个界面,首先要布局,划分成一个一个的功能区域,再实现每个区域就行。要做到极致,那确实需要长时间的累积经验,但如果只是出于个人需求,先布好局,再向每个区域里面填,还是很容易的。一定要做好笔记,只要自己能看懂就行,如下,我自己写的笔记,很乱,但忘记了回来能翻到就行。一定及时及时及时做笔记,待会儿就忘了记笔记这件事了,哪天突然想翻这个知识点,发现没有,又得重新搞一圈(应该不止我是这样吧吧)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值