How to create stacked wave containers - flutter

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.

Related

How to paint arc or moon shape over another circle in flutter

I really need your help to create or paint this kind of container in a flutter,
What I Want is below pic as a result
this is to show user profiles or different users inside this container like this, please help me out with how to do this I would really like you to appreciate your help, thanks in advance
What I did so far:
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
Color(0XFF8134AF),
Color(0XFFDD2A7B),
Color(0XFFFEDA77),
Color(0XFFF58529),
],
),
shape: BoxShape.circle),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
image: DecorationImage(
image: AssetImage(
IconAssets.user_icon,
),
fit: BoxFit.cover,
),
),
margin: EdgeInsets.all(AppMargin.m2),
padding: const EdgeInsets.all(AppPadding.p3),
),
),
Result:
please help me out how to create like above picture , thank you
I am using PathOperation.difference to paint the moon.
class MoonPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
final center = Offset(size.width / 2, size.height / 2);
final paint = Paint()
..shader = const LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
Color(0XFF8134AF),
Color(0XFFDD2A7B),
Color(0XFFFEDA77),
Color(0XFFF58529),
],
).createShader(Rect.fromLTRB(0, 0, size.width, size.height));
Path path1 = Path()
..addOval(Rect.fromCenter(
center: center, width: size.width, height: size.height));
Path path2 = Path()
..addOval(
Rect.fromCenter(
center: Offset(
center.dx - 10,
center.dy - 10,
),
width: size.width - 10,
height: size.height - 10,
),
);
canvas.drawPath(
Path.combine(PathOperation.difference, path1, path2),
paint,
);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return false;
}
}
SizedBox(
width: 300,
height: 300,
child: CustomPaint(
painter: MoonPainter(),
),
),
You can include another oval inside paint. Change the color and decorate the way you like
Is this what you want?
child: Container(
width: 400,
height: 400,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
Color(0XFF8134AF),
Color(0XFFDD2A7B),
Color(0XFFFEDA77),
Color(0XFFF58529),
],
),
shape: BoxShape.circle),
child: Align(
child: Container(
width: 350,
height: 350,
decoration: BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
),
),
),
),
This gives you a basic idea of how you can draw an arc using paint and place it over another widget.
https://dartpad.dev/?null_safety=true&id=0cc9f5ad27e13bc76b8cee125dabfd71

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(),
),
),

Invisible part of container

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

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),
),
),
)