flutter SDK提供的ProgressIndicator不支持圆角属性的设置,看起来不是很美观,系统自带的LinearProgressIndicator是这样的:
这样的进度条显然无法满足UI设计师的要求,既然系统提供的进度条不支持圆角和渐变,那我们只能通过自定义view来实现了。
先来看一下实现的效果:
flutter是如何自定义view的呢,
flutter提供两个类来实现自定义view
CustomPaint
:在绘制阶段提供一个 Canvas
画布CustomPainter
: 可以设置画笔的颜色、粗细、是否抗锯齿、笔触形状以及作画风格等下面就用这两个类的使用来实现一个渐变的圆角进度条
import 'package:flutter/material.dart';
class GradientLinearProgressBar extends StatelessWidget {
final double strokeWidth;//画笔的宽度,其实是进度条的高度
final bool strokeCapRound;//是否需要圆角
final double value;//进度值
final Color backgroundColor;//进度条背景色
final List colors;//渐变的颜色列表
GradientLinearProgressBar({
this.strokeWidth = 2.0,
@required this.colors,
this.value,
this.backgroundColor = const Color(0xFFEEEEEE),
this.strokeCapRound = false
});
@override
Widget build(BuildContext context) {
var _colors = colors;
if (_colors == null) {
Color color = Theme.of(context).accentColor;
_colors = [color, color];
}
return CustomPaint(
size: MediaQuery.of(context).size,
painter: _GradientLinearProgressPainter(
strokeWidth: strokeWidth,
strokeCapRound: strokeCapRound,
backgroundColor: backgroundColor,
value: value,
colors: _colors
),
);
}
}
class _GradientLinearProgressPainter extends CustomPainter{
final double strokeWidth;
final bool strokeCapRound;
final double value;
final Color backgroundColor;
final List colors;
final List stops;
final p = Paint();
_GradientLinearProgressPainter({
this.strokeWidth = 2.0,
@required this.colors,
this.value = 0.0,
this.backgroundColor = const Color(0xFFEEEEEE),
this.strokeCapRound = false,
this.stops
});
@override
void paint(Canvas canvas, Size size) {
p.strokeCap = strokeCapRound ? StrokeCap.round : StrokeCap.butt;
p.style = PaintingStyle.fill;
p.isAntiAlias = true;
p.strokeWidth = strokeWidth;
double _offset = strokeWidth / 2;//留一定的偏移量
var start = Offset(_offset, _offset);//画笔起点坐标
var end = Offset(size.width, _offset);//画笔终点坐标
if (backgroundColor != Colors.transparent) {
p.color = backgroundColor;
canvas.drawLine(start, end, p);
}
if (value > 0) {
var valueEnd = Offset(value * size.width + _offset, _offset);//计算进度的长度
Rect rect = Rect.fromPoints(start, valueEnd);
p.shader = LinearGradient(colors: colors, stops: stops).createShader(rect);
p.color = Colors.amber;
canvas.drawLine(start, valueEnd, p);
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
自定义view最主要的是继承CustomPainter,实现paint方法。
自定义组件完成以后,使用就很简单了,直接放到widget树中即可
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('圆角渐变进度条'),
),
body: Center(
child: Container(
width: 300,
height: 200,
child: GradientLinearProgressBar(
strokeCapRound: true,
strokeWidth: 10,
colors: [Color(0xfffff7d7), Colors.blueAccent],
backgroundColor: Colors.transparent,
value: progress / 100,
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => updateProgress(),
child: Icon(
Icons.add
),
),
);