这是制作圆角容器的方法:
Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10),),
字符串但是有没有办法像下图那样做倒圆角呢?我在网上找不到
的数据
vwhgwdsa1#
作为选项(基于@pskink tip)
import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp(home: Scaffold(appBar: AppBar(), body: Demo())); }}class Demo extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: Column( children: [ Container( width: 300, height: 200, margin: const EdgeInsets.only(top: 24, bottom: 16), decoration: ShapeDecoration(shape: WeirdBorder(radius: 32), color: Colors.red), ), Container( width: 200, height: 100, margin: const EdgeInsets.only(bottom: 16), decoration: ShapeDecoration(shape: WeirdBorder(radius: 16, pathWidth: 8), color: Colors.green), ), Container( width: 300, height: 200, decoration: ShapeDecoration(shape: WeirdBorder(radius: 12, pathWidth: 2), color: Colors.blue), ), ], ), ); }}class WeirdBorder extends ShapeBorder { final double radius; final double pathWidth; WeirdBorder({@required this.radius, this.pathWidth = 1}); @override EdgeInsetsGeometry get dimensions => EdgeInsets.zero; @override Path getInnerPath(Rect rect, {TextDirection textDirection}) { return Path() ..fillType = PathFillType.evenOdd ..addPath(getOuterPath(rect, textDirection: textDirection), Offset.zero); } @override Path getOuterPath(Rect rect, {TextDirection textDirection}) => _createPath(rect); @override void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {} @override ShapeBorder scale(double t) => WeirdBorder(radius: radius); Path _createPath(Rect rect) { final innerRadius = radius + pathWidth; final innerRect = Rect.fromLTRB(rect.left + pathWidth, rect.top + pathWidth, rect.right - pathWidth, rect.bottom - pathWidth); final outer = Path.combine(PathOperation.difference, Path()..addRect(rect), _createBevels(rect, radius)); final inner = Path.combine(PathOperation.difference, Path()..addRect(innerRect), _createBevels(rect, innerRadius)); return Path.combine(PathOperation.difference, outer, inner); } Path _createBevels(Rect rect, double radius) { return Path() ..addOval(Rect.fromCircle(center: Offset(rect.left, rect.top), radius: radius)) ..addOval(Rect.fromCircle(center: Offset(rect.left + rect.width, rect.top), radius: radius)) ..addOval(Rect.fromCircle(center: Offset(rect.left, rect.top + rect.height), radius: radius)) ..addOval(Rect.fromCircle(center: Offset(rect.left + rect.width, rect.top + rect.height), radius: radius)); }}
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(home: Scaffold(appBar: AppBar(), body: Demo()));
}
class Demo extends StatelessWidget {
return Center(
child: Column(
children: [
Container(
width: 300,
height: 200,
margin: const EdgeInsets.only(top: 24, bottom: 16),
decoration: ShapeDecoration(shape: WeirdBorder(radius: 32), color: Colors.red),
),
width: 200,
height: 100,
margin: const EdgeInsets.only(bottom: 16),
decoration: ShapeDecoration(shape: WeirdBorder(radius: 16, pathWidth: 8), color: Colors.green),
decoration: ShapeDecoration(shape: WeirdBorder(radius: 12, pathWidth: 2), color: Colors.blue),
],
);
class WeirdBorder extends ShapeBorder {
final double radius;
final double pathWidth;
WeirdBorder({@required this.radius, this.pathWidth = 1});
EdgeInsetsGeometry get dimensions => EdgeInsets.zero;
Path getInnerPath(Rect rect, {TextDirection textDirection}) {
return Path()
..fillType = PathFillType.evenOdd
..addPath(getOuterPath(rect, textDirection: textDirection), Offset.zero);
Path getOuterPath(Rect rect, {TextDirection textDirection}) => _createPath(rect);
void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {}
ShapeBorder scale(double t) => WeirdBorder(radius: radius);
Path _createPath(Rect rect) {
final innerRadius = radius + pathWidth;
final innerRect = Rect.fromLTRB(rect.left + pathWidth, rect.top + pathWidth, rect.right - pathWidth, rect.bottom - pathWidth);
final outer = Path.combine(PathOperation.difference, Path()..addRect(rect), _createBevels(rect, radius));
final inner = Path.combine(PathOperation.difference, Path()..addRect(innerRect), _createBevels(rect, innerRadius));
return Path.combine(PathOperation.difference, outer, inner);
Path _createBevels(Rect rect, double radius) {
..addOval(Rect.fromCircle(center: Offset(rect.left, rect.top), radius: radius))
..addOval(Rect.fromCircle(center: Offset(rect.left + rect.width, rect.top), radius: radius))
..addOval(Rect.fromCircle(center: Offset(rect.left, rect.top + rect.height), radius: radius))
..addOval(Rect.fromCircle(center: Offset(rect.left + rect.width, rect.top + rect.height), radius: radius));
字符串x1c 0d1x的数据
92dk7w1h2#
你也可以使用fw_ticket包。
ua4mk5z43#
如果你想创建一个自定义票,每个角落都可以独立定制。我有一些东西。这就是结果:
的数据这里是代码。
import 'package:flutter/material.dart';class SwTicketBorder extends ShapeBorder { final double radius; final Color? fillColor; final double borderWidth; final Color? borderColor; final bool topLeft; final bool topRight; final bool bottomLeft; final bool bottomRight; const SwTicketBorder({ required this.radius, this.fillColor, this.borderWidth = 1.0, this.borderColor, this.topLeft = true, this.topRight = true, this.bottomLeft = true, this.bottomRight = true, }); @override EdgeInsetsGeometry get dimensions => EdgeInsets.all(borderWidth); @override Path getInnerPath(Rect rect, {TextDirection? textDirection}) { return Path() ..fillType = PathFillType.evenOdd ..addPath(getOuterPath(rect, textDirection: textDirection), Offset.zero); } @override Path getOuterPath(Rect rect, {TextDirection? textDirection}) => _createPath(rect); @override void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) { if (fillColor == null && borderColor == null) return; if (fillColor != null) { final fillPaint = Paint() ..color = fillColor! // Use the provided fillColor ..style = PaintingStyle.fill; final fillPath = getInnerPath(rect, textDirection: textDirection); canvas.drawPath(fillPath, fillPaint); } if (borderColor != null) { final borderPaint = Paint() ..color = borderColor! ..style = PaintingStyle.stroke ..strokeWidth = borderWidth; final borderPath = getOuterPath(rect, textDirection: textDirection); canvas.drawPath(borderPath, borderPaint); } } Path _createPath(Rect rect) { // Inset the rect by the pathWidth so the border is inside the rect. Rect insetRect = rect.deflate(borderWidth); // The path for the 'ticket' shape Path path = Path(); // The distance from the corner to start the curve for the inverted corners double inset = radius; // Move to the start point path.moveTo(insetRect.left + inset, insetRect.top); // Top line and top-right inverted corner path.lineTo(insetRect.right - inset, insetRect.top); path.arcToPoint( Offset(insetRect.right, insetRect.top + inset), radius: Radius.circular(inset), clockwise: !topRight, ); // Right line and bottom-right inverted corner path.lineTo(insetRect.right, insetRect.bottom - inset); path.arcToPoint( Offset(insetRect.right - inset, insetRect.bottom), radius: Radius.circular(inset), clockwise: !bottomRight, ); // Bottom line and bottom-left inverted corner path.lineTo(insetRect.left + inset, insetRect.bottom); path.arcToPoint( Offset(insetRect.left, insetRect.bottom - inset), radius: Radius.circular(inset), clockwise: !bottomLeft, ); // Left line and top-left inverted corner path.lineTo(insetRect.left, insetRect.top + inset); path.arcToPoint( Offset(insetRect.left + inset, insetRect.top), radius: Radius.circular(inset), clockwise: !topLeft, ); // Close the path path.close(); return path; } @override ShapeBorder scale(double t) { return SwTicketBorder( radius: radius * t, borderWidth: borderWidth * t, borderColor: borderColor, topLeft: topLeft, topRight: topRight, bottomLeft: bottomLeft, bottomRight: bottomRight, ); }}
class SwTicketBorder extends ShapeBorder {
final Color? fillColor;
final double borderWidth;
final Color? borderColor;
final bool topLeft;
final bool topRight;
final bool bottomLeft;
final bool bottomRight;
const SwTicketBorder({
required this.radius,
this.fillColor,
this.borderWidth = 1.0,
this.borderColor,
this.topLeft = true,
this.topRight = true,
this.bottomLeft = true,
this.bottomRight = true,
});
EdgeInsetsGeometry get dimensions => EdgeInsets.all(borderWidth);
Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
Path getOuterPath(Rect rect, {TextDirection? textDirection}) =>
_createPath(rect);
void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {
if (fillColor == null && borderColor == null) return;
if (fillColor != null) {
final fillPaint = Paint()
..color = fillColor! // Use the provided fillColor
..style = PaintingStyle.fill;
final fillPath = getInnerPath(rect, textDirection: textDirection);
canvas.drawPath(fillPath, fillPaint);
if (borderColor != null) {
final borderPaint = Paint()
..color = borderColor!
..style = PaintingStyle.stroke
..strokeWidth = borderWidth;
final borderPath = getOuterPath(rect, textDirection: textDirection);
canvas.drawPath(borderPath, borderPaint);
// Inset the rect by the pathWidth so the border is inside the rect.
Rect insetRect = rect.deflate(borderWidth);
// The path for the 'ticket' shape
Path path = Path();
// The distance from the corner to start the curve for the inverted corners
double inset = radius;
// Move to the start point
path.moveTo(insetRect.left + inset, insetRect.top);
// Top line and top-right inverted corner
path.lineTo(insetRect.right - inset, insetRect.top);
path.arcToPoint(
Offset(insetRect.right, insetRect.top + inset),
radius: Radius.circular(inset),
clockwise: !topRight,
// Right line and bottom-right inverted corner
path.lineTo(insetRect.right, insetRect.bottom - inset);
Offset(insetRect.right - inset, insetRect.bottom),
clockwise: !bottomRight,
// Bottom line and bottom-left inverted corner
path.lineTo(insetRect.left + inset, insetRect.bottom);
Offset(insetRect.left, insetRect.bottom - inset),
clockwise: !bottomLeft,
// Left line and top-left inverted corner
path.lineTo(insetRect.left, insetRect.top + inset);
Offset(insetRect.left + inset, insetRect.top),
clockwise: !topLeft,
// Close the path
path.close();
return path;
ShapeBorder scale(double t) {
return SwTicketBorder(
radius: radius * t,
borderWidth: borderWidth * t,
borderColor: borderColor,
topLeft: topLeft,
topRight: topRight,
bottomLeft: bottomLeft,
bottomRight: bottomRight,
字符串
width: double.infinity, decoration: const ShapeDecoration( shape: SwTicketBorder( radius: 16, fillColor: Colors.grey, borderColor: Colors.yellow, borderWidth: 4, bottomLeft: true, bottomRight: true, topLeft: false, topRight: false, ), ), padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 24, ), child: const Column( children: [ Text( "This is a ticket", style: TextStyle( fontSize: 24, fontWeight: FontWeight.w600, ), ), Text( "And this is its description", style: TextStyle( fontSize: 16, ), ), ], ),)
width: double.infinity,
decoration: const ShapeDecoration(
shape: SwTicketBorder(
radius: 16,
fillColor: Colors.grey,
borderColor: Colors.yellow,
borderWidth: 4,
bottomLeft: true,
bottomRight: true,
topLeft: false,
topRight: false,
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 24,
child: const Column(
Text(
"This is a ticket",
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w600,
"And this is its description",
fontSize: 16,
)
型
3条答案
按热度按时间vwhgwdsa1#
作为选项(基于@pskink tip)
字符串
x1c 0d1x的数据
92dk7w1h2#
你也可以使用fw_ticket包。
ua4mk5z43#
如果你想创建一个自定义票,每个角落都可以独立定制。我有一些东西。
这就是结果:
的数据
这里是代码。
形状
字符串
使用示例
型