UI设计工具文档UI设计工具文档
反馈
  • AC791
  • AC792
  • AC63
  • GPMCU
  • AD14/15/17/18/AD104
  • AD16
  • AD24
  • AC82
  • AW30
  • AW31
反馈
  • AC791
  • AC792
  • AC63
  • GPMCU
  • AD14/15/17/18/AD104
  • AD16
  • AD24
  • AC82
  • AW30
  • AW31
  • 1.工具前言

    • 1.1.工具首页
    • 1.2.前言说明
  • 2.快速使用

    • 2.1.快速使用
    • 2.2.快速上手
    • 2.3.板子配置
    • 2.4.视频教程
    • 2.5.硬件资料
  • 3.控件说明

    • 3.1.控件说明
    • 3.2.基础控件

      • 页面
      • 按钮
      • 图片按钮
      • 标签
      • 图片
      • 文本框
      • 开关
      • 数字微调器
      • 复选框
      • 下拉框
      • 进度条
      • Lottie动画
      • 帧动画
      • 图表
      • 滑动条
      • 弧线
      • 仪表盘
    • 3.3.菜单控件

      • 圆弧菜单
      • 齿轮菜单
      • 列表菜单
      • 曲线菜单
      • 网格菜单
      • 万花筒菜单
      • 多边形菜单
    • 3.4.容器控件

      • 通用容器
      • Flex布局
  • 4.高级功能

    • 4.1.时间轴动画
    • 4.2.模型绑定
    • 4.3.资源管理
    • 4.4.国际化
    • 4.5.硬件仿真
    • 4.6.自动化测试
    • 4.7.控件组
    • 4.8.菜单管理
    • 4.9.页面管理
    • 4.10.动态页面
  • 5.插件系统

    • 5.1.插件说明
    • 5.2.开发指南
    • 5.3.字体合并
    • 5.4.图片编辑
    • 5.5.截图
    • 5.6.项目合并
    • 5.7.项目属性编辑
    • 5.8.视频转图片
  • 6.使用案例

    • 6.1.倒计时案例
  • 7.常见问题

    • 7.1.问题说明
    • 7.2.编译问题
    • 7.3.LVGL问题
    • 7.4.仿真问题
    • 7.5.UI工具问题
    • 7.6.其他问题
  • 8.工具杂项

    • 8.1.杂项1
    • 8.2.杂项2

多边形菜单

多边形菜单是一个用于显示多边形布局的菜单。通过改变不同的 形状, 可以实现不同风格的多边形菜单。

本章目录
  • 1. 属性
    • 1.1. 样式属性
  • 2. 样式
  • 3. 使用
    • 3.1. 六边形
    • 3.2. 编码器滚动加载页面
本章正文

属性

PropertyDescription
Menu菜单项列表
Shape形状,六边形和正方形
Load Screen加载页面,启用后,在菜单项处于 STATUS_ZOOM_4 状态时,点击菜单项会加载到菜单项所关联的页面
Duration加载动画持续时间
Delay加载动画延迟时间
Anim Type加载动画类型
Is Clear加载新屏幕前释放当前屏幕内存, 相当于 lv_obj_clear(obj)
Is Del加载完后删除当前页面, 相当于 lv_obj_del(obj)
Push Satck当前页面是否压入页面栈

样式属性

菜单控件默认会使用 lv_polygonmenu_item_transform_cb 位置变换回调函数处理菜单项的坐标、Zoom 等属性。如果 位置变换 填写了自定义的回调函数名,则使用自定义的位置变换回调函数。

  • 默认位置变换回调函数支持的样式属性
PropertyDescription
Radius球体半径
R Corner球体圆角
Distortion Coeff畸变系数
  • 自定义位置变换回调函数支持的样式属性
PropertyDescription
Nop1自定义属性1
Nop2自定义属性2
Nop3自定义属性3
Nop4自定义属性4

样式

StylePartDescription
Padding LeftMain左内边距
Padding RightMain右内边距
Padding TopMain上内边距
Padding BottomMain下内边距
Padding RowItems行内边距
Padding ColumnItems列内边距

使用

  • 菜单配置

多边形菜单控件默认处于 STATUS_ZOOM_2 状态时,点击菜单项时,会自动放大到 STATUS_ZOOM_4 状态。所以在配置菜单项时,不能像是其他菜单控件那样,通过配置菜单项的事件,来实现点击菜单项时,执行加载页面。

如果需要实现点击菜单项来加载页面,可以通过配置菜单项的 关联页面 来为菜单项绑定页面,在控件属性启用 加载页面 选项,这样点击菜单项时,会自动加载页面。

在下面的菜单配置中,为菜单项都配置了 关联页面。

六边形

  • 控件属性

启用 加载页面 选项后,注意需启用 入页面栈 选项,这样在其他页面点击按钮后,可以返回到菜单页面。

  • 关联页面配置

分别创建了 page1、page2、page3 、page4 四个页面,然后在其页面加了按钮,用于点击后 页面出栈 返回菜单页面。

  • 仿真

编码器滚动加载页面

为了实现编码器滚动,能控制缩放菜单项,当放大到最大状态,能够自动切换到菜单项所关联的页面,为此需要在 custom 目录下实现这个功能。

增加 indev_encode.h 和 indev_encode.c 文件,目的是能接收编码器事件,并处理编码器事件。

  • indev_encode.h
#ifndef INDEV_ENCODE_H
#define INDEV_ENCODE_H

#ifdef __cplusplus
extern "C" {
#endif

#include "lvgl.h"

typedef void (*indev_encode_roll_cb_t)(bool up);

void indev_encode_init();

void indev_encode_set_roll_cb(indev_encode_roll_cb_t cb);

#ifdef __cplusplus
}
#endif // __cplusplus

#endif

  • indev_encode.c
#include "indev_encode.h"
#include "lv_drivers/sdl/sdl.h"
#include "gui_guider.h"

static lv_indev_drv_t indev_encode_drv;
static lv_indev_t * indev;

static indev_encode_roll_cb_t roll_cb;

static void indev_read_timer_cb(lv_timer_t * timer);
static void indev_proc(lv_indev_t * i, lv_indev_data_t * data);
static void indev_proc_reset_query_handler(lv_indev_t * indev);

void indev_encode_init()
{
    lv_indev_drv_init(&indev_encode_drv);
    indev_encode_drv.type = LV_INDEV_TYPE_ENCODER;
#ifdef USE_GUIBUILDER_SIMULATOR
    indev_encode_drv.read_cb = sdl_mousewheel_read;
#else
    indev_encode_drv.read_cb = sdl_mousewheel_read; // TODO: 需要修改为设备自定义的拨盘读取函数
#endif
    indev = lv_indev_drv_register(&indev_encode_drv);
    if(indev->driver->read_timer) {
        lv_timer_del(indev->driver->read_timer);
    }
    indev->driver->read_timer = lv_timer_create(indev_read_timer_cb, LV_INDEV_DEF_READ_PERIOD, indev);
}

void indev_encode_set_roll_cb(indev_encode_roll_cb_t cb)
{
    roll_cb = cb;
}

static void indev_read_timer_cb(lv_timer_t * timer)
{
    lv_indev_data_t data;
    if(indev->driver->disp == NULL)
        return;

    indev_proc_reset_query_handler(indev);
    if(indev->proc.disabled)
        return;

    /*Read the data*/
    _lv_indev_read(indev, &data);

    /*The active object might be deleted even in the read function*/
    indev_proc_reset_query_handler(indev);

    indev->proc.state = data.state;

    /*Save the last activity time*/
    if(indev->proc.state == LV_INDEV_STATE_PRESSED) {
        indev->driver->disp->last_activity_time = lv_tick_get();
    }

    indev_proc(indev, &data);
}

static void indev_proc(lv_indev_t * i, lv_indev_data_t * data)
{
    if(data->state == LV_INDEV_STATE_PRESSED && i->proc.wait_until_release) return;

    if(i->proc.wait_until_release) {
        i->proc.wait_until_release      = 0;
        i->proc.pr_timestamp            = 0;
        i->proc.long_pr_sent            = 0;
        i->proc.types.keypad.last_state = LV_INDEV_STATE_RELEASED; /*To skip the processing of release*/
    }

    /*Save the last keys before anything else.
      *They need to be already saved if the function returns for any reason*/
    lv_indev_state_t last_state     = i->proc.types.keypad.last_state;
    i->proc.types.keypad.last_state = data->state;
    i->proc.types.keypad.last_key   = data->key;

    if(data->state == LV_INDEV_STATE_RELEASED && last_state == LV_INDEV_STATE_PRESSED) {
        return;
    }

    if(data->enc_diff != 0) {
        // -1 :往上拨  1 :往下拨
        bool up = data->enc_diff < 0;
        if(roll_cb) {
            roll_cb(up);
        }
    }
}

/**
 * Process a new point from LV_INDEV_TYPE_BUTTON input device
 * @param i pointer to an input device
 * @param data pointer to the data read from the input device
 * Reset input device if a reset query has been sent to it
 * @param indev pointer to an input device
 */
static void indev_proc_reset_query_handler(lv_indev_t * indev)
{
    if(indev->proc.reset_query) {
        indev->proc.types.pointer.act_obj = NULL;
        indev->proc.types.pointer.last_obj = NULL;
        indev->proc.types.pointer.scroll_obj = NULL;
        indev->proc.long_pr_sent = 0;
        indev->proc.pr_timestamp = 0;
        indev->proc.longpr_rep_timestamp = 0;
        indev->proc.types.pointer.scroll_sum.x = 0;
        indev->proc.types.pointer.scroll_sum.y = 0;
        indev->proc.types.pointer.scroll_dir = LV_DIR_NONE;
        indev->proc.types.pointer.scroll_throw_vect.x = 0;
        indev->proc.types.pointer.scroll_throw_vect.y = 0;
        indev->proc.types.pointer.gesture_sum.x = 0;
        indev->proc.types.pointer.gesture_sum.y = 0;
        indev->proc.reset_query = 0;
    }
}

/**
 * Checks if the reset_query flag has been set. If so, perform necessary global indev cleanup actions
 * @param proc pointer to an input device 'proc'
 * @return true if indev query should be immediately truncated.
 */
static bool indev_reset_check(_lv_indev_proc_t * proc)
{
    // if(proc->reset_query) {
    //     indev_obj_act = NULL;
    // }

    return proc->reset_query ? true : false;
}


在 custom.c 文件中,初始化编码器,并实现 indev_encode_set_roll_cb 函数。

// 编码器滚动回调函数,识别到是多边形菜单所在页面时,根据编码器滚动方向,放大或缩小多边形菜单
static void indev_encode_roll_cb(bool up)
{
    gui_scr_t * act_scr = gui_scr_get_act();
    // 注意将 GUI_SCREEN_POLYGONMENU 替换为实际的多边形菜单所在页面
    if(act_scr->id == GUI_SCREEN_POLYGONMENU) {
        lv_ui_polygonmenu * ui_polygonmenu = (lv_ui_polygonmenu *)ui_get_scr_ptr(&guider_ui, GUI_SCREEN_POLYGONMENU);
        if(up) {
            lv_polygonmenu_zoom_in(ui_polygonmenu->polygonmenu_polygonmenu_1);
        }
        else {
            lv_polygonmenu_zoom_out(ui_polygonmenu->polygonmenu_polygonmenu_1);
        }
    }
}

void custom_init(lv_ui * ui)
{
    indev_encode_init();
    indev_encode_set_roll_cb(indev_encode_roll_cb);
}

  • 仿真
  • 正方形仿真
上一页
万花筒菜单