Invisible part of container - flutter

I try to make invisible part of container, a circle that is cut out of it.
That's my goal: https://www.autodraw.com/share/FU2LW3XS7H18
This is my container:
Container(
color: Colors.white,
height: size.height/2 - size.width/2,
width: size.width,
);
And the circle that I want to cut out:
child: GestureDetector(
child: Container(
child: Opacity(opacity: 1),
width: 50,
height: 50,
decoration: ShapeDecoration(
shape: new CircleBorder(
side: new BorderSide(
width: 10.0, color: Colors.black)))))
And this is what I tried but didn't work:
Container(
color: Colors.white,
height: size.height/2 - size.width/2,
width: size.width,
child: Opacity(opacity: 1, child: GestureDetector(
child: Container(
width: 50,
height: 50,
decoration: ShapeDecoration(
shape: new CircleBorder(
side: new BorderSide(
width: 10.0, color: Colors.black)))))),
);

You can use CustomClipper to achieve this look. fillType = PathFillType.evenOdd is required.
class InvertedClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
return Path()
..addRect(Rect.fromLTWH(0, 0, size.width, size.height))
..addOval(Rect.fromCircle(
center: Offset(size.width / 2, size.height / 2),
radius: 50))
..fillType = PathFillType.evenOdd;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
You will need to adjust values for your needs.
Please note that this will not work on web. This is a known bug reported here.
In the widget tree use ClipPath to use InvertedClipper. Here's implementation:
ClipPath(
clipper: InvertedClipper(),
child: Container(
color: Colors.red,
height: 200
),
),
Source: https://stackoverflow.com/a/49396544/7616528

Related

How to create a button like this in flutter?

I have wrote this much code. I am trying to use custom painter here to draw those lines. But I don't know how to fill cooler inside them. I am using row to divide these 3 sections. But I am not sure if this is the right way.
Container(
height: 10.0.h,
padding: EdgeInsets.only(left: 20),
color: Color.fromRGBO(211, 237, 241, 1),
child: Row(
children: [
Container(
width: 70.0.w,
child: Text(
"Create an Event",
textAlign: TextAlign.left,
style: TextStyle(fontSize: 22.0.sp),
),
),
Flexible(
child: Container(
width: double.infinity,
height: double.infinity,
color: Colors.blue,
child: CustomPaint(
painter: CurvedPainter(),
),
),
)
],
),
)
class CurvedPainter extends CustomPainter { #override void paint(Canvas canvas, Size size) {
print(size.width);
print(size.height);
var paint = Paint();
var path = Path();
paint.color = Colors.red;
paint.style = PaintingStyle.stroke;
paint.strokeWidth = 2.0;
path.arcToPoint(Offset(-20, size.height * 0.5),
radius: Radius.circular(100), clockwise: false);
path.arcToPoint(Offset(-30, size.height),
radius: Radius.circular(70), clockwise: true);
canvas.drawPath(path, paint); }
}
I have made this with custom painter you can edit the values to customize the shape
Add this as a body of your Widget
Container(
height: 50,
width: 250,
decoration: BoxDecoration(
color: Colors.blue.shade50,
borderRadius: BorderRadius.all(Radius.circular(20))),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(20)),
child: Row(
children: [
Expanded(
child: Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.fromLTRB(20, 0, 0, 0),
height: 50,
color: Colors.blue.shade50,
child: Text('Hello'),
),
),
Container(
width: 70,
height: 50,
child: Stack(
children: [
Container(
width: 70,
height: 50,
child: CustomPaint(
painter: buttonBackground(),
),
),
Align(
alignment: Alignment(.8,1),
child: IconButton(icon: Icon(Icons.arrow_forward_ios_rounded), onPressed: (){})),
],
),
),
],
),
),
),
And you can change the value and color of the button background in this class
class buttonBackground extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
var sw = size.width;
var sh = size.height;
var paint = Paint();
Path mainBackground = Path();
mainBackground.addRect(Rect.fromLTRB(0, 0, sw, sh));
paint.color = Colors.blue.shade50;
canvas.drawPath(mainBackground, paint);
Path greyWave = Path();
greyWave.lineTo(sw, 0);
greyWave.lineTo(sw, sh);
greyWave.cubicTo(sw * 0.15, sh, sw * 0.5, sh, sw * .6, sh * 0.5);
greyWave.cubicTo(sw * 0.92, sh * 01.2, 0, sh * 0.15, sh * .4, sh * 0);
greyWave.close();
paint.color = Colors.blue.shade200;
canvas.drawPath(greyWave, paint);
Path blueWave2 = Path();
greyWave.lineTo(sw, 0);
greyWave.lineTo(sw, sh);
greyWave.cubicTo(sw * 0.05, sh, sw * 0.3, sh, sw * .4, sh * 0.5);
greyWave.cubicTo(sw * 0.62, sh * 0.92, 0, sh * 0.15, sh * .3, sh * 0);
greyWave.close();
paint.color = Colors.blue.withOpacity(.3);
canvas.drawPath(greyWave, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return oldDelegate != this;
}
}
I don't have access right now in an IDE to write flutter code. But I guess you can use a GestureDetector where inside of it you can add the button functionality in the onTap argument and as a child you can use the Image that you have created and want to use for the button.
Something like this below:
GestureDetector(
onTap: () {print('put a method here that runs the code that you want to be executed on tap');},
child: Image(
image: AssetImage('path/to/your/img'),
fit: BoxFit.cover,
height: 30,
),
)

How to create stacked wave containers

I want to implement this screen with this waves and with the same curves , I'm trying to put multi containers in stack to get this shape but I can't , the top part of screen will be slider of images
and this is my code which I used to draw this screen
Scaffold(
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
gradient: LinearGradient(
end: Alignment.centerRight,
begin: Alignment.centerLeft,
colors: [
blueColor,
lightColor,
],
),
),
child: Stack(
alignment: Alignment.topCenter,
children: [
Container(
height: MediaQuery.of(context).size.height * .5,
decoration: BoxDecoration(),
child: Stack(
children: [
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * .5,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(100),
),
image: DecorationImage(
image: AssetImage('assets/images/bg.png'),
fit: BoxFit.cover)),
),
Positioned(
bottom: 0,
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * .08,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(150),
topLeft: Radius.circular(150),
),
gradient: LinearGradient(
end: Alignment.centerRight,
begin: Alignment.centerLeft,
colors: [
blueColor,
lightColor,
],
),
),
),
),
],
),
),
Positioned(
bottom: 0,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
end: Alignment.centerRight,
begin: Alignment.centerLeft,
colors: [
blueColor,
lightColor,
],
),
),
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * .5,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(120),
),
color: Colors.white),
),
),
),
],
),
),
);
but this is the result which I have and have no idea to complete it
So can anyone help me in my case please !
You can make this with a CustomPainter, here is how you could do it and how it looks.
class StackedWaves extends StatelessWidget {
const StackedWaves({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return CustomPaint(
size: Size(MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height),
painter: StackedWavesPainter(),
);
}
}
class StackedWavesPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..shader = LinearGradient(colors: [
Colors.green,
Colors.lightGreenAccent,
]).createShader(Offset.zero & size);
final double side = 80;
final double radius = 80;
final path = Path()
..moveTo(0, size.height / 2 + side)
..arcToPoint(Offset(side, size.height / 2),
radius: Radius.circular(radius))
..lineTo(size.width - side, size.height / 2)
..arcToPoint(Offset(size.width, size.height / 2 - side),
radius: Radius.circular(radius), clockwise: false)
..lineTo(size.width, size.height)
..lineTo(0, size.height)
..close();
canvas.save();
canvas.drawPath(path, paint);
canvas.restore();
canvas.save();
canvas.translate(0, 100);
canvas.drawPath(path, Paint()..color = Colors.white);
canvas.restore();
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
Of course you can play with the variables "side" and "radius" if you want, just make sure they do not have a difference greater than 20 or so, I've seen if you change it like that you might not get the result you want.

How to design tile like given image?

I'm trying to making tile like below image.
This is the piece of code that I have tried:
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
ListTile(
leading: Container(
alignment: Alignment.center,
height: MediaQuery.of(context).size.height/20,
width: MediaQuery.of(context).size.height/20,
decoration: BoxDecoration(
color: index.isEven?Colors.yellow:Colors.orange,
shape: BoxShape.circle,
image: snapshot.data.content[index].image != null? DecorationImage(
image: NetworkImage(snapshot.data.content[index].image.fileUrl),
fit: BoxFit.cover
):null
),
child: snapshot.data.content[index].image == null?
Icon(Icons.person):Container()
),
title:Text(
snapshot.data.content[index].name, style: TextStyle(
fontWeight: FontWeight.bold)
),
subtitle: Text(snapshot.data.content[index].phoneNumber),
trailing: Container(
alignment: Alignment.centerRight,
width: MediaQuery.of(context).size.width/5.5,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Image.asset('assets/icons/reminder.png',fit: BoxFit.cover,
),
Image.asset('assets/icons/calendar_soon.png',fit: BoxFit.cover,),
],
),
),
onTap: (){
//
},
),
Container(
alignment: Alignment.center,
height: MediaQuery.of(context).size.height/25,
width: MediaQuery.of(context).size.width/1.5,
decoration: BoxDecoration(
color: Colors.green[100],
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(10),
topLeft: Radius.circular(10),
bottomRight: Radius.circular(30),
)
),
child: Text("12 Mar, Marriage Anniversary",style:TextStyle(color: Colors.green)),
),
SizedBox(height:5),
Divider(height: 0.5,)
],
)
and What I have got from this code:
This is my attempt using a CustomPainter:
class CurvePainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
final radius = 16.0;
final tipHeight = size.height * 0.2;
final paint = Paint()..color = const Color(0xFFDEF8EB);
final path = Path()
..moveTo(0, tipHeight)
..lineTo(0, size.height - radius)
..quadraticBezierTo(0, size.height, radius, size.height)
..lineTo(size.width - radius, size.height)
..quadraticBezierTo(
size.width, size.height, size.width, size.height - radius)
..lineTo(size.width, tipHeight + radius)
..quadraticBezierTo(size.width, 0, size.width - radius, 0)
..quadraticBezierTo(size.width - radius, tipHeight,
size.width - (radius + 8.0), tipHeight)
..lineTo(radius, tipHeight)
..quadraticBezierTo(0, tipHeight, 0, tipHeight + radius);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
To implement it, you need to use the CustomPaint widget:
Container(
height: 50.0,
width: 300,
child: CustomPaint(
painter: CurvePainter(),
),
),

How to use a semi circle inside a container like in this image in flutter?

I'm trying to make semi circle like in image inside container i have tried a lot but couldn't figure out how to make this
Now let me explain what i have tried so far and how i got the result
I have tried using custompainter class but am getting result like this:
enum CircleAlignment {
topLeft,
topRight,
bottomLeft,
bottomRight,
}
class QuarterCirclePainter extends CustomPainter {
final CircleAlignment circleAlignment;
final Color color;
const QuarterCirclePainter({this.circleAlignment, this.color});
#override
void paint(Canvas canvas, Size size) {
final radius = math.min(size.height, size.width-80);
final offset = circleAlignment == CircleAlignment.topLeft
? Offset(.0, .0)
: circleAlignment == CircleAlignment.topRight
? Offset(size.width, 5)
: circleAlignment == CircleAlignment.bottomLeft
? Offset(.0, size.height+10)
: Offset(size.width, size.height);
canvas.drawCircle(offset, radius, Paint()..color = color);
}
#override
bool shouldRepaint(QuarterCirclePainter oldDelegate) {
return color == oldDelegate.color &&
circleAlignment == oldDelegate.circleAlignment;
}
}
But am getting result like this:
Anyone got idea how to do this?
Below is an example of a text being at the centre of a circle.
You can just replace the text with your image, can also choose where you would like to align the child in your case the image widget
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
width: 500,
height: 250,
color: Colors.pink,
child: Align(
alignment: Alignment.topRight,
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(90)),
border: Border.all(width: 3, color: Colors.green, style: BorderStyle.solid)),
child: Align(alignment: Alignment.center, child: Text('asdasd'))),
),
);
}
}
I have edited so that curve is only one side of the border now. on the top left as you expect
Edit:
Not ideal semi curve on top right, however close, I think you can play around with the radius values, and find what you want #M.Yogeshwaran
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
width: 500,
height:250,
color: Colors.pink,
child: Align(
alignment: Alignment.topRight,
child: RotatedBox(
quarterTurns: 1,
child: Container(
width: 115,
height: 125,
decoration: BoxDecoration(
color: Colors.orange,
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(60), bottomRight: Radius.circular(80), topRight: Radius.circular(60)),
border: Border.all(width: 3,color: Colors.green,style: BorderStyle.none)
),
child: Align(
alignment: Alignment.center,
child: Text('asdasd'))),
),
),
);
}
}
Before using this, make sure if you using a "Stack Widget"
Positioned(
top: -(displayWidth(context) * 0.085),
left: -(displayWidth(context) * 0.15),
child: Container(
height: displayWidth(context) * 0.5,
width: displayWidth(context) * 0.5,
decoration: BoxDecoration(
color: HexColor('a4d9e9'),
borderRadius: BorderRadius.all(Radius.circular(
displayWidth(context) * 0.5
))
),
),
),

How can I create a Half Circle without Spacing in Flutter [duplicate]

This question already has answers here:
Flutter how to draw semicircle (half circle)
(6 answers)
Closed 3 years ago.
I want to create a half Circle at the bottom. But theres some space which I cant delete.
// Flutter
Image:
#override
Path getClip(Size size) {
final Path path = new Path();
path.lineTo(0.0, size.height / 2);
path.lineTo(size.width, size.height / 2);
path.lineTo(size.width, 0);
return path;
}
why not going the easy way
something like this
Container(
height: 30,
width: 50,
color: Colors.transparent,
child: new Container(
decoration: new BoxDecoration(
color: Colors.black,
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(40.0),
topRight: const Radius.circular(40.0),
),
),
),
),
You can easily achieve this view using ArcView link. See attached image
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Row(
children: <Widget>[
Align(
alignment: Alignment.bottomCenter,
child: Arc(
arcType: ArcType.CONVEX,
edge: Edge.TOP,
height: 70.0,
clipShadows: [ClipShadow(color: Colors.black)],
child: new Container(
height: 70,
width: MediaQuery.of(context).size.width,
color: Colors.lime,
),
),
),
],
),
),
);
}
Or create a custom clipper
class CustomHalfCircleClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
final Path path = new Path();
path.lineTo(0.0, size.height / 2);
path.lineTo(size.width, size.height / 2);
path.lineTo(size.width, 0);
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return true;
}
}
Use Above class as shown below
new ClipPath(
clipper: new CustomHalfCircleClipper(),
child: new Container(
height: MediaQuery.of(context).size.width,
width: MediaQuery.of(context).size.width,
decoration: new BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(
MediaQuery.of(context).size.width / 2),
),
),
)