i am trying to make layout like this
i need the bottomRight corner at other side ..
i tried this but it does not work
Container(
width: 200
height: 200
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(bottomRight:
Radius.circular(40),),),
color: Colors.deepPurple[900]!,
),
),
does it possible in flutter frame work ?
You can follow this ClipPath
For left corner
class CustomCornerClipPath extends CustomClipper<Path> {
final double cornerR;
const CustomCornerClipPath({this.cornerR = 16.0});
#override
Path getClip(Size size) => Path()
..lineTo(size.width, 0)
..lineTo(
size.width,
size.height - cornerR,
)
..arcToPoint(
Offset(
size.width - cornerR,
size.height,
),
radius: Radius.circular(cornerR),
clockwise: false,
)
..lineTo(0, size.height);
#override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}
And use
ClipPath(
clipper: const CustomCornerClipPath(),
child: Container(
height: 100, //based on your need
width: 100,
color: Colors.cyanAccent,
),
),
For the right corner, path will be
#override
Path getClip(Size size) => Path()
..lineTo(size.width, 0)
..lineTo(size.width, size.height)
..lineTo(cornerR, size.height)
..arcToPoint(
Offset(
0,
size.height - cornerR,
),
radius: Radius.circular(cornerR),
clockwise: false,
);
I will recommend visiting cliprrect-clippath-in-flutter
Related
I'm trying to curve a container using this code:
class CurveClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
int curveHeight = 40;
Offset controlPoint = Offset(size.width / 2, size.height + curveHeight);
Offset endPoint = Offset(size.width, size.height - curveHeight);
Path path = Path()
..lineTo(0, size.height - curveHeight)
..quadraticBezierTo(controlPoint.dx, controlPoint.dy, endPoint.dx, endPoint.dy)
..lineTo(size.width, 0)
..close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
Usage:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// The title text which will be shown on the action bar
title: Text(title),
),
body: Container(
child: ClipPath(
clipper: CurveClipper(),
child: Container(
color: Colors.red,
height: 200.0,
),
),
),
);
}
However, this gets me this:
Screenshot
But I want the curve to be at the top of the container, not the bottom. How can I achieve this?
This one work for me
ClipPath File
Container(
margin: EdgeInsets.only(left: 15, right: 15),
alignment: Alignment.center,
child: ClipPath(
clipper: ClipPathClass(),
child: SizedBox(
width: 320,
height: 240,
child: Container(
color: Colors.red,
),
),
),
),
ClipPathClass File
class ClipPathClass extends CustomClipper<Path> {
#override
Path getClip(Size size) {
var path = Path();
path.moveTo(0.0, size.height - (size.height * 6 / 8));
var secondControlPoint = Offset(size.width / 2, 0);
var secondPoint = Offset(size.width, size.height - (size.height * 6 / 8));
path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
secondPoint.dx, secondPoint.dy);
path.lineTo(size.width, size.height);
path.lineTo(0, size.height);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => true;
}
I'm starting with Flutter and have to design a UI that looks like
But with icon button at the center of the Bezier curve.
What I tried is
class HeaderPainter extends CustomPainter {
HeaderPainter({
#required this.color,
#required this.avatarRadius
});
final Color color;
final double avatarRadius;
#override
void paint(Canvas canvas, Size size) {
final shapeBounds = Rect.fromLTRB(0, 0, size.width, size.height - avatarRadius);
final centerAvatar = Offset(shapeBounds.center.dx, shapeBounds.bottom);
final avatarBounds = Rect.fromCircle(center: centerAvatar, radius: avatarRadius).inflate(3);
_drawBackground(canvas, shapeBounds, avatarBounds);
}
#override
bool shouldRepaint(HeaderPainter oldDelegate) {
return color != oldDelegate.color;
}
void _drawBackground(Canvas canvas, Rect shapeBounds, Rect avatarBounds) {
final paint = Paint()..color = color;
final backgroundPath = Path()
..moveTo(shapeBounds.left, shapeBounds.top)
..lineTo(shapeBounds.bottomLeft.dx, shapeBounds.bottomLeft.dy)
..arcTo(avatarBounds, -pi, pi, false)
..lineTo(shapeBounds.bottomRight.dx, shapeBounds.bottomRight.dy)
..lineTo(shapeBounds.topRight.dx, shapeBounds.topRight.dy)
..lineTo(0.0, shapeBounds.height - 100)
..quadraticBezierTo(
shapeBounds.width / 4, shapeBounds.height,
shapeBounds.width / 2, shapeBounds.height
)
..quadraticBezierTo(
shapeBounds.width - shapeBounds.width / 4, shapeBounds.height,
shapeBounds.width, shapeBounds.height - 100
)
..lineTo(shapeBounds.width, 0.0)
..close();
canvas.drawPath(backgroundPath, paint);
}
}
And the outcome is
How can I get the bezier curve with the rectangle?
Edit 2: The HeaderPainter is used like
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Container(
child: CustomPaint(
size: Size.fromHeight(400.0),
painter: HeaderPainter(
color: Colors.red,
avatarRadius: avatarRadius
),
),
),
Positioned(
left: 0,
right: 0,
bottom: titleBottomMargin,
child: Column(
children: <Widget>[
Text('Hello World', style: TextStyle(fontWeight: FontWeight.bold),),
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: CircleAvatar(
radius: avatarRadius,
backgroundColor: Colors.green,
child: IconButton(icon: Icon(Icons.message), onPressed: _onAddMessageButtonClick,),
),
)
],
);
}
Got it solved using ClipPath and CustomClipper.
The updated build() method is
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Container(
child: ClipPath(
clipper: HeaderClipper(avatarRadius: avatarRadius),
child: CustomPaint(
size: Size.fromHeight(400.0),
painter: HeaderPainter(
color: Colors.green,
avatarRadius: avatarRadius
),
),
),
),
...
and HeaderClipper
class HeaderClipper extends CustomClipper<Path> {
HeaderClipper({
#required this.avatarRadius
});
final avatarRadius;
#override
getClip(Size size) {
final path = Path()
..lineTo(0.0, size.height - 100)
..quadraticBezierTo(
size.width / 4, (size.height - avatarRadius),
size.width / 2, (size.height - avatarRadius)
)
..quadraticBezierTo(
size.width - (size.width / 4), (size.height - avatarRadius),
size.width, size.height - 100
)
..lineTo(size.width, 0.0)
..close();
return path;
}
#override
bool shouldReclip(CustomClipper oldClipper) {
return false;
}
}
The final output is
My current code :
Container(
height: 1 / 3 * deviceSize.height,
width: double.infinity,
child: Text(
'Add New Location',
style: TextStyle(color: Colors.black, fontSize: 20.0),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.elliptical(300, 100),
bottomRight: Radius.elliptical(300, 100)),
color: Color(0xFFFAD02E),
),
)
I am not getting desired results.... :/
You can Try ClipPath using custom clipper to make this desire UI in flutter. But Your Method can still work need some tweaking.
ClipPath(
clipper: ProfileClipper(),
child: Image(
height: 300.0,
width: double.infinity,
image: AssetImage('You can use image or your desire color use container'),
fit: BoxFit.cover,
),
),
import 'package:flutter/material.dart';
class ProfileClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
Path path = Path();
path.lineTo(0, 4 * size.height / 5);
Offset curvePoint = Offset(size.width / 2, size.height);
Offset endPoint = Offset(size.width, 4 * size.height / 5);
path.quadraticBezierTo(
curvePoint.dx,
curvePoint.dy,
endPoint.dx,
endPoint.dy,
);
path.lineTo(size.width, 0);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return false;
}
}
You can use ClipPath
Try this
ClipPath(
clipper: BottomClipper(),
child: Container(
height: 200,
color: Colors.yellow,
child: Center(child: Text("BottomClipper()")),
),
),
BottomClipper()
import 'package:flutter/material.dart';
class BottomClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
var path = Path();
path.lineTo(0, 0);
path.lineTo(0, size.height - 40);
path.quadraticBezierTo(
size.width / 4, size.height, size.width / 2, size.height);
path.quadraticBezierTo(
size.width - size.width / 4, size.height, size.width, size.height - 40);
path.lineTo(size.width, 0);
path.lineTo(0, 0);
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return true;
}
}
OUTPUT
I want to build this
I used a ClipPath like this:
ClipPath(
clipper: HeaderClipper(),
child: Image.asset(
"assets/images/stores/bg1.jpg",
fit: BoxFit.cover,
),
),
And this is my HeaderClipper class:
class HeaderClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
final path = Path();
final heightFactor = 5 / 8;
path.lineTo(0, size.height * heightFactor);
path.quadraticBezierTo(
50,
size.height,
size.width / 4,
size.height,
);
path.lineTo(size.width * (3 / 4), size.height);
path.quadraticBezierTo(
size.width - 50,
size.height,
size.width,
size.height * heightFactor,
);
path.lineTo(size.width, 0);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => true;
}
But I don't know why it doesn't look like the picture. Can you help me what parameters should I change or should I use another method instead of quadraticBezierTo?
You can simply achieve it using - ClipRRect
Code:
ClipRRect(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(140.0),
bottomRight: Radius.circular(140.0)),
child: Container(
child:
Image(image: NetworkImage('https://placeimg.com/640/480/people')),
),
)
I am trying to create a custom card in flutter that looks like this :
how can i achieve this in flutter ?
This is what i want to achieve:
You could use ClipPath for custom clipping your widget
ClipPath(clipper: _CustomClipper(), child: Container(width: 200.0, height: 100.0, color: Colors.grey,),)
(gray container just for example)
const double _topPadding = 20.0;
const double _arcRadius = 8.0;
class _CustomClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
double point = size.width / 3 * 2;
final path = Path()
..moveTo(0.0, _topPadding)
..lineTo(point, _topPadding)
..lineTo(point, _arcRadius)
..lineTo(point + _arcRadius, 0.0)
..lineTo(size.width - _arcRadius, 0.0)
..lineTo(size.width, _arcRadius)
..lineTo(size.width, size.height)
..lineTo(0.0, size.height)
..lineTo(0.0, _topPadding)
..addOval(Rect.fromLTRB(
point, 0.0, point + 2 * _arcRadius, 2 * _arcRadius))
..addOval(Rect.fromLTRB(
size.width - 2 * _arcRadius, 0.0, size.width, 2 * _arcRadius));
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
UPD - elevated solution
Material(
color: Colors.yellow,
clipBehavior: Clip.antiAlias,
shape: _CustomBorder(),
elevation: 16.0, child: Container(width: 200.0, height: 100.0, child: Stack(
children: <Widget>[
Positioned(child: FittedBox(fit: BoxFit.scaleDown, child: Text('and a text here too'),),left: 140.0, right: 4.0, top: 4.0,),
Positioned(child: Text('I want a text here', style: TextStyle(fontSize: 24.0),), top: 40.0, left: 4.0,)
],
),),)
...
class _CustomBorder extends BorderDirectional {
#override
Path getOuterPath(ui.Rect rect, {ui.TextDirection textDirection}) {
Size size = rect.size;
double point = size.width / 3 * 2;
final path = Path()
..moveTo(0.0, _topPadding)
..lineTo(point, _topPadding)
..lineTo(point, _arcRadius)
..lineTo(point + _arcRadius, 0.0)
..lineTo(size.width - _arcRadius, 0.0)
..lineTo(size.width, _arcRadius)
..lineTo(size.width, size.height)
..lineTo(0.0, size.height)
..lineTo(0.0, _topPadding)
..addOval(Rect.fromLTRB(
point, 0.0, point + 2 * _arcRadius, 2 * _arcRadius))
..addOval(Rect.fromLTRB(
size.width - 2 * _arcRadius, 0.0, size.width, 2 * _arcRadius));
path.close();
return path;
}
}
import 'package:getwidget/getwidget.dart';
GFCard(
boxFit: BoxFit.cover,
image: Image.asset('your asset image'),
title: GFListTile(
avatar: GFAvatar(
backgroundImage: AssetImage('your asset image'),
),
title: Text('Card Title'),
subTitle: Text('Card Sub Title'),
),
content: Text("Some quick example text to build on the card"),
buttonBar: GFButtonBar(
children: <Widget>[
GFButton(
onPressed: () {},
text: 'Buy',
),
GFButton(
onPressed: () {},
text: 'Cancel',
),
],
),
),
Read complete article for Flutter card - https://docs.getwidget.dev/gf-card/