How to fit a GridView.Builder inside a ClipPath Container in Flutter - flutter

what I want to achieve is centring the whole grid view inside the blue background, and to be able to scroll it.
The screenshot only shows the container I'm editing and not the whole page.
Container>Stack
This is the list of services - an array with four elements. BaseScreen is just a ChangeNotifier from Provider.
class ServicesStateManager extends BaseScreenProvider {
final _servicesList = [
const Service(
serviceName: "serviceName1",
description:
"datadatadatadatadatadatadatadatadatadat adatadatadatadatadatadatadatadatadatadatadatadatadat adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadata",
image: "assets/images/favicon.png",
),
const Service(
serviceName: "serviceName2",
description:
"datadatadatadatadatadatadatadatadatadat adatadatadatadatadatadatadatadatadatadatadatadatadat adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadata",
image: "assets/images/favicon.png",
),
const Service(
serviceName: "serviceName3",
description:
"datadatadatadatadatadatadatadatadatadat adatadatadatadatadatadatadatadatadatadatadatadatadat adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadata",
image: "assets/images/favicon.png",
),
const Service(
serviceName: "serviceName4",
description:
"datadatadatadatadatadatadatadatadatadat adatadatadatadatadatadatadatadatadatadatadatadatadat adatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadatadata",
image: "assets/images/favicon.png",
),
];
List<Service> get getServicesList => _servicesList;
// TODO: add setter
}
This is the blue - Clipped Container and the Stack
ClipPath(
clipper: CustomBodyClipPath(),
child: Container(
color: samsBlue,
height: 1200,
width: double.infinity,
child: Stack(
fit: StackFit.expand,
children: [
BaseScreen<ServicesStateManager>(
builder: (context, model, child) => SizedBox(
height: 400,
child: GridView.builder(
physics: NeverScrollableScrollPhysics(),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 1.0,
mainAxisSpacing: 1.0,
),
primary: false,
shrinkWrap: true,
itemBuilder: (context, index) {
return ServicesTileWidget(
servicesList: model.getServicesList[index],
);
},
itemCount: model.getServicesList.length),
),
),
// Heading
Positioned(
top: 600,
left: largeSpace,
child: Padding(
padding: const EdgeInsets.all(defaultPadding),
child: Text(
"Our Services",
style: Theme.of(context)
.textTheme
.headline1!
.copyWith(color: samsBlack),
),
),
),
],
),
),
),
This is the Clipper - CustomBodyClipper
class CustomBodyClipPath extends CustomClipper<Path> {
#override
Path getClip(Size size) {
double w = size.width;
double h = size.height;
// Paint paint0 = Paint()
// ..color = const Color.fromARGB(255, 33, 150, 243)
// ..style = PaintingStyle.stroke
// ..strokeWidth = 1.0;
Path path = Path();
path.moveTo(0, size.height * 0.55);
path.quadraticBezierTo(size.width * 0.25, size.height * 0.3,
size.width * 0.6, size.height * 0.6);
path.quadraticBezierTo(size.width * 0.85, size.height * 0.8,
size.width * 1.0, size.height * 0.6);
path.lineTo(size.width, size.height);
path.lineTo(0, size.height);
return path;
}
#override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
return false;
}
}

Related

Flutter border around container with text in the middle (divider?)

I try to create a border around a container, that is not that difficult ofcourse, but i need also a text IN the border with space around it. Like horizontal divder but i need a complete border.
Attached what i like to achieve.
Any one who can help me how to approach this?
Thanks!
Tried to use the horizontal and vertical divider packages, but then the border is not in full.
You can use CustomPainter like this:
class CustomDraw extends CustomPainter {
late Paint painter;
late double radius;
late double textWidth;
CustomDraw(Color color, this.textWidth, {this.radius = 0}) {
painter = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 2
..color = color;
}
#override
void paint(Canvas canvas, Size size) {
var path = Path();
path.moveTo(size.width - ((size.width - textWidth) / 2), 0);
path.lineTo(size.width - radius, 0);
path.cubicTo(size.width - radius, 0, size.width, 0, size.width, radius);
path.lineTo(size.width, size.height - radius);
path.cubicTo(size.width, size.height - radius, size.width, size.height,
size.width - radius, size.height);
path.lineTo(radius, size.height);
path.cubicTo(radius, size.height, 0, size.height, 0, size.height - radius);
path.lineTo(0, radius);
path.cubicTo(0, radius, 0, 0, radius, 0);
path.lineTo(((size.width - textWidth) / 2), 0);
canvas.drawPath(path, painter);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
and this widget:
class CustomTitleWidget extends StatefulWidget {
final double height;
final double width;
final double? radius;
final String title;
const CustomTitleWidget(
{Key? key,
required this.height,
required this.width,
required this.title,
this.radius})
: super(key: key);
#override
State<CustomTitleWidget> createState() => _CustomTitleWidgetState();
}
class _CustomTitleWidgetState extends State<CustomTitleWidget> {
GlobalKey textKey = GlobalKey();
double textHeight = 0.0;
double textWidth = 0.0;
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
final textKeyContext = textKey.currentContext;
if (textKeyContext != null) {
final box = textKeyContext.findRenderObject() as RenderBox;
textHeight = box.size.height;
textWidth = box.size.width;
}
});
});
}
#override
Widget build(BuildContext context) {
return Stack(
clipBehavior: Clip.none,
alignment: Alignment.topCenter,
children: [
CustomPaint(
child: Container(
height: widget.height,
width: widget.width,
),
painter: CustomDraw(
Colors.red,
textWidth,
radius: widget.radius ?? 0,
),
),
Positioned(
top: -textHeight / 2,
child: Padding(
key: textKey,
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
widget.title,
),
),
)
],
);
}
}
use like this:
CustomTitleWidget(
height: 200,
width: double.infinity,
title: 'asdasdasdasdasd',
radius: 16),
#Maenda, We can implement such kind of structure using Stack, take one container with a border & put the other container over the first one.
Here is an example:
Stack(
children: [
Positioned(
top: 12,
left: 0,
right: 0,
child: Container(
height: 120,
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.green,
border: Border.all(width: 1.2),
borderRadius: BorderRadius.circular(3)),
)),
Container(
margin: EdgeInsets.symmetric(
horizontal: 21,
),
child: Column(
children: [
Container(
width: 100,
margin: EdgeInsets.only(top: 12, bottom: 5),
alignment: Alignment.center,
color: Colors.blue,
child: Text(
"Any Text",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
),
Text(
"Nature, in the broadest sense, is the physical world or universe. Nature can refer to the phenomena of the physical world, and also to life in general.",
textAlign: TextAlign.center,
),
SizedBox(
height: 8,
)
],
),
),
],
);
Hope this works! You can customize as per the design.

How to give border to Clippath and fit text of dynamic length in flutter?

I am trying to achieve the design as in the image below:
I could achieve the output as shown in the image below:
As in the first image, there is border with all the text fitted inside it. The length and lines of text inside clip is dynamic and can be of anylength and line.
My Problem is the text does not get it inside the clippath. Also the border of clipath is not showing properly. I have implmented as follows:
ListView.builder(
shrinkWrap: true,
itemCount: 10,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (ctx, i) {
return i % 2 == 0
? Padding(
padding:
const EdgeInsets.fromLTRB(10, 10, 0, 0),
child: CustomPaint(
painter: ReceiverBubble(),
child: Container(
width:
MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(12),
child: Expanded(
child: Wrap(
children: [
Text(
" One of the most common way to do this is, using paths. In this blog post, we will go through each function which in Path class and see how ... One of the most common way to do this is, using paths. In this blog post, we will go through each function which in Path class and see how ...,",
style: TextStyle(
color: Colors.white,
fontSize: 18),
softWrap: true,
),
],
),
)),
),
)
: Padding(
padding:
const EdgeInsets.fromLTRB(10, 0, 0, 0),
child: CustomPaint(
painter: SenderBubble(),
child: Container(
width:
MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(12),
child: Wrap(
children: [
Text(
" One of the most common way to do this is, using paths. In this blog post, we will go through each function which in Path class and see how ... One of the most common way to do this is, using paths. In this blog post, we will go through each function which in Path class and see how ...,",
style: TextStyle(
color: Colors.white,
fontSize: 18),
softWrap: true,
),
],
)),
),
);
},
),
Sender bubble
class SenderBubble extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 2.0
..color = Colors.white.withOpacity(0.5);
Path path = Path();
Receiver Bubble
class ReceiverBubble extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 2.0
..color = Colors.white.withOpacity(0.5);
Path path = Path();
path.lineTo(0.0, size.height-size.height*0.2);
path.lineTo(size.width-size.width*0.3,size.height-size.height*0.2);
path.lineTo(size.width-size.width*0.2,size.height);
path.lineTo(size.width-size.width*0.2,0);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
path.lineTo(0.0, size.height);
path.lineTo(
size.height - size.height * 0.8, size.height - size.height * 0.2);
path.lineTo(size.width, size.height - size.height * 0.2);
path.lineTo(size.width, 0);
path.close();
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}

flutter : I want curve clip on top

I am using multiple curve in my container but that is show on bottom. how to set on top?
Please help me.
I am using multiple curve in my container but that is show on bottom. how to set on top?
Please help me.
I am using multiple curve in my container but that is show on bottom. how to set on top?
Please help me.
This is my code.
import 'package:evillage_app/style/style.dart';
import 'package:flutter/material.dart';
class MenuCard extends StatefulWidget {
const MenuCard({Key? key}) : super(key: key);
#override
_MenuCardState createState() => _MenuCardState();
}
class _MenuCardState extends State<MenuCard> {
List menuService = [
{'name': 'ASAA', 'icon': 'assets/icon/ASAA.png'},
{'name': 'INFO INDIA', 'icon': 'assets/icon/Info India.png'},
{'name': 'BUSINESS', 'icon': 'assets/icon/business.png'},
{'name': 'E-DIARY', 'icon': 'assets/icon/e Diary.png'},
{'name': 'NEWS', 'icon': 'assets/icon/News.png'},
{'name': 'SERVICES', 'icon': 'assets/icon/Service.png'},
];
#override
Widget build(BuildContext context) {
return Stack(
children: [
ClipPath(
clipper:SkewCut() ,
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.width / 1.58,
decoration: BoxDecoration(gradient: menuGradient),
child: GridView.count(
crossAxisCount: 2,
childAspectRatio: (2 / 0.75),
crossAxisSpacing: 2,
mainAxisSpacing: 5,
physics: ScrollPhysics(),
padding: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width / 30,
vertical: 13),
children: List.generate(
menuService.length,
(index) {
return Container(
child: Card(
shadowColor: Colors.grey,
elevation: 4,
child: Container(
width: MediaQuery.of(context).size.width / 1,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(25)),
color: Colors.white,
),
child: ListTile(
leading: CircleAvatar(
// backgroundColor: red,
backgroundImage:
AssetImage(menuService[index]['icon']),
),
contentPadding: EdgeInsets.only(left: 15),
title: Text(
menuService[index]['name'].toString(),
style: labelStyle(),
overflow: TextOverflow.ellipsis,
),
)),
));
},
),
),
),
),
],
);
}
}
class SkewCut extends CustomClipper<Path> {
#override
Path getClip(Size size) {
Path path = Path();
path.lineTo(0, size.height);
path.quadraticBezierTo(
size.width / 4, size.height - 40, size.width / 2, size.height - 20);
path.quadraticBezierTo(
3 / 4 * size.width, size.height, size.width, size.height - 30);
path.lineTo(size.width, 0);
return path;
}
#override
bool shouldReclip(SkewCut oldClipper) => false;
}
This is ScreenShot
My suggestion would be using CustomPaint instead of CustomClipper<Path>.
CustomPaint
class SkewCut extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.color = Colors.purpleAccent;
paint.style = PaintingStyle.fill;
var pathUp = Path();
pathUp.moveTo(0, size.height * 0.1033);
pathUp.quadraticBezierTo(size.width * 0.25, size.height * 0.145,
size.width * 0.5, size.height * 0.1033);
pathUp.quadraticBezierTo(size.width * 0.75, size.height * 0.0750,
size.width * 1.0, size.height * 0.1033);
pathUp.lineTo(size.width, 0);
pathUp.lineTo(0, 0);
canvas.drawPath(pathUp, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
I have just replaced your CustomClipper with CustomPainter.
Usage
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: CustomPaint(
painter: SkewCut(),
child: <<YOUR CHILD WIDGET>>,
),
);
}
While there are many ways to do this but personally I use the following visual editor to have some generated code and then tweak it based on requirements.
https://fluttershapemaker.com/
This saves me a lot of time and effort.

Flutter custom shape using CustomPaint

I just want my created shape so that i can stack a widget to achieve the Image below. i am trying to get the transparent shape at the back ground of the X and Love. I Try using the shape maker but my mouse designing is not perfect. here is the code generated from the shape maker
child: CustomPaint(
size: Size(400,(400*0.2857142857142857).toDouble()),
painter: RPSCustomPainter(),
),
class RPSCustomPainter extends CustomPainter{
#override
void paint(Canvas canvas, Size size) {
Paint paint_0 = new Paint()
..color = Color.fromARGB(255, 33, 150, 243)
..style = PaintingStyle.stroke
..strokeWidth = 1;
Path path_0 = Path();
path_0.moveTo(size.width*0.2137714,size.height*0.2524000);
path_0.cubicTo(size.width*0.1736143,size.height*0.4775500,size.width*0.1973000,size.height*0.6711500,size.width*0.2153286,size.height*0.7510000);
path_0.cubicTo(size.width*0.2270429,size.height*0.7777500,size.width*0.2705286,size.height*0.9439500,size.width*0.3556000,size.height*0.7521500);
path_0.cubicTo(size.width*0.3856000,size.height*0.6504000,size.width*0.3970143,size.height*0.6162000,size.width*0.4283571,size.height*0.7526000);
path_0.cubicTo(size.width*0.4669286,size.height*0.8264000,size.width*0.5172429,size.height*0.9022500,size.width*0.5719714,size.height*0.7500000);
path_0.cubicTo(size.width*0.6146429,size.height*0.5440500,size.width*0.5914429,size.height*0.3101000,size.width*0.5713714,size.height*0.2514000);
path_0.cubicTo(size.width*0.5520714,size.height*0.1778000,size.width*0.4875429,size.height*0.0767500,size.width*0.4296571,size.height*0.2527000);
path_0.cubicTo(size.width*0.4023714,size.height*0.3646000,size.width*0.3816857,size.height*0.3850000,size.width*0.3557143,size.height*0.2523000);
path_0.cubicTo(size.width*0.3438571,size.height*0.2086000,size.width*0.2652143,size.height*0.0579000,size.width*0.2137714,size.height*0.2524000);
path_0.close();
canvas.drawPath(path_0, paint_0);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
what i am trying to achieve
my result. the shape is not perfect.
thanks
At first I wanted to describe you the ways you can achieve the shape you want and so on...
But got carried away with this fun programming challenge and ended up creating an actual widget :)
It depends on the font_awesome_flutter package, so don't forget to install it (for the heart icon). font_awesome_flutter
So the widget's source code is:
import 'package:flutter/material.dart';
import 'dart:math' as math;
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
extension ToRadians on int {
double get toRadians => this * (math.pi / 180.0);
}
enum _ButtonType { like, dislike }
class LikeOrNot extends StatelessWidget {
final VoidCallback onLike;
final VoidCallback onDislike;
// Percents from total widget width, default - 2%
final _gapSizeRatio = 0.02;
final _likeIconColor = const Color(0xffb85076);
final _dislikeIconColor = Colors.white;
const LikeOrNot({
Key? key,
required this.onLike,
required this.onDislike,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 2,
child: LayoutBuilder(
builder: (context, constraints) {
final buttonPaddings = constraints.maxHeight * 0.1;
final halfWidth = constraints.maxWidth / 2;
return Stack(
children: [
Positioned.fill(
child: CustomPaint(
painter: RPSCustomPainter(
gapSizeRatio: _gapSizeRatio,
),
),
),
Positioned(
left: 0,
bottom: 0,
top: 0,
right: halfWidth + constraints.maxWidth * _gapSizeRatio,
child: SizedBox.expand(
child: Padding(
padding: EdgeInsets.all(buttonPaddings),
child: _buildButton(_ButtonType.dislike),
),
),
),
Positioned(
right: 0,
bottom: 0,
top: 0,
left: halfWidth + constraints.maxWidth * _gapSizeRatio,
child: SizedBox.expand(
child: Padding(
padding: EdgeInsets.all(buttonPaddings),
child: _buildButton(_ButtonType.like),
),
),
),
],
);
},
),
);
}
Widget _buildButton(_ButtonType buttonType) {
final isPositiveAction = buttonType == _ButtonType.like;
return ElevatedButton(
style: ElevatedButton.styleFrom(
shape: const CircleBorder(),
primary: isPositiveAction ? _dislikeIconColor : _likeIconColor,
onPrimary: isPositiveAction ? _likeIconColor : _dislikeIconColor,
padding: EdgeInsets.zero,
elevation: 10,
shadowColor: Colors.black54,
),
onPressed: onDislike,
child: FractionallySizedBox(
widthFactor: 0.35,
heightFactor: 0.35,
child: FittedBox(
child: isPositiveAction
? const FaIcon(FontAwesomeIcons.heart)
: const Icon(Icons.close),
),
),
);
}
}
class RPSCustomPainter extends CustomPainter {
final double gapSizeRatio;
RPSCustomPainter({
required this.gapSizeRatio,
});
#override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.black.withOpacity(0.08)
..style = PaintingStyle.fill
..strokeWidth = 1;
final path = Path();
final gapSize = size.width * gapSizeRatio;
final arcRadius = size.height / 2 - gapSize / 2;
final leftCircleCenter = Offset(
size.width * 0.25 - gapSize / 2,
size.height / 2,
);
final rightCircleCenter = Offset(
size.width * 0.75 + gapSize / 2,
size.height / 2,
);
path.arcTo(
Rect.fromCircle(
center: leftCircleCenter,
radius: arcRadius,
),
45.toRadians,
270.toRadians,
false,
);
final bezierOffset = arcRadius * (105 / 360);
path.quadraticBezierTo(
size.width / 2,
size.height * 0.30,
rightCircleCenter.dx - arcRadius + bezierOffset,
rightCircleCenter.dy - arcRadius + bezierOffset,
);
path.arcTo(
Rect.fromCircle(
center: rightCircleCenter,
radius: arcRadius,
),
225.toRadians,
270.toRadians,
false,
);
path.quadraticBezierTo(
size.width / 2,
size.height * 0.70,
leftCircleCenter.dx + arcRadius - bezierOffset,
leftCircleCenter.dy + arcRadius - bezierOffset,
);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return false;
}
}
It's dynamic, the buttons are built-in. You get 2 options to work with - onDislike() and onLike() callbacks.
An example using different sizes.
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xffc0496f), Color(0xffdb6b59)],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
),
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
title: const Text('Test'),
backgroundColor: Colors.transparent,
elevation: 0,
),
body: Container(
width: double.infinity,
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
for (final size in List.generate(5, (index) => index++))
FractionallySizedBox(
widthFactor: 1.0 - size * 0.2,
child: LikeOrNot(
onLike: () {},
onDislike: () {},
),
),
],
),
),
),
);
}
}
There's a _gapSize parameter which is the gap between two circles. The one you need is already inside (2% default) but you can get some cool other variations by changing it. For example, here's a gap of 20% total width:

Flutter Cards : How can i create a custom card widget in flutter

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/