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
    • 8.3.工具生成API接口
    • 8.4.自定义Symbol

进度条

进度条控件用于显示操作的进度。

本章目录
  • 1. 属性
    • 1.1. 进度条模式
  • 2. 样式
  • 3. 控件支持的绑定属性
  • 4. 使用
    • 4.1. 不同模式下的进度条
    • 4.2. 背景图片进度条
    • 4.3. 自定义进度条
本章正文

属性

PropertyDescription
Range数值范围
Value当前值
Animation Enable是否启用动画,启用后数值变化时会有动画效果
Animation Time动画时长, 单位毫秒
Bar Mode进度条模式

进度条模式

  • Normal:正常模式,普通进度条
  • Symmetrical:对称模式,从零值到当前值绘制指示器。需要负的最小范围和正的最大范围

样式

PartDescription
Main主样式
Indicator指示器样式

控件支持的绑定属性

PropertyTypeDescriptionSync Mode
Valueint32_tOneWayModelToView

使用

不同模式下的进度条

  • 控件属性

两个进度条的属性与基本进度条相同,只是 Bar Mode 属性不同。

  • 仿真

背景图片进度条

通过设置不同 Part 的 Bg Image 属性,可以实现更丰富的进度条样式。

  • 控件属性

为了仿真时,更好看出进度条的样式,这里为进度条、滑动条控件都绑定了 Value 属性。

  • 仿真

自定义进度条

通过重绘控件来实现更多自定义进度条样式。

  • 控件属性

为了仿真时,更好看出进度条的样式,这里为进度条、弧形控件都绑定了 Value 属性。

在 custom.c 文件中,重新实现 draw_rounded_border 函数

void draw_rounded_rect_progress(lv_draw_ctx_t * draw_ctx,
                                const lv_area_t * rect_area, lv_coord_t radius,
                                const lv_draw_line_dsc_t * line_dsc,
                                const lv_draw_arc_dsc_t * arc_dsc,
                                float progress)
{
    if(progress <= 0.0f)
        return;

    lv_coord_t rect_x = rect_area->x1;
    lv_coord_t rect_y = rect_area->y1;
    lv_coord_t rect_w = lv_area_get_width(rect_area);
    lv_coord_t rect_h = lv_area_get_height(rect_area);
    lv_coord_t border_width = line_dsc->width;

    // 计算圆角矩形的各个部分长度
    lv_coord_t straight_w = rect_w - 2 * radius; // 顶边和底边的直线部分
    lv_coord_t straight_h = rect_h - 2 * radius; // 左边和右边的直线部分
    float quarter_circle = 3.14159f * radius / 2.0f; // 四分之一圆的弧长

    float total_perimeter;
    float progress_length;
    float current_length = 0;

    // 从顶部中间开始:顶边右半部分 + 右上角 + 右边 + 右下角 + 底边 + 左下角 + 左边 + 左上角 + 顶边左半部分
    total_perimeter = straight_w / 2 + quarter_circle + straight_h +
                      quarter_circle + straight_w + quarter_circle + straight_h +
                      quarter_circle + straight_w / 2;

    progress_length = total_perimeter * progress;

    // 1. 顶边右半部分(从中间到右边)
    if(progress_length > current_length && straight_w > 0) {
        float segment_progress = LV_MIN(progress_length - current_length, straight_w / 2);
        lv_coord_t start_x = rect_x + rect_w / 2; // 从顶部中间开始
        lv_point_t p1 = {start_x, rect_y + border_width / 2};
        lv_point_t p2 = {start_x + (lv_coord_t)segment_progress, rect_y + border_width / 2};
        if(segment_progress + 1 > straight_w / 2) {
            // 解决直线到曲线出现缝隙的问题
            p2.x++;
        }
        lv_draw_line(draw_ctx, line_dsc, &p1, &p2);
    }
    current_length += straight_w / 2;

    // 2. 右上角圆角 (从270°开始,顺时针到0°)
    if(progress_length > current_length && radius > 0) {
        float segment_progress = LV_MIN(progress_length - current_length, quarter_circle);
        int16_t start_angle = 270; // 270°
        int16_t end_angle = 270 + (int16_t)((segment_progress / quarter_circle) * 90); // 270° to 360°
        lv_point_t center = {rect_x + rect_w - radius, rect_y + radius};
        lv_draw_arc(draw_ctx, arc_dsc, &center, radius, start_angle, end_angle);
    }
    current_length += quarter_circle;

    // 3. 右边直线部分(从上到下)
    if(progress_length > current_length && straight_h > 0) {
        float segment_progress = LV_MIN(progress_length - current_length, straight_h);
        lv_point_t p1 = {rect_x + rect_w - border_width / 2, rect_y + radius};
        lv_point_t p2 = {rect_x + rect_w - border_width / 2, rect_y + radius + (lv_coord_t)segment_progress};
        lv_draw_line(draw_ctx, line_dsc, &p1, &p2);
    }
    current_length += straight_h;

    // 4. 右下角圆角 (从0°开始,顺时针到90°)
    if(progress_length > current_length && radius > 0) {
        float segment_progress = LV_MIN(progress_length - current_length, quarter_circle);
        int16_t start_angle = 0; // 0°
        int16_t end_angle = (int16_t)((segment_progress / quarter_circle) * 90); // 0° to 90°
        lv_point_t center = {rect_x + rect_w - radius, rect_y + rect_h - radius};
        lv_draw_arc(draw_ctx, arc_dsc, &center, radius, start_angle, end_angle);
    }
    current_length += quarter_circle;

    // 5. 底边直线部分(从右到左)
    if(progress_length > current_length && straight_w > 0) {
        float segment_progress = LV_MIN(progress_length - current_length, straight_w);
        lv_point_t p1 = {rect_x + rect_w - radius, rect_y + rect_h - border_width / 2};
        lv_point_t p2 = {rect_x + rect_w - radius - (lv_coord_t)segment_progress, rect_y + rect_h - border_width / 2};
        lv_draw_line(draw_ctx, line_dsc, &p1, &p2);
    }
    current_length += straight_w;

    // 6. 左下角圆角 (从90°开始,顺时针到180°)
    if(progress_length > current_length && radius > 0) {
        float segment_progress = LV_MIN(progress_length - current_length, quarter_circle);
        int16_t start_angle = 90; // 90°
        int16_t end_angle = 90 + (int16_t)((segment_progress / quarter_circle) * 90); // 90° to 180°
        lv_point_t center = {rect_x + radius, rect_y + rect_h - radius};
        lv_draw_arc(draw_ctx, arc_dsc, &center, radius, start_angle, end_angle);
    }
    current_length += quarter_circle;

    // 7. 左边直线部分(从下到上)
    if(progress_length > current_length && straight_h > 0) {
        float segment_progress = LV_MIN(progress_length - current_length, straight_h);
        lv_point_t p1 = {rect_x + border_width / 2, rect_y + rect_h - radius};
        lv_point_t p2 = {rect_x + border_width / 2, rect_y + rect_h - radius - (lv_coord_t)segment_progress};
        lv_draw_line(draw_ctx, line_dsc, &p1, &p2);
    }
    current_length += straight_h;

    // 8. 左上角圆角 (从180°开始,顺时针到270°)
    if(progress_length > current_length && radius > 0) {
        float segment_progress = LV_MIN(progress_length - current_length, quarter_circle);
        int16_t start_angle = 180; // 180°
        int16_t end_angle = 180 + (int16_t)((segment_progress / quarter_circle) * 90); // 180° to 270°
        lv_point_t center = {rect_x + radius, rect_y + radius};
        lv_draw_arc(draw_ctx, arc_dsc, &center, radius, start_angle, end_angle);
    }
    current_length += quarter_circle;

    // 9. 顶边左半部分(从左边到中间)
    if(progress_length > current_length && straight_w > 0) {
        float segment_progress = LV_MIN(progress_length - current_length, straight_w / 2);
        lv_point_t p1 = {rect_x + radius, rect_y + border_width / 2};
        lv_point_t p2 = {rect_x + radius + (lv_coord_t)segment_progress, rect_y + border_width / 2};
        lv_draw_line(draw_ctx, line_dsc, &p1, &p2);
    }
}

void draw_rounded_border(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    if(code == LV_EVENT_DRAW_MAIN) {
        lv_obj_t * obj = lv_event_get_target(e);
        lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e);

        // 获取bar的当前值和进度百分比
        int32_t current_value = lv_bar_get_value(obj);
        int32_t min_value = lv_bar_get_min_value(obj);
        int32_t max_value = lv_bar_get_max_value(obj);
        float progress = (float)(current_value - min_value) / (max_value - min_value);

        lv_coord_t rect_w = lv_obj_get_width(obj);
        lv_coord_t rect_h = lv_obj_get_height(obj);
        lv_coord_t rect_x = lv_obj_get_x(obj);
        lv_coord_t rect_y = lv_obj_get_y(obj);
        lv_coord_t radius = lv_obj_get_style_radius(obj, LV_PART_MAIN);
        radius = LV_MIN3(radius, rect_w / 2, rect_h / 2);

        lv_area_t main_area = {.x1 = rect_x,
                               .y1 = rect_y,
                               .x2 = rect_x + rect_w,
                               .y2 = rect_y + rect_h
                              };

        lv_draw_rect_dsc_t bg_dsc;
        lv_draw_rect_dsc_init(&bg_dsc);
        bg_dsc.bg_color = lv_color_hex(0xffffff);
        bg_dsc.bg_opa = LV_OPA_COVER;
        bg_dsc.radius = radius;
        lv_draw_rect(draw_ctx, &bg_dsc, &main_area);

        lv_coord_t border_width = 14; // 边框宽度

        lv_draw_line_dsc_t bg_line_dsc;
        lv_draw_line_dsc_init(&bg_line_dsc);
        bg_line_dsc.color = lv_color_hex(0xe6e6e6);
        bg_line_dsc.width = border_width;
        bg_line_dsc.opa = LV_OPA_100;
        bg_line_dsc.round_start = false;
        bg_line_dsc.round_end = false;

        lv_draw_arc_dsc_t bg_arc_dsc;
        lv_draw_arc_dsc_init(&bg_arc_dsc);
        bg_arc_dsc.color = lv_color_hex(0xe6e6e6);
        bg_arc_dsc.width = border_width;
        bg_arc_dsc.opa = LV_OPA_100;
        bg_arc_dsc.rounded = false;

        draw_rounded_rect_progress(draw_ctx, &main_area, radius, &bg_line_dsc, &bg_arc_dsc, 1.0f);

        if(progress > 0.0f) {
            lv_draw_line_dsc_t line_dsc;
            lv_draw_line_dsc_init(&line_dsc);
            line_dsc.color = lv_color_hex(0x2196F3);
            line_dsc.width = border_width;
            line_dsc.opa = LV_OPA_COVER;
            line_dsc.round_start = false;
            line_dsc.round_end = false;

            lv_draw_arc_dsc_t arc_dsc;
            lv_draw_arc_dsc_init(&arc_dsc);
            arc_dsc.color = lv_color_hex(0x2196F3);
            arc_dsc.width = border_width;
            arc_dsc.opa = LV_OPA_COVER;
            arc_dsc.rounded = false;

            draw_rounded_rect_progress(draw_ctx, &main_area, radius, &line_dsc, &arc_dsc, progress);
        }
    }
}

  • 仿真
上一页
下拉框
下一页
Lottie动画