进度条
进度条控件用于显示操作的进度。
属性
Property | Description |
---|---|
Range | 数值范围 |
Value | 当前值 |
Animation Enable | 是否启用动画,启用后数值变化时会有动画效果 |
Animation Time | 动画时长, 单位毫秒 |
Bar Mode | 进度条模式 |
进度条模式
- Normal:正常模式,普通进度条
- Symmetrical:对称模式,从零值到当前值绘制指示器。需要负的最小范围和正的最大范围
样式
Part | Description |
---|---|
Main | 主样式 |
Indicator | 指示器样式 |
控件支持的绑定属性
Property | Type | Description | Sync Mode |
---|---|---|---|
Value | int32_t | OneWayModelToView |
使用
不同模式下的进度条
- 控件属性
两个进度条的属性与基本进度条相同,只是 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, ¢er, 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, ¢er, 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, ¢er, 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, ¢er, 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);
}
}
}
- 仿真
