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),
),
),
)
Related
I was wondering how can I achieve something like this, this kind of shape?
Here:
class Draw extends StatelessWidget {
const Draw({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
width: 300,
height: 170,
child: Stack(
clipBehavior: Clip.none,
children: [
Center(
child: ClipPath(
clipper: MyClipper(),
child: Container(
width: 300,
height: 170,
color: Colors.black,
),
),
),
Positioned(
left: -20,
child: SizedBox(
height: 170,
child: Center(
child: Material(
elevation: 3,
color: Colors.black,
shadowColor: Colors.white,
borderRadius: BorderRadius.circular(10),
child: const SizedBox(width: 80, height: 80),
),
),
),
)
],
),
),
),
);
}
}
class MyClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
final p = Path();
double facotr = 30;
p.moveTo(10, 0);
p.lineTo(10, size.height - 20);
p.quadraticBezierTo(10, size.height, 20, size.height);
p.lineTo(size.width - facotr, size.height - facotr);
p.lineTo(size.width, size.height / 2);
p.lineTo(size.width - facotr, facotr);
p.lineTo(20, 0);
p.quadraticBezierTo(10, 0, 10, 10);
return p;
}
#override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => true;
}
There is the Paint widget, but also someone made a tool for that wich makes it convienent.
Shape Maker
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,
),
)
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(),
),
),
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
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
))
),
),
),