CircularProgressIndicatorを使う場合、下の画像のように青い部分の角が丸くならない。
今のところ、角を丸くする方法はなさそうなので、CustomPaintを使ってカスタムウィジェットを作成します。
目次
CustomPaintを使った角丸のプログレスインジケータ
import 'package:flutter/material.dart';
import 'dart:math' as math;
// カスタムプログレスバー
class RoundedProgressBar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 300.0,
height: 300.0,
child: CustomPaint(
painter: RoundedProgressPainter(
valueColor: Colors.blue,
backgroundColor: Colors.grey[300]!,
strokeWidth: 30.0,
value: 0.7,
),
),
);
}
}
// カスタムペインター
class RoundedProgressPainter extends CustomPainter {
final Color valueColor; // 進捗の色
final Color backgroundColor; // 背景色
final double strokeWidth; // ストローク幅
final double value; // 進捗値 (0.0 - 1.0)
// コンストラクタ
RoundedProgressPainter({
required this.valueColor,
required this.backgroundColor,
required this.strokeWidth,
required this.value,
});
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = backgroundColor
..strokeWidth = strokeWidth
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
final center = Offset(size.width / 2, size.height / 2);
final radius = math.min(size.width, size.height) / 2 - strokeWidth / 2;
// 背景の円を描画
canvas.drawCircle(center, radius, paint);
// 進捗のアークを描画
paint.color = valueColor;
final progressStartAngle = -math.pi / 2;
final progressEndAngle = progressStartAngle + (math.pi * 2 * value);
canvas.drawArc(
Rect.fromCircle(center: center, radius: radius),
progressStartAngle,
progressEndAngle - progressStartAngle,
false,
paint,
);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
結果
Center(
child: RoundedProgressBar(),
)
いい感じに角丸になりました。
プログレスインジケータの中心にテキストを入れる
import 'package:flutter/material.dart';
import 'dart:math' as math;
class RoundedProgressBarWithText extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 300.0,
height: 300.0,
child: CustomPaint(
painter: RoundedProgressPainterWithText(
valueColor: Colors.blue,
backgroundColor: Colors.grey[300]!,
strokeWidth: 30.0,
value: 0.7,
text: '70', // 表示するテキスト
textStyle: TextStyle(
color: Colors.grey.shade800,
fontSize: 76.0,
fontWeight: FontWeight.bold
),
),
),
);
}
}
// テキストが付いたカスタムペインター
class RoundedProgressPainterWithText extends CustomPainter {
final Color valueColor; // 進捗の色
final Color backgroundColor; // 背景色
final double strokeWidth; // ストローク幅
final double value; // 進捗値 (0.0 - 1.0)
final String text; // 表示するテキスト
final TextStyle textStyle; // テキストのスタイル
// コンストラクタ
RoundedProgressPainterWithText({
required this.valueColor,
required this.backgroundColor,
required this.strokeWidth,
required this.value,
required this.text,
required this.textStyle,
});
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = backgroundColor
..strokeWidth = strokeWidth
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
final center = Offset(size.width / 2, size.height / 2);
final radius = math.min(size.width, size.height) / 2 - strokeWidth / 2;
// 背景の円を描画
canvas.drawCircle(center, radius, paint);
// 進捗のアークを描画
paint.color = valueColor;
final progressStartAngle = -math.pi / 2;
final progressEndAngle = progressStartAngle + (math.pi * 2 * value);
canvas.drawArc(
Rect.fromCircle(center: center, radius: radius),
progressStartAngle,
progressEndAngle - progressStartAngle,
false,
paint,
);
// テキストを描画
final textPainter = TextPainter(
text: TextSpan(
text: text,
style: textStyle,
),
textDirection: TextDirection.ltr,
);
textPainter.layout();
final textX = center.dx - textPainter.width / 2;
final textY = center.dy - textPainter.height / 2;
textPainter.paint(canvas, Offset(textX, textY));
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
結果
Center(
child: RoundedProgressBarWithText(),
)
プログレスインディケーターの中心にテキストを表示できました。
Comment