Can't recreate this floating widget - flutter

I'm currently blocked trying to create a widget (like a tooltip box) that is represented by the image below. I should probably be able to create it by relying on a Painter class, but i'm not familiar doing so...
https://pasteboard.co/IgccNxD.png
(it's small, yes, max height = ~35px)

The code ended being something like:
void paint(Canvas canvas, Size size) {
Paint p = Paint()
..color = Colors.red
..isAntiAlias = true
..style = PaintingStyle.fill;
Offset nw = Offset(0, 0);
Offset se = Offset(size.width, size.height * 0.8);
final Rect rect = Rect.fromPoints(nw, se);
final RRect r = RRect.fromRectAndRadius(rect, Radius.circular(10));
canvas.drawRRect(r, p);
Offset bottomPoint = Offset((size.width / 2), size.height);
Offset rightPoint = Offset((size.width / 2) * 0.80, size.height * 0.80);
Offset leftPoint = Offset((size.width / 2) * 1.20, size.height * 0.80);
var path1 = Path()
..moveTo(rightPoint.dx, rightPoint.dy)
..lineTo(bottomPoint.dx, bottomPoint.dy)
..lineTo(leftPoint.dx, leftPoint.dy)
..lineTo(rightPoint.dx, rightPoint.dy);
canvas.drawPath(path1, p);
}
For the text inside, I've stacked it above this painting.

Related

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;

flutter : how to flip this path clip Bezier

I have this shape
enter image description here
I want to flip it to be like this
enter image description here
this is the original code
class CustomMenuClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
Paint paint = Paint();
paint.color = Colors.white;
final width = size.width;
final height = size.height;
Path path = Path();
path.moveTo(0, 0);
path.quadraticBezierTo(0, 8, 10, 16);
path.quadraticBezierTo(width - 1, height / 2 - 20, width, height / 2);
path.quadraticBezierTo(width + 1, height / 2 + 20, 10, height - 16);
path.quadraticBezierTo(0, height - 8, 0, height);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return true;
}
}
this is the github repository
I don't mind if it comes to a half-circle.
I think is should be something like this:
Path getClip(Size size) {
Paint paint = Paint();
paint.color = Colors.white;
final width = size.width;
final height = size.height;
Path path = Path();
path.moveTo(width, 0);
path.quadraticBezierTo(16, 10, 8, 0);
path.quadraticBezierTo(height / 2, width, height / 2 - 20 ,width - 1);
path.quadraticBezierTo( height - 16, 10, height / 2 + 20, height - 16width + 1);
path.quadraticBezierTo(height, 0, height - 8, 0);
path.close();
return path;
}
I would not recommend this, since different devices might reproduce different behaviors. Maybe using size.width and size.height might be a better idea for responsiveness.

How to round Arc edges in flutter?

I need to create an arc chart as following:
Using canvas I've created this one:
My code:
class CustomChartPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Rect drawingRect = Rect.fromCircle(center: Offset(size.width / 2, size.height / 2), radius: size.width / 2);
final Paint paint2 = Paint();
paint2.color = const Color.fromRGBO(0, 0, 0, 0.04);
paint2.style = PaintingStyle.stroke;
paint2.strokeWidth = 50;
canvas.drawCircle(Offset(size.width / 2, size.height / 2), size.width / 2, paint2);
canvas.drawArc(drawingRect,
-pi / 2 + 0.35,
pi - 0.35,
false,
greenPaint);
canvas.drawArc(drawingRect,
pi / 2 + 0.35,
pi - 0.35,
false,
orangePaint);
}
}
How can I round edges of arcs as presented on the first picture?
As #pskink mentioned, the solution is to use Paint.strokeCap, more precisely: paint.strokeCap = StrokeCap.round

Flutter Custom paint cross with path but with gradient and rounded corners

I've just started getting to grips with Custom painter and I've created a basic cross but not sure how to make the corners rounded and make the colour a gradient?
It seems a gradient requires createShader which takes a rect but I don't have one since I used paths.
Also I'd like to round the corners of the cross a little but not sure how that is done. I thought about creating rectangles but it doesn't seem to be possible to create slanted rectangles either.
class CrossPainter extends CustomPainter {
CrossPainter({this.bodyColour, this.strokeColour, this.stroke});
final Color bodyColour;
final Color strokeColour;
final double stroke;
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint();
paint
..color = strokeColour
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round
..strokeWidth = stroke;
Paint paint1 = Paint();
paint1
..color = bodyColour
..style = PaintingStyle.fill
..strokeWidth = 0;
double width = size.width;
double height = size.height;
Path path = Path();
path.addPolygon([Offset.zero, Offset(width / 4, 0), Offset(width, height), Offset(width - (width / 4), height)], true);
Path path2 = Path();
path2.addPolygon(
[Offset(width, 0), Offset(width - (width / 4), 0), Offset(0, height), Offset(0 + (width / 4), height)], true);
canvas.drawPath(path, paint1);
canvas.drawPath(path2, paint1);
// canvas.drawPath(path, paint); //border
// canvas.drawPath(path2, paint); //border
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
I also have paint1 which adds a border but it doesn't look so good since each polygon is a separate object.
You can freely use Rect on the Shader to fill gradient on rounded polygon drawn on the canvas. On my approach, I used the size defined on the canvas as a base for the Rect.
Paint()
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round
..shader = gradient
.createShader(Rect.fromLTWH(0.0, 0.0, size.width, size.height))
..strokeWidth = 20,
You can then add this paint object to the canvas that you're rendering.
As for the gradient, you can define it however you like. But here's an example.
const Gradient gradient = SweepGradient(
startAngle: 1.25 * math.pi / 2,
endAngle: 5.5 * math.pi / 2,
tileMode: TileMode.repeated,
colors: <Color>[
Colors.blueAccent,
Colors.lightBlueAccent,
],
);