Why is my setState not working in Flutter? - flutter
My first day learning flutter, can someone help me understand why my setState is not working?
Making a basic clock app.
The main part is the initState where I am trying to make it so that the Paint function which creates the clock UI is updated once every second so my second hand is updated in real-time.
import 'dart:math';
import 'package:flutter/material.dart';
class ClockView extends StatefulWidget{
#override
_ClockViewState createState() => _ClockViewState();
}
class _ClockViewState extends State<ClockView>{
#override void initState() {
Timer.periodic(Duration(seconds: 1), (timer) {setState(() {
});});
super.initState();
}
#override
Widget build(BuildContext context){
return Container(
width: 300,
height: 300,
child: Transform.rotate(
angle: -pi/2,
child: CustomPaint(
painter: ClockPainter(),
),
),
);
}
}
class ClockPainter extends CustomPainter{
#override
void paint(Canvas canvas, Size size) {
var CenterX = size.width/2;
var CenterY = size.height/2;
var CenterTrue = Offset(CenterX, CenterY);
var CRadius = min(CenterY, CenterY);
var SecHandBrush = Paint()..strokeCap = StrokeCap.round ..color = Colors.orange ..style = PaintingStyle.stroke ..strokeWidth = 4;
var MinHandBrush = Paint()..strokeCap = StrokeCap.round ..shader = RadialGradient(colors: [Colors.lightBlue, Colors.pink]).createShader(Rect.fromCircle(center: CenterTrue, radius: CRadius)) ..style = PaintingStyle.stroke ..strokeWidth = 8;
var HrHandBrush = Paint()..strokeCap = StrokeCap.round ..shader = RadialGradient(colors: [Colors.deepPurpleAccent, Colors.redAccent]).createShader(Rect.fromCircle(center: CenterTrue, radius: CRadius/2)) ..style = PaintingStyle.stroke ..strokeWidth = 10;
var FillBrush = Paint()..color = Color(0xFF444974);
var OutlineBrush = Paint()..color = Color(0xFFEAECFF) ..style = PaintingStyle.stroke ..strokeWidth = 5;
var CenterBrush = Paint()..color = Color(0xFFEAECFF);
canvas.drawCircle(CenterTrue, CRadius - 50, FillBrush);
canvas.drawCircle(CenterTrue, CRadius - 50.1, OutlineBrush);
var SecHandX = CenterX + 80 * cos(DateTime.now().second * 6 * pi/180);
var SecHandY = CenterX + 80 * sin(DateTime.now().second * 6 * pi/180);
canvas.drawLine(CenterTrue, Offset(SecHandX, SecHandY), SecHandBrush);
var MinHandX = CenterX + 75 * cos(DateTime.now().minute * 6 * pi/180);
var MinHandY = CenterX + 75 * sin(DateTime.now().minute * 6 * pi/180);
canvas.drawLine(CenterTrue, Offset(MinHandX,MinHandY), MinHandBrush);
var HrHandX = CenterX + 60 * cos((DateTime.now().hour * 30 + DateTime.now().minute * 0.5) * pi/180);
var HrHandY = CenterX + 60 * sin((DateTime.now().hour * 30 + DateTime.now().minute * 0.5) * pi/180);
canvas.drawLine(CenterTrue, Offset(HrHandX,HrHandY), HrHandBrush);
canvas.drawCircle(CenterTrue, 5, CenterBrush);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}```
Add a widgets binding observer to trigger timer after the initial state build is complete, I would rewrite it as:
import 'dart:math';
import 'package:flutter/material.dart';
class ClockView extends StatefulWidget{
#override
_ClockViewState createState() => _ClockViewState();
}
class _ClockViewState extends State<ClockView>{
void _startTimer(){
WidgetsBinding.instance.endOfFrame.then(
(_) {
if (mounted) {
// do some suff
Timer.periodic(Duration(seconds: 1), (timer) {setState(() {
});});
};
},
);
}
#override void initState() {
_startTimer();
super.initState();
}
#override
Widget build(BuildContext context){
return Container(
width: 300,
height: 300,
child: Transform.rotate(
angle: -pi/2,
child: CustomPaint(
painter: ClockPainter(),
),
),
);
}
}
class ClockPainter extends CustomPainter{
#override
void paint(Canvas canvas, Size size) {
var CenterX = size.width/2;
var CenterY = size.height/2;
var CenterTrue = Offset(CenterX, CenterY);
var CRadius = min(CenterY, CenterY);
var SecHandBrush = Paint()..strokeCap = StrokeCap.round ..color = Colors.orange ..style = PaintingStyle.stroke ..strokeWidth = 4;
var MinHandBrush = Paint()..strokeCap = StrokeCap.round ..shader = RadialGradient(colors: [Colors.lightBlue, Colors.pink]).createShader(Rect.fromCircle(center: CenterTrue, radius: CRadius)) ..style = PaintingStyle.stroke ..strokeWidth = 8;
var HrHandBrush = Paint()..strokeCap = StrokeCap.round ..shader = RadialGradient(colors: [Colors.deepPurpleAccent, Colors.redAccent]).createShader(Rect.fromCircle(center: CenterTrue, radius: CRadius/2)) ..style = PaintingStyle.stroke ..strokeWidth = 10;
var FillBrush = Paint()..color = Color(0xFF444974);
var OutlineBrush = Paint()..color = Color(0xFFEAECFF) ..style = PaintingStyle.stroke ..strokeWidth = 5;
var CenterBrush = Paint()..color = Color(0xFFEAECFF);
canvas.drawCircle(CenterTrue, CRadius - 50, FillBrush);
canvas.drawCircle(CenterTrue, CRadius - 50.1, OutlineBrush);
var SecHandX = CenterX + 80 * cos(DateTime.now().second * 6 * pi/180);
var SecHandY = CenterX + 80 * sin(DateTime.now().second * 6 * pi/180);
canvas.drawLine(CenterTrue, Offset(SecHandX, SecHandY), SecHandBrush);
var MinHandX = CenterX + 75 * cos(DateTime.now().minute * 6 * pi/180);
var MinHandY = CenterX + 75 * sin(DateTime.now().minute * 6 * pi/180);
canvas.drawLine(CenterTrue, Offset(MinHandX,MinHandY), MinHandBrush);
var HrHandX = CenterX + 60 * cos((DateTime.now().hour * 30 + DateTime.now().minute * 0.5) * pi/180);
var HrHandY = CenterX + 60 * sin((DateTime.now().hour * 30 + DateTime.now().minute * 0.5) * pi/180);
canvas.drawLine(CenterTrue, Offset(HrHandX,HrHandY), HrHandBrush);
canvas.drawCircle(CenterTrue, 5, CenterBrush);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}```
Note: This problem has been solved. It required a complete re-installation of the flutter package but the code as mentioned in the code works fine on its own without any modifications.
Related
How to round just one end of a line using CustomPainter in Flutter?
I can change both ends to square or rounded using the strokeCap property but can't figure out how to apply tailored settings for each end (ie one end rounded and one square). How can I achieve this effect? import 'package:flutter/material.dart'; class LinePainter extends CustomPainter { #override void paint(Canvas canvas, Size size) { var height = size.height; var width = size.width; var paint = Paint() ..color = Colors.red ..strokeWidth = 20 ..style = PaintingStyle.stroke ..strokeCap = StrokeCap.round; var path = Path(); path.moveTo(width * 0.25, height / 2); path.lineTo(width * 0.75, height / 2); canvas.drawPath(path, paint); } #override bool shouldRepaint(covariant CustomPainter oldDelegate) { return false; } } class Example extends StatefulWidget { const Example({Key? key}) : super(key: key); #override State<Example> createState() => _ExampleState(); } class _ExampleState extends State<Example> with SingleTickerProviderStateMixin { #override Widget build(BuildContext context) { return Scaffold( body: CustomPaint( painter: LinePainter(), child: Container(), ), ); } }
There is no existing PaintingStyle or StrokeCap option for setting only one cap, currently both caps are controlled the same. If you just want the rounded cap at one end, an alternative would be to draw the line with no caps, then draw a circle overlapping the end. This would only work for solid colors though. #override void paint(Canvas canvas, Size size) { var height = size.height; var width = size.width; var thickness = 20; var capRadius = thickness * 0.5 ; //Line paint, is set to stroke var linePaint = Paint() ..color = Colors.red ..strokeWidth = thickness ..style = PaintingStyle.stroke ..strokeCap = StrokeCap.butt; //butt is default, no caps //Cap paint, is set to fill by default var capPaint = Paint() ..color = Colors.red; //Draw line var path = Path(); path.moveTo(width * 0.25, height / 2); path.lineTo(width * 0.75, height / 2); canvas.drawPath(path, linePaint); //Draw cap canvas.drawCircle( Offset(width * 0.75, height / 2), capRadius, capPaint ); }
How To Make A Curved Chart with Custom Painter Which Include Custom Tool-tip with Moving Cursor?
I'm Learning Custom Paint and I'm Confused About Them i referred Few Documentation but Still i'm Lacking on it. Referrence:Curved Chart, Paths Some of the Code I have Mentioned Here ..Pls Help Me out of This.... import 'package:flutter/material.dart'; import 'dart:ui' as ui; class ChartPainter extends CustomPainter { final List<String> x; final List<double> y; final double min, max; ChartPainter(this.x, this.y, this.min, this.max); final yLabelStyle = const TextStyle(color: Colors.white, fontSize: 14); final xLabelStyle = const TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold); static double border = 10.0; static double radius = 5.0; final dotPaintFill = Paint() ..color = Colors.black ..style = PaintingStyle.fill ..strokeWidth = 2; final linePaint = Paint() ..color = Colors.white ..style = PaintingStyle.stroke ..strokeWidth = 2.0; #override void paint(Canvas canvas, Size size) { final clipRect = Rect.fromLTWH(0, 0, size.width, size.height); canvas.clipRect(clipRect); canvas.drawPaint(Paint()..color = Colors.black); final drawableHeight = size.height / 10.0 * border; final drawableWidth = size.width / 15 * border; final leftPadding = size.width / 6; final rightPadding = size.width / 1000; final hd = drawableHeight / 5.0; final wd = drawableWidth / x.length.toDouble(); final height = hd * 3.0; final width = drawableWidth; if (height <= 0.0 || width <= 0.00) return; if (max - min < 1.0e-6) return; final hr = height / (max - min); final left = border; final top = border; final c = Offset(left + wd / 2.0, top + height / 2.0); _drawOutline(canvas, c, wd, height); final points = _computePoints(c, wd, height, hr); final fillpath = _computePath( points, drawableHeight, width, true, leftPadding, rightPadding); final labels = _computeLabels(); canvas.drawPath(fillpath, linePaint); // drawvertical(canvas, c, wd, height, hr, wd); _drawDataPoints(canvas, points, dotPaintFill, linePaint); _drawYLabels(canvas, labels, points, wd, top); // final c1 = Offset(c.dx, top + 4 * hd); // _drawXLabels(canvas, c1, wd); } void _drawXLabels(Canvas canvas, Offset c, double wd) { x.forEach((xp) { drawTextCentered(canvas, c, xp, xLabelStyle, wd); c += Offset(wd, 0); }); } void _drawYLabels(Canvas canvas, List<String> labels, List<Offset> points, double wd, double top) { var i = 0; labels.forEach((label) { final dp = points[i]; final dy = (dp.dy - 15.0) < top ? 15.0 : -15.0; final ly = dp + Offset(0, dy); drawTextCentered(canvas, ly, label, yLabelStyle, wd); i++; }); } void _drawDataPoints( Canvas canvas, List<Offset> points, Paint dotPaintFill, Paint linePaint) { points.forEach((dp) { canvas.drawCircle(dp, radius, dotPaintFill); canvas.drawCircle(dp, radius, linePaint); }); } Path _computePath(List<Offset> points, double h, double w, bool cp, double leftPadding, double rightPadding) { Path path = Path(); for (var i = 0; i < points.length; i++) { final p = points[i]; if (i == 0) { path.moveTo(p.dx, p.dy); path.lineTo(p.dx, p.dy); } else { path.lineTo(p.dx, p.dy); } } return path; } List<Offset> _computePoints( Offset c, double width, double height, double hr) { List<Offset> points = []; y.forEach((yp) { final yy = height - (yp - min) * hr; final dp = Offset(c.dx, c.dy - height / 2.0 + yy); points.add(dp); c += Offset(width, 0); }); return points; } #override bool shouldRepaint(covariant CustomPainter oldDelegate) { return true; } final Paint outlinePaint = Paint() ..strokeWidth = 1.0 ..style = PaintingStyle.stroke ..color = Colors.white; void _drawOutline(Canvas canvas, Offset c, double width, double height) { y.forEach((p) { final rect = Rect.fromCenter(center: c, width: width, height: height); canvas.drawRect(rect, outlinePaint); c += Offset(width, 0); }); } List<String> _computeLabels() { return y.map((yp) => yp.toStringAsFixed(1)).toList(); } TextPainter measureText( String s, TextStyle style, double maxwidth, TextAlign align) { final span = TextSpan(text: s, style: style); final tp = TextPainter( text: span, textAlign: align, textDirection: TextDirection.ltr); tp.layout(minWidth: 0, maxWidth: maxwidth); return tp; } Size drawTextCentered( Canvas canvas, Offset c, String text, TextStyle style, double maxwidth) { final tp = measureText(text, style, maxwidth, TextAlign.center); final offset = c + Offset(-tp.width / 2.0, -tp.height / 2.0); tp.paint(canvas, offset); return tp.size; } } In cubicTO() Method we assign 3 points one for control points to draw a curve . and One for Starting point and another for end point I'm confused about points and math
I try to make custom progress indicator with Custom painter but painter is not updating the value
I try to make custom progress indicator with Custom painter but painter is not updating the value help: can you help me to use custom painter? also can we change circle pointer to square box with arrow pointing to progress class MyCsPaint extends CustomPainter { MyCsPaint({required this.progress}); final double progress; #override void paint(Canvas canvas, Size size) { Paint paintBg = Paint() ..color = Colors.teal.shade100 ..strokeWidth = 1 ..strokeCap = StrokeCap.round; Paint paint = Paint() ..color = Colors.teal ..strokeWidth = 5 ..strokeCap = StrokeCap.round; Offset p1bg = Offset(size.width, size.height); Offset p2bg = Offset(0, size.height); Offset p2 = Offset(0, size.height); Offset p1 = Offset(size.width * progress, size.height); canvas.drawLine(p1bg, p2bg, paintBg); canvas.drawLine(p1, p2, paint); Offset pc = Offset(size.width * progress, size.height * .7); canvas.drawCircle(pc, 10, paint); final textStyle = ui.TextStyle( color: Colors.black, fontSize: 16, ); final paragraphStyle = ui.ParagraphStyle( textDirection: TextDirection.ltr, ); final paragraphBuilder = ui.ParagraphBuilder(paragraphStyle) ..pushStyle(textStyle) ..addText('${progress * 100} %'); final constraints = ui.ParagraphConstraints(width: size.width); final paragraph = paragraphBuilder.build(); paragraph.layout(constraints); canvas.drawParagraph(paragraph, pc); } #override bool shouldRepaint(covariant CustomPainter oldDelegate) { return true; } }
Flutter - how do I rotate an object on a CustomPainter canvas?
How do you rotate an object drawn on a canvas in Flutter (not the whole canvas, just the object)? The following does not work. Error is: This expression has a type of 'void' so its value can't be used. Transform.rotate( angle: pi, child: canvas.drawPath( getTrianglePath(Offset(secondhandX, secondhandY)), secondhandBrush)); Here is the full code: // imports omitted class TimerDialPainter extends CustomPainter { Path getTrianglePath(Offset position) { return Path() ..moveTo(position.dx - 20, position.dy - 20) ..lineTo(position.dx + 40, position.dy + 40) ..lineTo(position.dx - 20, position.dy + 40) ..lineTo(position.dx - 20, position.dy - 20); } #override void paint(Canvas canvas, Size size) { int centerX = size.width / 2; int centerY = size.height / 2; int secondsArc = 60; Paint countBrush = Paint() ..color = (Colors.red) ..style = PaintingStyle.fill ..strokeWidth = 3; var secondhandX = centerX + 80 * cos(secondsArc * pi / 180); var secondhandY = centerY + 80 * sin(secondsArc * pi / 180); Transform.rotate( angle: pi/3, child: canvas.drawPath( getTrianglePath(Offset(secondhandX, secondhandY)), countBrush)); } //I feel this is not a right place to solve this?? } #override bool shouldRepaint(covariant CustomPainter oldDelegate) { return true; } }
Try rotating the canvas and paint it. Then rotate it back to previous value #override void paint(Canvas canvas, Size size) { double centerX = size.width / 2; double centerY = size.height / 2; int secondsArc = 60; Paint countBrush = Paint() ..color = (Colors.red) ..style = PaintingStyle.fill ..strokeWidth = 3; num secondhandX = centerX + 80 * cos(secondsArc * pi / 180); num secondhandY = centerY + 80 * sin(secondsArc * pi / 180); canvas.rotate(40); canvas.drawPath( getTrianglePath(Offset(secondhandX.toDouble(), secondhandY.toDouble())), countBrush); canvas.rotate(0); }
How to Insert/draw Image/text inside canvas circle in flutter
I want to draw/insert image and text inside canvas circle but I am unable to do that. I am posting screenshot for better understanding of my requirements Image Code void paint(Canvas canvas, Size size) { Size size = MediaQuery.of(buildContext).size; double strokeWidth = 10; Rect myRect = Offset(-size.width * 0.21, -40) & Size(size.width * 0.195, size.width * 0.195); var paint1 = Paint() ..color = Color(0xFF23BBFF) ..strokeWidth = strokeWidth ..style = PaintingStyle.stroke; var paint2 = Paint() ..color = Color(0xFFFF8623) ..strokeWidth = strokeWidth ..style = PaintingStyle.stroke; double firstLineRadianStart = 0; double _unAnswered = 0.30; double firstLineRadianEnd = (360 * _unAnswered) * pi / 180; canvas.drawArc( myRect, firstLineRadianStart, firstLineRadianEnd, false, paint1); double _learned = 1 - _unAnswered; double secondLineRadianEnd = getRadians(_learned); canvas.drawArc( myRect, firstLineRadianEnd, secondLineRadianEnd, false, paint2); } double getRadians(double value) { return (360 * value) * pi / 180; } #override bool shouldRepaint(CustomPainter oldDelegate) => true;