Im trying to draw the ticket model using dart canvas.
But I just can't draw those semi-circles. path.arcToPoint seems not to work.
Try this demo:
import 'package:flutter/material.dart';
class Ticket extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.orange
..strokeWidth = 2
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round;
Path path = Path();
//top
path.moveTo(50, 0);
path.lineTo(50, 150);
path.arcToPoint(const Offset(70, 170), radius: const Radius.circular(20));
path.lineTo(300, 170);
path.arcToPoint(const Offset(320, 150), radius: const Radius.circular(20));
path.lineTo(320, 0);
//bottom
path.moveTo(70, 170);
path.lineTo(300, 190);
path.arcToPoint(const Offset(320, 210), radius: const Radius.circular(20), clockwise: false);
path.lineTo(310, 290);
path.arcToPoint(const Offset(290, 300), radius: const Radius.circular(20));
path.lineTo(60, 280);
path.arcToPoint(const Offset(40, 260), radius: const Radius.circular(20));
path.lineTo(50, 190);
path.arcToPoint(const Offset(70, 170), radius: const Radius.circular(20), clockwise: false);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(Ticket oldDelegate) => false;
#override
bool shouldRebuildSemantics(Ticket oldDelegate) => false;
}
use:
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: CustomPaint(
painter: Ticket(),
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
),
),
),
);
}
Related
I have a page on which the container is located, I need to make borders and a cutout for the buttons in this container. I want to do this using ClipPath when I added this widget, nothing has changed, there are no borders and there is no vyzer that I registered. Tell me why nothing is displayed, what is my mistake?
#override
Widget build(BuildContext context) {
return ClipPath(
clipper: CustomClipperArc(position: 150, holeRadius: 32),
child: Container(
decoration: const BoxDecoration(
color: constants.Colors.greyXDark,
),
padding: const EdgeInsets.only(top: 50),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
constants.Assets.likeBoarding,
height: 50,
),
],
),
],
),
),
);
}
CustomClipperArc
class CustomClipperArc extends CustomClipper<Path> {
CustomClipperArc({this.position, this.holeRadius = 16});
double? position;
final double holeRadius;
#override
Path getClip(Size size) {
final path = Path()
..moveTo(0, 0)
..lineTo(position! - holeRadius, 0.0)
..lineTo(size.width, 0.0)
..lineTo(size.width, size.height)
..lineTo(position!, size.height)
..arcToPoint(
Offset(position! - holeRadius, size.height),
clockwise: false,
radius: const Radius.circular(1),
);
path.lineTo(0.0, size.height);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper oldClipper) => oldClipper != this;
}
Here is your Clip Code... and also use Shape Maker to design such layout and you will get clip code
Your clip container with border
Padding(
padding: const EdgeInsets.all(8.0),
child: Stack(
children: <Widget>[
ClipPath(
clipper: CustomClipPathTopContainer(),
child: Container(
height: 400,
color: Colors.green,
),
),
CustomPaint(
painter: BorderPainter(),
child: Container(
height: 400,
),
),
],
),
),
Clipping Code of Container
import 'package:flutter/cupertino.dart';
class CustomClipPathTopContainer extends CustomClipper<Path> {
#override
Path getClip(Size size) {
double w = size.width;
double h = size.height;
Path path0 = Path();
path0.moveTo(0,size.height);
path0.lineTo(0,0);
path0.lineTo(size.width,0);
path0.lineTo(size.width,size.height);
path0.lineTo(size.width*0.3333333,size.height);
path0.lineTo(size.width*0.3014833,size.height*0.9182714);
path0.quadraticBezierTo(size.width*0.2795000,size.height*0.8617714,size.width*0.2488333,size.height*0.8552714);
path0.quadraticBezierTo(size.width*0.2145667,size.height*0.8643571,size.width*0.1948583,size.height*0.9179714);
path0.lineTo(size.width*0.1653417,size.height);
path0.lineTo(0,size.height);
path0.lineTo(0,size.height);
path0.lineTo(0,size.height);
path0.close();
return path0;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
Making Border Painting
class BorderPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 2
..color = Colors.pink;
Path path0 = Path();
path0.moveTo(0,size.height);
path0.lineTo(0,size.height*0.2114714);
path0.quadraticBezierTo(size.width*0.1255833,size.height*0.4277857,size.width*0.2698833,size.height*0.4275143);
path0.cubicTo(size.width*0.4168083,size.height*0.4270286,size.width*0.5467250,size.height*0.0190429,size.width*0.6867167,size.height*0.0189000);
path0.quadraticBezierTo(size.width*0.8293000,size.height*0.0211000,size.width,size.height*0.2121429);
path0.lineTo(size.width,size.height);
path0.lineTo(0,size.height);
path0.lineTo(0,size.height);
path0.lineTo(0,size.height*0.9994143);
path0.close();
canvas.drawPath(path0, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
I want to create a Container, which has a sharp triangle type figure or arrow on its edge, exactly like in the picture below. If there is a pre-defined widget for funtions like this, please do tell me.
You can use CustomPainter,try this
Container(
child:Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment:CrossAxisAlignment.end,
children:[
Container(
child:CustomPaint(
painter: TrianglePainter(
strokeColor: Colors.red,
strokeWidth: 10,
paintingStyle: PaintingStyle.fill,
),
child: Container(
height: 10,
width: 20,
),
)
),
Container(
color:Colors.red,
height:2,
width:100,
),
Container(
color:Colors.blue,
height:20,
width:100,
)
]
)
)
Triangle Painter Class:
class TrianglePainter extends CustomPainter {
final Color strokeColor;
final PaintingStyle paintingStyle;
final double strokeWidth;
TrianglePainter({this.strokeColor = Colors.black, this.strokeWidth = 3, this.paintingStyle = PaintingStyle.stroke});
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = strokeColor
..strokeWidth = strokeWidth
..style = paintingStyle;
canvas.drawPath(getTrianglePath(size.width, size.height), paint);
}
Path getTrianglePath(double x, double y) {
return Path()
..moveTo(0, y)
..lineTo(x / 2, 0)
..lineTo(x, y)
..lineTo(0, y);
}
#override
bool shouldRepaint(TrianglePainter oldDelegate) {
return oldDelegate.strokeColor != strokeColor ||
oldDelegate.paintingStyle != paintingStyle ||
oldDelegate.strokeWidth != strokeWidth;
}
}
I have to design screen like above image:
I want to draw white background portion in the above image. I have try by using custom paint with clip path but I can't achieve like the image.
Here is my code:
class CommomContainer extends CustomClipper<Path> {
CommomContainer({#required this.holeRadius});
final double holeRadius;
#override
Path getClip(Size size) {
final path = Path()
..moveTo(0, 0)
..lineTo(size.width / 2 - holeRadius - 10, 0.0)
..quadraticBezierTo(
size.width / 2 - holeRadius, 0.0, size.width / 2 - holeRadius, 10.0)
..arcToPoint(
Offset(size.width / 2 + holeRadius, 0.0),
clockwise: false,
radius: Radius.circular(2),
)
..lineTo(size.width, 0.0)
..lineTo(size.width, size.height);
path.lineTo(0.0, size.height);
path.close();
return path;
}
#override
bool shouldReclip(CommomContainer oldClipper) => true;
}
Any help is appreciated.
Here you can use Shape Maker and I used that too. You can change stroke style from PaintingStyle.stroke to PaintingStyle.fill to fill the desired color.
class MyCustomPainter extends CustomPainter{
#override
void paint(Canvas canvas, Size size) {
Paint paint_0 = new Paint()
..color = Color.fromARGB(255, 33, 150, 243)
..style = PaintingStyle.stroke
..strokeWidth = 1;
Path path_0 = Path();
path_0.moveTo(0,0);
path_0.lineTo(size.width,0);
path_0.lineTo(size.width,size.height);
path_0.lineTo(0,size.height);
path_0.lineTo(0,0);
path_0.close();
canvas.drawPath(path_0, paint_0);
Paint paint_1 = new Paint()
..color = Color.fromARGB(255, 33, 150, 243)
..style = PaintingStyle.stroke
..strokeWidth = 1;
Path path_1 = Path();
path_1.moveTo(size.width*0.3071375,size.height*0.3273600);
path_1.cubicTo(size.width*0.3067750,size.height*0.1999400,size.width*0.3815000,size.height*0.1964000,size.width*0.4125000,size.height*0.2000000);
path_1.cubicTo(size.width*0.4514375,size.height*0.3614200,size.width*0.5514000,size.height*0.3594200,size.width*0.5875000,size.height*0.2000000);
path_1.quadraticBezierTo(size.width*0.6656000,size.height*0.1954200,size.width*0.6943500,size.height*0.3273600);
path_1.quadraticBezierTo(size.width*0.6943500,size.height*0.6060200,size.width*0.6943500,size.height*0.6990200);
path_1.quadraticBezierTo(size.width*0.6943500,size.height*0.8229400,size.width*0.6169000,size.height*0.8229400);
path_1.quadraticBezierTo(size.width*0.4427250,size.height*0.8229400,size.width*0.3846250,size.height*0.8229400);
path_1.quadraticBezierTo(size.width*0.3049125,size.height*0.8229600,size.width*0.3071375,size.height*0.6990200);
path_1.quadraticBezierTo(size.width*0.3071375,size.height*0.6060200,size.width*0.3071375,size.height*0.3273600);
path_1.close();
canvas.drawPath(path_1, paint_1);
Paint paint_2 = new Paint()
..color = Color.fromARGB(255, 33, 150, 243)
..style = PaintingStyle.stroke
..strokeWidth = 1;
Path path_2 = Path();
path_2.moveTo(size.width*0.5000002,size.height*0.0804608);
path_2.cubicTo(size.width*0.5273750,size.height*0.0804200,size.width*0.5684875,size.height*0.1111200,size.width*0.5684620,size.height*0.1899997);
path_2.cubicTo(size.width*0.5684875,size.height*0.2338200,size.width*0.5479250,size.height*0.2995600,size.width*0.5000002,size.height*0.2995385);
path_2.cubicTo(size.width*0.4726125,size.height*0.2995600,size.width*0.4315250,size.height*0.2667000,size.width*0.4315384,size.height*0.1899997);
path_2.cubicTo(size.width*0.4315250,size.height*0.1462000,size.width*0.4520625,size.height*0.0804200,size.width*0.5000002,size.height*0.0804608);
path_2.close();
canvas.drawPath(path_2, paint_2);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
Try this, I have used stack and then I have put 2 concentric circle on top of rectangle.
Scaffold(
backgroundColor: Colors.yellow,
body: Center(
child: Stack(
alignment: Alignment.topCenter,
clipBehavior: Clip.none,
children: [
Card(
color: Colors.white,
child: Container(
height: 300,
width: 300,
),
),
Positioned(
top: -50,
child: Container(
height: 100,
width: 100,
// color: Colors.yellow,
decoration: BoxDecoration(
shape: BoxShape.circle, color: Colors.yellow),
),
),
Positioned(
top: -40,
child: Container(
height: 80,
width: 80,
// color: Colors.yellow,
decoration: BoxDecoration(
shape: BoxShape.circle, color: Colors.white),
),
)
],
),));
I have a custom button that I plan to reuse over and over again.
How can I put a CustomPainter into CustomButtom, with the condition that it also changes its internal state?
class CustomButton extends StatelessWidget {
CustomButton({this.icon, this.text, this.onPressed});
final Icon icon;
final Text text;
final Function onPressed;
#override
Widget build(BuildContext context) {
return RawMaterialButton(
onPressed: onPressed,
elevation: 2.0,
fillColor: Colors.lightGreenAccent,
child: SizedBox(
width: 90,
height: 90,
child: Column(
children: [
icon,
text,
Container(
height: 15,
width: 70,
decoration: new BoxDecoration(
color: Colors.red,
borderRadius: new BorderRadius.all(Radius.elliptical(45, 10)),
),
),
],
),
),
padding: EdgeInsets.all(5.0),
shape: CircleBorder(),
);
}
}
How can I implement a smile animation that should not be a rotation, but a transition from one state to another?
Smooth redrawing of the CustomPaint part when the button is pressed
class SmileyPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
final radius = 100.0;
final center = Offset(150, 120);
// Body
final paint = Paint()..color = Colors.yellow;
canvas.drawCircle(center, radius, paint);
// Eyes
canvas.drawOval(
Rect.fromCenter(
center: Offset(center.dx + radius / 3, center.dy - radius / 3),
width: 25,
height: 60),
Paint());
canvas.drawOval(
Rect.fromCenter(
center: Offset(center.dx - radius / 3, center.dy - radius / 3),
width: 25,
height: 60),
Paint());
final paintMouth = Paint()
..color = Colors.black
..style = PaintingStyle.stroke
..strokeWidth = 10;
Path path = Path();
path.moveTo(200, 150);
path.quadraticBezierTo(150, 200, 100, 150);
path.moveTo(200, 150);
path.quadraticBezierTo(150, 220, 100, 150);
canvas.drawPath(path, paintMouth);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
By using CustomPainter i have created a half circle.Now i have this widget tree:
return Scaffold(
body: Center(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
// card view
height: 100,
alignment: Alignment.center,
margin: EdgeInsets.only(
top: 20.0, bottom: 0.0, left: 50.0, right: 50.0),
decoration: BoxDecoration(
boxShadow: ([
BoxShadow(
color: color_transparent_black,
spreadRadius: 5,
blurRadius: 3.0,
offset: Offset(2, 3),
),
]),
borderRadius: BorderRadius.circular(14.0),
),),
MyArc(diameter: 200),
This is MyArc:
class MyArc extends StatelessWidget {
final double diameter;
const MyArc({Key key, this.diameter = 200}) : super(key: key);
#override
Widget build(BuildContext context) {
return CustomPaint(
painter: MyPainter(),
size: Size(diameter, diameter),
);
}
}
// This is the Painter class
class MyPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()..color = Colors.blue;
canvas.drawArc(
Rect.fromCenter(
center: Offset(size.height / 2, 0),
height: size.height,
width: size.width,
),
6.4,
2.9,
false,
paint,
);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
But i got this problem:
I don't want any space between gray and blue shape!!!
I finally figured it out...
import 'dart:math' as math;
//...
class MyPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint blue = Paint()..color = Colors.blue;
canvas.translate(0, -size.height / 2);
canvas.drawArc(
Offset.zero & size,
-math.pi,
-math.pi,
false,
blue,
);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
If you want to make your canvas fit nicely also you can make it rectangular like so...
CustomPaint(
painter: MyPainter(),
size: Size(diamieter, diameter / 2),
)
Then have you custom painter as...
class MyPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint blue = Paint()..color = Colors.blue;
Paint red = Paint()..color = Colors.red;
canvas.drawRect(Offset.zero & size, red);
canvas.translate(0, -size.height);
canvas.drawArc(
Offset.zero & Size(size.width, size.height * 2),
-math.pi,
-math.pi,
false,
blue,
);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
It'll fit snug this way...
try changing the spreadRadius to 3.0
Its possible that it's creating a boundary greater than the container's Blur Radius boundary.
BoxShadow(
color: color_transparent_black,
spreadRadius: 5,
blurRadius: 3.0,
offset: Offset(2, 3),
),