使用自定义笔划帽在 flutter 中创建自定义圆形进度指示器
Create custom circular progress indicator in flutter with custom stroke cap
我需要创建这个百分比指标
我怎样才能做到这一点?我在 Flutter 中尝试过 percent_indicator 包,但主要问题是我们的 strokeCap 选项数量有限。我也试过用两条弧来做,但问题仍然存在。有没有办法创建自定义 strokeCap,或者没有 canvas.drawArc 的其他方法?
您可以使用 CustomPainter 实现此目的。以下是我的解决方案。
NOTE
You can pass in a dynamic value to update the progress bar's value. I have not done that since it should be trivial to implement once the rendering is correct ;). You might also update the colors to fit your need!
import 'package:flutter/material.dart';
import 'package:vector_math/vector_math.dart' as vmath;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: TestPage(),
);
}
}
class TestPage extends StatelessWidget {
const TestPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
width: 200,
height: 200,
child: CustomPaint(
painter: MyPainter(),
child: Container(),
),
),
),
);
}
}
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
// Get the center of the canvas
final center = Offset(size.width / 2, size.height / 2);
// Draw the gray background seen on the progress indicator
// This will act as the background layer.
canvas.drawCircle(
center,
85,
Paint()
..style = PaintingStyle.stroke
..color = Colors.black12
..strokeWidth = 30,
);
// Create a new layer where we will be painting the
// actual progress indicator
canvas.saveLayer(
Rect.fromCenter(center: center, width: 200, height: 200),
Paint(),
);
// Draw the light green portion of the progress indicator
canvas.drawArc(
Rect.fromCenter(center: center, width: 170, height: 170),
vmath.radians(0),
vmath.radians(200),
false,
Paint()
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round
..color = Colors.green[100]
..strokeWidth = 30,
);
// Draw the dark green portion of the progress indicator
// Basically, this covers the entire progress indicator circle.
// But because we have set the blending mode to srouce-in (BlendMode.srcIn),
// only the segment that is overlapping with the lighter portion will be visible.
canvas.drawArc(
Rect.fromCenter(center: center, width: 155, height: 155),
vmath.radians(0),
vmath.radians(360),
false,
Paint()
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round
..color = Colors.green
..strokeWidth = 15
..blendMode = BlendMode.srcIn,
);
// we fatten the layer
canvas.restore();
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
您应该得到如下所示的输出:
我需要创建这个百分比指标
我怎样才能做到这一点?我在 Flutter 中尝试过 percent_indicator 包,但主要问题是我们的 strokeCap 选项数量有限。我也试过用两条弧来做,但问题仍然存在。有没有办法创建自定义 strokeCap,或者没有 canvas.drawArc 的其他方法?
您可以使用 CustomPainter 实现此目的。以下是我的解决方案。
NOTE You can pass in a dynamic value to update the progress bar's value. I have not done that since it should be trivial to implement once the rendering is correct ;). You might also update the colors to fit your need!
import 'package:flutter/material.dart';
import 'package:vector_math/vector_math.dart' as vmath;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: TestPage(),
);
}
}
class TestPage extends StatelessWidget {
const TestPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
width: 200,
height: 200,
child: CustomPaint(
painter: MyPainter(),
child: Container(),
),
),
),
);
}
}
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
// Get the center of the canvas
final center = Offset(size.width / 2, size.height / 2);
// Draw the gray background seen on the progress indicator
// This will act as the background layer.
canvas.drawCircle(
center,
85,
Paint()
..style = PaintingStyle.stroke
..color = Colors.black12
..strokeWidth = 30,
);
// Create a new layer where we will be painting the
// actual progress indicator
canvas.saveLayer(
Rect.fromCenter(center: center, width: 200, height: 200),
Paint(),
);
// Draw the light green portion of the progress indicator
canvas.drawArc(
Rect.fromCenter(center: center, width: 170, height: 170),
vmath.radians(0),
vmath.radians(200),
false,
Paint()
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round
..color = Colors.green[100]
..strokeWidth = 30,
);
// Draw the dark green portion of the progress indicator
// Basically, this covers the entire progress indicator circle.
// But because we have set the blending mode to srouce-in (BlendMode.srcIn),
// only the segment that is overlapping with the lighter portion will be visible.
canvas.drawArc(
Rect.fromCenter(center: center, width: 155, height: 155),
vmath.radians(0),
vmath.radians(360),
false,
Paint()
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round
..color = Colors.green
..strokeWidth = 15
..blendMode = BlendMode.srcIn,
);
// we fatten the layer
canvas.restore();
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
您应该得到如下所示的输出: