I wanted to create the curved container like widget in the picture below
I used the Custom clipper class and created a similar one which is shown below
Below is the WaveClipper class I used to create the curved widget
class WaveClipper extends CustomClipper<Path> {
#override
getClip(Size size) {
var path = new Path();
path.lineTo(0, size.height / 5.25);
var firstControlPoint = Offset(size.width / 120, size.height / 2);
var firstEndPoint = Offset(size.width / 1.5, size.height / 2.5 );
var thirdControlPoint = Offset(size.width/1.025, size.height / 2.8 );
var thirdEndPoint = Offset(size.width, size.height / 1.8 );
path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy, firstEndPoint.dx,
firstEndPoint.dy);
path.quadraticBezierTo(thirdControlPoint.dx, thirdControlPoint.dy, thirdEndPoint.dx,
thirdEndPoint.dy);
path.lineTo(size.width, size.height/3 );
path.lineTo(size.width, 0);
path.close();
return path;
}
#override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
return true;
}
}
Please help me to achieve the desired output !!!
By wrapping the ClipPath widget with the container you can create your design see below code.
Container(
decoration: BoxDecoration(
border: Border.all(width: 2, color: Colors.blue),
color: Colors.blue),
child: ClipPath(
child: Container(
height: 200,
width: 200,
color: Colors.white,
),
clipper: WaveClipper()),
),
Related
I want a bottom border in the above given way for an image
I have used ClipRRect for the same
ClipRRect(
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(50),
bottomRight: Radius.circular(50)),
// Image border
child: SizedBox.fromSize(
size: Size.fromRadius(48), // Image radius
child: Image.network(data['displayPic'],
fit: BoxFit.cover),
),
)),
You could create CustomClipper , I will share an example Code which will achieve the way you want to shape the image , you could change radius according to your need.
class ClipPathClass extends CustomClipper<Path> {
#override
Path getClip(Size size) {
double radius = 50;
var path = Path();
path.lineTo(0.0, size.height - 30);
var firstControlPoint = Offset(size.width / 4, size.height);
var firstPoint = Offset(size.width / 2, size.height);
path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
firstPoint.dx, firstPoint.dy);
var secondControlPoint = Offset(size.width - (size.width / 4), size.height);
var secondPoint = Offset(size.width, size.height - 30);
path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
secondPoint.dx, secondPoint.dy);
path.lineTo(size.width, 0.0);
path.lineTo(size.width - radius, 0);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
Now use this ClipPathClass like ,
ClipPath(
clipper: ClipPathClass(),
child: //Your Image Container here
)
This question already has an answer here:
How to draw custom shapes in flutter
(1 answer)
Closed last month.
I am wondering if is there any efficient way to create a custom shape like this, where I can change the color of each segment?
You can do this with CustomClipper like this:
class CustomDraw2 extends CustomClipper<Path> {
#override
Path getClip(Size size) {
var path = Path();
path.moveTo(0, 0);
path.cubicTo(
0, 0, size.height * 0.3, 0, size.height * 0.4, size.height * 0.4);
path.cubicTo(
size.height * 0.4,
size.height * 0.4,
size.height * 0.4,
size.height * 0.66,
size.height * 0.9,
size.height * 0.7,
);
path.cubicTo(
size.height * 0.9,
size.height * 0.7,
size.height * 1.4,
size.height * 0.7,
size.height * 1.5,
size.height,
);
path.lineTo(0, size.height);
path.lineTo(0, 0);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return false;
}
}
and use it like this:
Container(
clipBehavior: Clip.antiAlias,
margin: EdgeInsets.all(16),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)),
child: Stack(
children: [
Container(
height: 100,
width: double.infinity,
color: Colors.green,
),
SizedBox(
height: 100,
width: 300,
child: ClipPath(
clipper: CustomDraw2(),
child: Container(
color: Colors.blueAccent,
),
),
),
],
),
)
The best thing you can use is Flutter Shape Maker
Fun Fact: If you know some basics how to draw, it will be fun! It can generate the custom clipper code for you!
Shape Maker Official Website
Reference Video 1 (Basic and Old)
Reference Video 2
Reference Video 3
Been using for some production based application, and working very nicely
I want to design this appbar :
and my code in main.dart is :
#override
Widget build(BuildContext context) {
return Column(
children: [
ClipPath(
clipper: WaveClip(),
child: Container(
height: 200,
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFF7CB342), Color(0xFFDCEDC8)],
),
),
child: childWidget),
),
],
);
and the WaveClip is:
class WaveClip extends CustomClipper<Path> {
#override
Path getClip(Size size) {
var path = new Path();
path.lineTo(0, 0); //start path with this if you are making at bottom
path.lineTo(0, size.height); //start path with this if you are making at bottom
var controlpoint = Offset(size.width / 5 , size.height - 100);
var endpoint = Offset(size.width / 3 , size.height +50);
path.quadraticBezierTo(
controlpoint.dx, controlpoint.dy, endpoint.dx, endpoint.dy);
var controlpoint2 = Offset(size.width /2 , size.height +90 );
var endpoint2 = Offset(size.width /4 , size.height -50);
path.quadraticBezierTo(
controlpoint2.dx, controlpoint2.dy, endpoint2.dx, endpoint2.dy);
path.lineTo(size.width, size.height);
path.lineTo(size.width, 0.0);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
but i cant handle it and my code does not works true, how can I fix it?
Should i use path.cubicto to design it?
It's better to use custompainter instead of customclipper, and there is a website that automatically generates custompainter code base on your drawing
https://shapemaker.web.app
And this is the guide to use this auto shape maker:
https://youtu.be/AnKgtKxRLX4
I hope this help u to solve your problem
I would like to operate some perspective on a ClipPath overlay with Flutter.
I reproduced inverted Clip Oval from Flutter: inverted ClipOval which works fine.
Then i would like to operate a perspective on this overlay:
For now i use a Transform widget but the "grey background" gets also rotated.I would like the background to expand on all screen left.
I think i should rotate only in InvertedRectClipper but i can't find a way to do something similar as alignment: FractionalOffset.center which tell where is the origin to rotate on.
Anyone have a tips for this ?
Actual screenshot :
Background is not entirely grey
Full code to test :
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: SafeArea(
child: Stack(
children: <Widget>[
Container(
color: Colors.white,
),
Transform(
alignment: FractionalOffset.center,
transform: Matrix4.identity()
..setEntry(3, 2, 0.0005) // perspective
..rotateX(-0.9),
child: ClipPath(
clipper: InvertedRectClipper(),
child: Container(
color: Color.fromRGBO(0, 0, 0, 0.5),
),
),
)
],
),
),
));
}
class InvertedRectClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
return Path()
..addRect(Rect.fromCenter(
center: Offset(size.width / 2, size.height / 2),
width: size.width / 2,
height: size.height / 2))
..addRect(Rect.fromLTWH(0.0, 0.0, size.width, size.height))
..fillType = PathFillType.evenOdd;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => true;
}
The key is to only transform the path you need to transform, not the whole widget.
Here is a sample :
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: SafeArea(
child: Stack(
children: <Widget>[
Container(
color: Colors.blue,
),
ClipPath(
clipper: InvertedRectClipper(),
child: Container(
color: Colors.black.withOpacity(0.5),
),
)
],
),
),
));
}
class InvertedRectClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
// First rectangle, to be transformed
var path = Path()
..fillType = PathFillType.evenOdd
..addRect(Rect.fromCenter(
center: Offset(size.width / 2, size.height / 2),
width: size.width / 2,
height: size.height / 2));
// Transform matrix
final matrix = Matrix4.identity()
..setEntry(3, 2, 0.0005)
..rotateX(-0.9);
path = path.transform(matrix.storage);
// Outer rectangle, straight
path.addRect(Rect.fromLTWH(0.0, 0.0, size.width, size.height));
// Return path
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => true;
}
Here is the result
You'll 'just' have to adapt the transformation to your convenance.
** EDIT **
If you need the transformation to be centered relative to your rectangle, an easy way is to draw the rectangle centered on the origin, apply the transformation, then translate it to be centered to the screen :
Path getClip(Size size) {
// First rectangle, to be transformed, centered at the origin
var path = Path()
..fillType = PathFillType.evenOdd
..addRect(Rect.fromCenter(
center: Offset(0, 0),
width: size.width / 2,
height: size.height / 2));
// Rotation X
final matrix = Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateX(-0.9);
path = path.transform(matrix.storage);
// Translation to center back the rectangle
path = path.transform(Matrix4.translationValues(size.width / 2, size.height / 2, 0).storage);
// Outer rectangle, straight
path.addRect(Rect.fromLTWH(0.0, 0.0, size.width, size.height));
// Return path
return path;
}
for my Container borderRadius. I am currently using borderRadius: BorderRadius.all(Radius.circular(20)). I want instead of it taking out the inside I want a border that adds to the outside like a triangluar like shape thing instead of taking away a triangleish looking thing.
you can do this easily using a custom ClipperPath.
Define a custom ClipperPath as given below.
class CustomClipPath extends CustomClipper<Path> {
final radius = 10.0;
final arcHeight = 50.0;
#override
Path getClip(Size size) {
final path = Path();
path.lineTo(size.width, 0.0);
path.lineTo(size.width, size.height);
path.arcToPoint(Offset(size.width, size.height - arcHeight),
radius: Radius.circular(radius));
path.lineTo(size.width, size.height - arcHeight / 2);
path.lineTo(0, size.height - arcHeight / 2);
path.lineTo(0,size.height- arcHeight);
path.arcToPoint(Offset(0, size.height),
radius: Radius.circular(radius));
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
Then you can apply it to any container like shown below.
ClipPath(
child: Container(
width: MediaQuery.of(context).size.width,
height: 200,
alignment:Alignment.center,
color: Colors.blue,
),
clipper: CustomClipPath(),
)
I am sharing a live demo on the Dartpad, find it here.