I'm trying to add border radius to my custom shaped widget using Custom Paint, but I don't know how to add rounded edges to the custom shape.
I achieved the shape, but not the rounded edges.
Below is the code for the custom paint. How can I add border radius to the edges.
``
class RPSCustomPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint paint0 = Paint()
..color = const Color.fromARGB(255, 33, 150, 243)
..style = PaintingStyle.stroke
..strokeWidth = 1.4900000095367432;
Path path0 = Path();
path0.moveTo(3.03, 197.85);
path0.quadraticBezierTo(0.87, 47.28, 1.9, 1.36);
path0.lineTo(207.0, 2.0);
path0.lineTo(170.24, 197.9);
path0.quadraticBezierTo(16.26, 197.13, 3.03, 197.85);
canvas.drawPath(path0, paint0);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
``
you can use drawRRect() to draw the border radius for corners of your shape.
canvas.drawRRect(RRect.fromRectAndRadius(Rect.fromLTWH(size.width / 2 - gap - smallMarkWidth - 15,gap * 8,gap + 70,gap * 5,),Radius.circular(15.0)),backgroundPaint);
Related
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 );
}
I am learning custom painter in Flutter to create my own pie chart. I draw a circle first and then draw an arc for each percentage in the list. The problem is that the arcs are in stacks. I want the arcs to draw next to the previous arc. How could I implement it? And also I want to appear their percentage in the center of each arc.
Following is my code and the screenshot of the pie chart I created:
import 'dart:math' as math;
import 'package:flutter/material.dart';
Color randomColor =
Color((math.Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0);
class PieChart extends CustomPainter {
List<int> percent = [50, 20, 30];
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = Colors.grey
..style = PaintingStyle.fill;
double radius = math.min(size.width / 2, size.height);
// center point of the size
Offset center = Offset(size.width / 2, size.height / 2);
// draw circle
canvas.drawCircle(center, radius, paint);
for (int i = 0; i < percent.length; i++) {
// set the angle of the arc
double arcAngle = 2 * math.pi * (percent[i] / 100);
// change random color
paint.color = randomColor =
Color((math.Random().nextDouble() * 0xFFFFFF).toInt())
.withOpacity(1.0);
// draw the arc
canvas.drawArc(Rect.fromCircle(center: center, radius: radius),
-math.pi / 2, arcAngle, true, paint);
}
}
#override
bool shouldRepaint(PieChart oldDelegate) => false;
#override
bool shouldRebuildSemantics(PieChart oldDelegate) => false;
}
Pie chart
I pin the picture of how it should looks like. I was trying ti use Cnavas, because as I inderstood such things can't be done by simple widget. So I have a question, how can I extract rectangle from this filled rectangle? I saw solution like this:
class TransparantRectanglePainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
final paint = Paint();
paint.color = Colors.blue;
canvas.drawPath(
Path.combine(
PathOperation.difference,
Path()
..addRRect(RRect.fromLTRBR(100, 100, 300, 300, Radius.elliptical(x: 10, y: 15))),
Path()
..addRect(Rect.fromLTRB(100, 100, 100, 100)
..close(),
),
paint,
);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
As for the fromLTRBR,
Construct a rounded rectangle from its left, top, right, and bottom edges,
and the same radius in each corner.
And fromLTRB
Construct a rectangle from its left, top, right, and bottom edges.
It is better to use size rather than hard coded value.
If you want round corner, use addRRect,
quadraticBezierTo or relativeQuadraticBezierTo etc.
class TransparentRectanglePainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
final paint = Paint();
paint.color = Colors.red;
final Path path1 = Path()
..addRRect(
RRect.fromLTRBR(
0, 0, size.width, size.height, const Radius.elliptical(10, 15)),
);
final Path path2 = Path()
..addRect(
Rect.fromLTRB(0, size.height / 2, size.width / 2, size.height),
);
canvas.drawPath(
Path.combine(PathOperation.difference, path1, path2),
paint,
);
}
#override
bool shouldRepaint(TransparentRectanglePainter oldDelegate) =>
this != oldDelegate;
}
Visit flutter.dev to learn more about CustomPaint widget.
I am trying to make a box like this. If I press on the "Product" button, then I need to show a box like this. But I cannot make it. I tried both clippath and custom paint. I can use visibility widget to show and hide – this is not problem. The problem is that I need to show a box like the picture I added here.
You can do that with CustomPainter. this is an example:
class LinePainter extends CustomPainter {
final double progress;
LinePainter({this.progress});
Paint _paint = Paint()
..color = Colors.black
..strokeWidth = 4.0
..style = PaintingStyle.stroke
..strokeJoin = StrokeJoin.round;
#override
void paint(Canvas canvas, Size size) {
var path = Path();
path.moveTo(0, size.height / 2);
path.lineTo(size.width * progress, size.height / 2);
canvas.drawPath(path, _paint);
}
#override
bool shouldRepaint(LinePainter oldDelegate) {
return oldDelegate.progress != progress;
}
}
for more information you can see this page.
Please tell me how can I create this Arc with Radius CustomPainter UI Component like this Mockup Design?
There must be a gap between Start & End angle.
Code:
class ArcPainter extends CustomPainter {
final double angle = 310.0;
double toAngle(double angle) => angle * pi / 180.0;
#override
void paint(Canvas canvas, Size size) {
final Offset center = Offset(size.width / 2.0, size.height / 2.0);
final double radius = size.width / 3.0;
Paint paint = Paint()
..strokeCap = StrokeCap.round
..strokeWidth = 8.0
..style = PaintingStyle.stroke
..color = Colors.pink;
canvas.drawArc(
Rect.fromCircle(center: center, radius: radius),
toAngle(110.0),
toAngle(angle),
true,
paint,
);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
Problem:
Here is the current output for my Arc with Radius. The problem is that borders are showing in the arc gap. I want to remove the border in the gap.
you can create drawPath instead of drawArc
#override
void paint(Canvas canvas, Size size) {
final center = size.center(Offset.zero);
final oval = Rect.fromCenter(
center: center,
width: size.width,
height: size.height,
);
var progressPath = _path(oval, 200);
var progressPaint = _paint(Color(0xFF8987F7));
var backgroundPath = _path(oval, 280);
var backgroundPaint = _paint(Color(0xFF3a329e));
canvas
..drawPath(backgroundPath, backgroundPaint)
..drawPath(progressPath, progressPaint);
}
Paint _paint(Color color) {
return Paint()
..strokeCap = StrokeCap.round
..strokeWidth = 15.0
..style = PaintingStyle.stroke
..color = color;
}
Path _path(Rect oval, double angle) {
return Path()
..addArc(
oval,
toAngle(130),
toAngle(angle),
);
}
You told it to close the gap using the center. You can tell it to not do so:
canvas.drawArc(
Rect.fromCircle(center: center, radius: radius),
toAngle(110.0),
toAngle(angle),
false, // this is called "useCenter" for a reason...
paint,
);