一個支持間隔俺陋,多色豁延,圓角,水平腊状,豎直的進(jìn)度條
特點
- 支持水平和豎直方向
- 支持進(jìn)度條間隔顏色
- 支持多色設(shè)置
- 支持起始圓角
使用方式
Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [10, 29, 18, 27, 16, 15, 24, 3, 20, 10].map<Widget>((i) {
return Padding(
padding: EdgeInsets.only(right: 10),
child: IntervalProgressBar(
direction: IntervalProgressDirection.vertical,
max: 30,
progress: i,
intervalSize: 2,
size: Size(12, 200),
highlightColor: Colors.red,
defaultColor: Colors.grey,
intervalColor: Colors.transparent,
intervalHighlightColor: Colors.transparent,
reverse: true,
radius: 0));
}).toList())
)
屬性
屬性 | 類型 | 說明 |
---|---|---|
direction | enum |
進(jìn)度條的方向诱咏,水平或豎直 |
max | int |
進(jìn)度塊的個數(shù) |
progress | int |
高亮進(jìn)度塊的個數(shù) |
intervalSize | int |
進(jìn)度塊之間間隔的大小。當(dāng)水平時缴挖,代表寬度袋狞;當(dāng)豎直時,代表高度 |
size | Size |
控件的尺寸 |
highlightColor | Color |
高亮進(jìn)度塊的顏色 |
defaultColor | Color |
進(jìn)度塊的默認(rèn)顏色 |
intervalColor | Color |
間隔塊的默認(rèn)顏色 |
intervalHighlightColor | Color |
高亮進(jìn)度塊之間的間隔塊的顏色 |
reverse | bool |
是否逆序填充 |
radius | int |
起始塊的圓角 |
? → https://github.com/stefanJi/IntervalProgressBar
實現(xiàn)
抽象基類
- 負(fù)責(zé)計算一些水平和豎直進(jìn)度條的公有屬性
- 調(diào)用子類的
paintBlock
執(zhí)行具體的draw
操作
abstract class IntervalProgressPainter extends CustomPainter {
final int max;
final int progress;
final int intervalSize;
final Color highlightColor;
final Color defaultColor;
final Color intervalColor;
final Color intervalHighlightColor;
final double radius;
final bool reverse;
final Paint _paint = Paint()
..style = PaintingStyle.fill
..isAntiAlias = true;
Rect bound;
IntervalProgressPainter(
this.max,
this.progress,
this.intervalSize,
this.highlightColor,
this.defaultColor,
this.intervalColor,
this.intervalHighlightColor,
this.radius,
this.reverse);
@override
@mustCallSuper
void paint(Canvas canvas, Size size) {
if (progress > max) {
throw Exception("progress must <= max");
}
bound = Offset.zero & size;
Size blockSize = calBlockSize();
for (int i = 0; i < max; i++) {
/// 調(diào)用子類執(zhí)行繪制
paintBlock(canvas, i, blockSize);
}
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
final old = oldDelegate as IntervalProgressPainter;
return old.max != max ||
old.progress != progress ||
old.intervalSize != intervalSize ||
old.intervalColor != intervalColor ||
old.defaultColor != defaultColor ||
old.highlightColor != highlightColor ||
old.intervalHighlightColor != intervalHighlightColor ||
old.radius != radius;
}
bool highlightBlock(int index) =>
reverse ? index >= (max - progress) : index < progress;
bool highlightInterval(int index) =>
reverse ? index >= (max - progress - 1) : index < progress - 1;
void paintBlock(Canvas canvas, int blockIndex, Size blockSize);
Size calBlockSize();
bool shouldDrawStartRadius(int index) => index == 0 && radius > 0;
bool shouldDrawEndRadius(int index) => index == max - 1 && radius > 0;
bool shouldDrawInterval(int index) =>
index != max - 1 &&
(intervalColor != IntervalProgressBar.TRANSPARENT ||
intervalHighlightColor != IntervalProgressBar.TRANSPARENT);
}
水平進(jìn)度條
- 計算每個進(jìn)度塊的尺寸
@override
Size calBlockSize() =>
Size(((bound.width - intervalSize * (max - 1)) / max), bound.height);
- 繪制每個塊
@override
void paintBlock(Canvas canvas, int i, Size blockSize) {
/// blockSize: calBlockSize 的返回值
/// i: 塊的索引
final blockWidth = blockSize.width;
final highlight = highlightBlock(i);
final dx = (blockWidth + intervalSize) * i;
Rect rect = Rect.fromLTRB(0, 0, blockWidth, bound.height);
_paint.color = highlight ? highlightColor : defaultColor;
canvas.save();
/// 畫布移動 dx: 進(jìn)度塊寬度+間隔塊寬度
canvas.translate(dx, 0);
/// 繪制起始圓角
if (shouldDrawStartRadius(i)) {
rect = _drawLeftRound(canvas, rect);
}
/// 繪制末尾圓角
if (shouldDrawEndRadius(i)) {
rect = _drawRightRound(canvas, rect);
}
/// 繪制塊
canvas.drawRect(rect, _paint);
/// 繪制間隔塊
if (shouldDrawInterval(i)) {
_paint.color =
highlightInterval(i) ? intervalHighlightColor : intervalColor;
canvas.drawRect(
Rect.fromLTRB(
blockWidth,
0,
blockWidth + intervalSize,
bound.height,
),
_paint);
}
canvas.restore();
}
- 繪制一邊帶圓角,另一半不帶圓角的矩形
void _drawRadius(Canvas canvas, Rect rect, Rect clipRect) {
final roundRect = RRect.fromLTRBR(
rect.left, rect.top, rect.right, rect.bottom, Radius.circular(radius));
final path = Path()..addRRect(roundRect);
canvas.save();
canvas.clipRect(clipRect, clipOp: ClipOp.difference);
canvas.drawPath(path, _paint);
canvas.restore();
}
}