Flutter BottomAppBar with specific shape - flutter

Could you suggest my how to implement BottomAppBar with shape as you could see in picture bellow
I'm trying to wrap BottomAppBar with ClipRRect
return ClipRRect(
borderRadius: BorderRadius.vertical(
top: Radius.circular(40),
),
child: BottomAppBar(
key: widget.key,
shape: widget.notchedShape,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: items,
),
color: Colors.red, //widget.backgroundColor,
),
);
But result is not as I wish

You can use CustomPainter() and using that you can make your own design.
This is not perfect as you have shown by you but you can always tweak the setting on your own.
class MyCustomPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint paint_0 = new Paint()
..color = Colors.white
..style = PaintingStyle.fill;
Path path_0 = Path();
path_0.moveTo(size.width * 0.0500000, size.height * 0.9000000);
path_0.cubicTo(
size.width * 0.5000000,
size.height * 0.8400000,
size.width * 0.4975000,
size.height * 0.8380000,
size.width * 0.9500000,
size.height * 0.9000000);
path_0.quadraticBezierTo(
size.width * 1, size.height * 0.9, size.width, size.height);
path_0.lineTo(0, size.height);
path_0.quadraticBezierTo(size.width * 0, size.height * 0.90,
size.width * 0.0500000, size.height * 0.9000000);
path_0.close();
canvas.drawPath(path_0, paint_0);
canvas.drawShadow(path_0, Color(0x68FFFFFF), 8, true);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
Output

Related

Clip Container inside CustomPainter

i made this shape using CustumPainter Class , i want the container color to fill only the shape , like a full charged battery
this is how i made the shape
void paint(Canvas canvas, Size size) {
var paint = Paint();
var path = Path();
paint.color = Colors.black;
paint.style = PaintingStyle.stroke;
paint.strokeWidth = 4.0;
var posX;
var posY;
path.lineTo(size.width*0.75, 0);
path.lineTo(size.width*0.75, size.height*0.25);
path.lineTo(size.width*0.75, size.height);
path.lineTo(0, size.height);
path.lineTo(0, 0);
path.moveTo(size.width*0.75, size.height*0.25);
path.lineTo(size.width*0.80, size.height*0.25);
path.lineTo(size.width*0.80, size.height*0.75);
path.lineTo(size.width*0.75, size.height*0.75);
canvas.drawPath(path, paint);
}
and this is my widget
return ClipRRect(
child: Container(
width: 100,
color: Colors.red,
height: 50,
child: CustomPaint(
child: Container(
),
painter: BatteryPainter(),
),
),
);
Create another Path/rect inside Painter to handle fill color property , Also include Paint()..strokeCap = StrokeCap.round for better look on outer side.
, pass the value to control fill color.
class BatteryPainter extends CustomPainter {
final Color fillColor;
final double value;
BatteryPainter({
required this.value,
this.fillColor = Colors.red,
});
#override
void paint(Canvas canvas, Size size) {
var paint = Paint()..strokeCap = StrokeCap.round;
var path = Path();
paint.color = Colors.black;
paint.style = PaintingStyle.stroke;
paint.strokeWidth = 4.0;
path.lineTo(size.width * 0.75, 0);
path.lineTo(size.width * 0.75, size.height * 0.25);
path.lineTo(size.width * 0.75, size.height);
path.lineTo(0, size.height);
path.lineTo(0, 0);
path.moveTo(size.width * 0.75, size.height * 0.25);
path.lineTo(size.width * 0.80, size.height * 0.25);
path.lineTo(size.width * 0.80, size.height * 0.75);
path.lineTo(size.width * 0.75, size.height * 0.75);
Rect rect = Rect.fromLTWH(0, 0, size.width * 0.75 * value, size.height);
canvas.drawPath(path, paint);
canvas.drawRect(
rect,
Paint()
..color = fillColor
..style = PaintingStyle.fill);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
Use
Container(
width: 100,
height: 50,
child: CustomPaint(
painter: BatteryPainter(value: value),
),
),
To get a custom shape you must be using clipPath instead of clip Rect
ClipPath(
clipper: CustomPath(),
child: Container(
width: double.infinity,
height: 500,
color: Colors.amberAccent,
),
),
More about clipPath

Flutter: How to make a Container shape with corner border

I have this piece of code.
Container(
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(18),
),
child: Center(
child: Text(
'Monday',
style: TextStyle(
color: Colors.white,
fontSize: 30,
),
),
),
);
That produces this
But I want something that looks like this.
By Knowing CustomPainter widget's paint
class MyCustomPainter extends CustomPainter {
final double padding;
final double frameSFactor;
MyCustomPainter({
required this.padding,
required this.frameSFactor,
});
#override
void paint(Canvas canvas, Size size) {
final frameHWidth = size.width * frameSFactor;
Paint paint = Paint()
..color = Colors.redAccent
..strokeCap = StrokeCap.round
..style = PaintingStyle.fill
..strokeWidth = 4;
/// background
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromLTRB(0, 0, size.width, size.height),
Radius.circular(18),
),
paint);
/// top left
canvas.drawLine(
Offset(0 + padding, padding),
Offset(
padding + frameHWidth,
padding,
),
paint..color = Colors.black,
);
canvas.drawLine(
Offset(0 + padding, padding),
Offset(
padding,
padding + frameHWidth,
),
paint..color = Colors.black,
);
/// top Right
canvas.drawLine(
Offset(size.width - padding, padding),
Offset(size.width - padding - frameHWidth, padding),
paint..color = Colors.black,
);
canvas.drawLine(
Offset(size.width - padding, padding),
Offset(size.width - padding, padding + frameHWidth),
paint..color = Colors.black,
);
/// Bottom Right
canvas.drawLine(
Offset(size.width - padding, size.height - padding),
Offset(size.width - padding - frameHWidth, size.height - padding),
paint..color = Colors.black,
);
canvas.drawLine(
Offset(size.width - padding, size.height - padding),
Offset(size.width - padding, size.height - padding - frameHWidth),
paint..color = Colors.black,
);
/// Bottom Left
canvas.drawLine(
Offset(0 + padding, size.height - padding),
Offset(0 + padding + frameHWidth, size.height - padding),
paint..color = Colors.black,
);
canvas.drawLine(
Offset(0 + padding, size.height - padding),
Offset(0 + padding, size.height - padding - frameHWidth),
paint..color = Colors.black,
);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true; //based on your use-cases
}
And use Like
SizedBox(
height: 200,
width: 200,
child: CustomPaint(
painter: MyCustomPainter(frameSFactor: .1, padding: 20),
child: Center(
child: Text(
'With Painter',
style: TextStyle(
color: Colors.black,
fontSize: 30,
),
),
),
),
),
Also using Container decoration
class CustomDecoration extends Decoration {
final Color? backgroundColor;
final double frameSFactor;
//defalut padding _Need to check
final double gap;
CustomDecoration({
this.backgroundColor = Colors.transparent,
required this.frameSFactor,
required this.gap,
});
#override
BoxPainter createBoxPainter([VoidCallback? onChanged]) {
return CustomDecorationPainter(
backgroundColor: backgroundColor!,
frameSFactor: frameSFactor,
padding: gap);
}
}
class CustomDecorationPainter extends BoxPainter {
final Color backgroundColor;
final double frameSFactor;
final double padding;
CustomDecorationPainter({
required this.backgroundColor,
required this.frameSFactor,
required this.padding,
});
#override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
print(configuration.size!.height);
final Rect bounds = offset & configuration.size!;
final frameHWidth = configuration.size!.width * frameSFactor;
Paint paint = Paint()
..color = backgroundColor
..strokeCap = StrokeCap.round
..style = PaintingStyle.fill
..strokeWidth = 4;
/// background
canvas.drawRRect(
RRect.fromRectAndRadius(
bounds,
Radius.circular(18),
),
paint..color = Colors.redAccent);
paint.color = Colors.black;
/// top left
canvas.drawLine(
bounds.topLeft + Offset(padding, padding),
Offset(bounds.topLeft.dx + frameHWidth, bounds.topLeft.dy) +
Offset(padding, padding),
paint,
);
canvas.drawLine(
bounds.topLeft + Offset(padding, padding),
Offset(bounds.topLeft.dx, bounds.topLeft.dy + frameHWidth) +
Offset(padding, padding),
paint,
);
//top Right
canvas.drawLine(
Offset(bounds.topRight.dx - padding, bounds.topRight.dy + padding),
Offset(bounds.topRight.dx - padding - frameHWidth,
bounds.topRight.dy + padding),
paint,
);
canvas.drawLine(
Offset(bounds.topRight.dx - padding, bounds.topRight.dy + padding),
Offset(bounds.topRight.dx - padding,
bounds.topRight.dy + padding + frameHWidth),
paint..color,
);
//bottom Right
canvas.drawLine(
Offset(bounds.bottomRight.dx - padding, bounds.bottomRight.dy - padding),
Offset(bounds.bottomRight.dx - padding,
bounds.bottomRight.dy - padding - frameHWidth),
paint,
);
canvas.drawLine(
Offset(bounds.bottomRight.dx - padding, bounds.bottomRight.dy - padding),
Offset(bounds.bottomRight.dx - padding - frameHWidth,
bounds.bottomRight.dy - padding),
paint,
);
//bottom Left
canvas.drawLine(
Offset(bounds.bottomLeft.dx + padding, bounds.bottomLeft.dy - padding),
Offset(bounds.bottomLeft.dx + padding,
bounds.bottomLeft.dy - padding - frameHWidth),
paint,
);
canvas.drawLine(
Offset(bounds.bottomLeft.dx + padding, bounds.bottomLeft.dy - padding),
Offset(bounds.bottomLeft.dx + padding + frameHWidth,
bounds.bottomLeft.dy - padding),
paint,
);
}
}
And use like
SizedBox(
width: 200,
height: 200,
child: Container(
alignment: Alignment.center,
decoration: CustomDecoration(
frameSFactor: .1,
gap: 20,
),
child: Text("With Decoration"),
),
),
you can add the button the way you like
You have to write a CustomPainter class to achieve this, luckily there's a site which generates code for a given svg or use Nested Stack with Container. This example gives the one which you expected.
CustomPainter class
class RPSCustomPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Path path_0 = Path();
path_0.moveTo(size.width * 0.1898734, 0);
path_0.lineTo(size.width * 0.06962025, 0);
path_0.cubicTo(size.width * 0.03117006, 0, 0, size.height * 0.03117006, 0,
size.height * 0.06962025);
path_0.lineTo(0, size.height * 0.1835443);
path_0.lineTo(size.width * 0.02531646, size.height * 0.1835443);
path_0.lineTo(size.width * 0.02531646, size.height * 0.06962025);
path_0.cubicTo(
size.width * 0.02531646,
size.height * 0.04515196,
size.width * 0.04515196,
size.height * 0.02531646,
size.width * 0.06962025,
size.height * 0.02531646);
path_0.lineTo(size.width * 0.1898734, size.height * 0.02531646);
path_0.lineTo(size.width * 0.1898734, 0);
path_0.close();
path_0.moveTo(size.width * 0.1898734, size.height * 0.9746835);
path_0.lineTo(size.width * 0.06962025, size.height * 0.9746835);
path_0.cubicTo(
size.width * 0.04515196,
size.height * 0.9746835,
size.width * 0.02531646,
size.height * 0.9548481,
size.width * 0.02531646,
size.height * 0.9303797);
path_0.lineTo(size.width * 0.02531646, size.height * 0.8164557);
path_0.lineTo(0, size.height * 0.8164557);
path_0.lineTo(0, size.height * 0.9303797);
path_0.cubicTo(0, size.height * 0.9688291, size.width * 0.03117006,
size.height, size.width * 0.06962025, size.height);
path_0.lineTo(size.width * 0.1898734, size.height);
path_0.lineTo(size.width * 0.1898734, size.height * 0.9746835);
path_0.close();
path_0.moveTo(size.width * 0.8227848, size.height);
path_0.lineTo(size.width * 0.8227848, size.height * 0.9746835);
path_0.lineTo(size.width * 0.9303797, size.height * 0.9746835);
path_0.cubicTo(
size.width * 0.9548481,
size.height * 0.9746835,
size.width * 0.9746835,
size.height * 0.9548481,
size.width * 0.9746835,
size.height * 0.9303797);
path_0.lineTo(size.width * 0.9746835, size.height * 0.8164557);
path_0.lineTo(size.width, size.height * 0.8164557);
path_0.lineTo(size.width, size.height * 0.9303797);
path_0.cubicTo(size.width, size.height * 0.9688291, size.width * 0.9688291,
size.height, size.width * 0.9303797, size.height);
path_0.lineTo(size.width * 0.8227848, size.height);
path_0.close();
path_0.moveTo(size.width * 0.8227848, size.height * 0.02531646);
path_0.lineTo(size.width * 0.8227848, 0);
path_0.lineTo(size.width * 0.9303797, 0);
path_0.cubicTo(size.width * 0.9688291, 0, size.width,
size.height * 0.03117006, size.width, size.height * 0.06962025);
path_0.lineTo(size.width, size.height * 0.1835443);
path_0.lineTo(size.width * 0.9746835, size.height * 0.1835443);
path_0.lineTo(size.width * 0.9746835, size.height * 0.06962025);
path_0.cubicTo(
size.width * 0.9746835,
size.height * 0.04515196,
size.width * 0.9548481,
size.height * 0.02531646,
size.width * 0.9303797,
size.height * 0.02531646);
path_0.lineTo(size.width * 0.8227848, size.height * 0.02531646);
path_0.close();
Paint paint_0_fill = Paint()..style = PaintingStyle.fill;
paint_0_fill.color = Color(0xff181717).withOpacity(1.0);
canvas.drawPath(path_0, paint_0_fill);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
and use it like so
Stack(
alignment: Alignment.bottomCenter,
children: [
Stack(
alignment: Alignment.center,
children: [
Container(
width: 200,
height: 200,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(18),
),
child: Center(
child: Text(
'Monday',
style: TextStyle(
color: Colors.white,
fontSize: 30,
),
),
),
),
Padding(
padding: EdgeInsets.all(24),
child: CustomPaint(
size: Size(180, 180),
painter: RPSCustomPainter(),
),
),
],
),
Padding(
padding: EdgeInsets.only(bottom: 24),
child: ClipRRect(
borderRadius: BorderRadius.circular(100),
child: Container(
padding: EdgeInsets.all(4),
color: Colors.black,
child: Icon(
Icons.close,
color: Colors.white,
size: 16,
),
),
),
),
],
),

Flutter How to create box container in price tag shape

How to create this corner-shaped card view in a flutter container..
You can archive this in several ways, using
Container Decoration
ClipPath
CustomPaint
Here is a demo of using CustomPaint, modify the value the way you like.
Result
Painter
class PriceTagPaint extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = Colors.green
..strokeCap = StrokeCap.round
..style = PaintingStyle.fill;
Path path = Path();
path
..moveTo(0, size.height * .5)
..lineTo(size.width * .13, 0)
..lineTo(size.width, 0)
..lineTo(size.width, size.height)
..lineTo(size.width * .13, size.height)
..lineTo(0, size.height * .5)
..close();
canvas.drawPath(path, paint);
//* Circle
canvas.drawCircle(
Offset(size.width * .13, size.height * .5),
size.height * .15,
paint..color = Colors.white,
);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
And use
SizedBox(
height: 100,
width: 300,
child: CustomPaint(
painter: PriceTagPaint(),
child: Center(
child: Text(
"Coolant",
style: TextStyle(
fontSize: 44,
),
),
),
),
);
Check on dartpad or on gist

Facing issue in making this in flutter

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

Make a half circle with ClipPath

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