问题
I want to give the above background for container
, tried the following code.but it's not working
ClipPath(
clipper: TriangleClipper(),
child: Container(
margin: EdgeInsets.only(top: 20, right: 20),
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: cardBackground,
borderRadius: BorderRadius.circular(10))),
Class TriangleClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
final path = Path();
path.lineTo(0.0, size.height);
path.lineTo(size.width, size.height);
path.close();
return path;
}
@override
bool shouldReclip(TriangleClipper oldClipper) => false;
}
回答1:
It's better to use custom shapes for this kind of purposes..
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(18.0),
child: Container(
decoration: ShapeDecoration(
color: Color(0xFFf3effd),
shape: MyBorderShape(),
shadows: [
BoxShadow(
color: Colors.black38,
blurRadius: 8.0,
offset: Offset(1, 1)),
],
),
height: 100,
),
),
),
),
);
}
}
class MyBorderShape extends ShapeBorder {
@override
EdgeInsetsGeometry get dimensions => EdgeInsets.zero;
@override
Path getInnerPath(Rect rect, {TextDirection textDirection}) => null;
final double holeSize = 70;
final double borderRadius = 10;
@override
Path getOuterPath(Rect rect, {TextDirection textDirection}) {
print(rect.topLeft);
var startX = rect.topLeft.dx;
var startY = rect.topLeft.dy;
return Path.combine(
PathOperation.union,
Path()
..addRRect(RRect.fromRectAndRadius(rect, Radius.circular(borderRadius)))
..close(),
Path()
..moveTo(startX + 20, startY)
..lineTo(startX + 35, startY - 15)
..lineTo(startX + 50, startY)
..close(),
);
}
@override
void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {}
@override
ShapeBorder scale(double t) => this;
}
回答2:
With ClipPath
, you need to draw the entire path which you want to carve, which will include drawing the triangle as well as the top-left and top-right rounded corners, because the corresponding original corners (borderRadius: BorderRadius.circular(10)
) will be cropped out. One way you can do this is something like this.
class _MyWidgetState extends State<MyWidget> {
@override
Widget build(BuildContext context) {
return ClipPath(
clipper: TriangleClipper(),
child: Container(
padding: EdgeInsets.fromLTRB(20, 30, 20, 20), //extra 10 for top padding because triangle's height = 10
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(10),
),
child: Text('My parent is a fancy container'),
),
);
}
}
class TriangleClipper extends CustomClipper<Path> {
double radius = 10, tw = 20, th = 10; //tw & th = triangle width & height
@override
Path getClip(Size size) {
final path = Path();
path.lineTo(0, size.height);
path.lineTo(size.width, size.height);
path.lineTo(size.width, th + radius);
path.arcToPoint(Offset(size.width - radius, th), radius: Radius.circular(radius), clockwise: false);
path.lineTo(radius + 10 + tw, th);
path.lineTo(radius + 10 + tw/2, 0); //in these lines, the 10 is to have a space of 10 between the top-left corner curve and the triangle
path.lineTo(radius + 10, th);
path.lineTo(radius, th);
path.arcToPoint(Offset(0, th + radius), radius: Radius.circular(radius), clockwise: false);
return path;
}
@override
bool shouldReclip(TriangleClipper oldClipper) => false;
}
Result:
来源:https://stackoverflow.com/questions/63448648/how-to-use-clippath-flutter