dart 如何在Flutter中制作一个倒圆角的容器?

evrscar2  于 2023-11-14  发布在  Flutter
关注(0)|答案(3)|浏览(153)

这是制作圆角容器的方法:

  1. Container(decoration: BoxDecoration(borderRadius: BorderRadius.circular(10),),

字符串
但是有没有办法像下图那样做倒圆角呢?我在网上找不到


的数据

vwhgwdsa

vwhgwdsa1#

作为选项(基于@pskink tip)

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class MyApp extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return MaterialApp(home: Scaffold(appBar: AppBar(), body: Demo()));
  7. }
  8. }
  9. class Demo extends StatelessWidget {
  10. @override
  11. Widget build(BuildContext context) {
  12. return Center(
  13. child: Column(
  14. children: [
  15. Container(
  16. width: 300,
  17. height: 200,
  18. margin: const EdgeInsets.only(top: 24, bottom: 16),
  19. decoration: ShapeDecoration(shape: WeirdBorder(radius: 32), color: Colors.red),
  20. ),
  21. Container(
  22. width: 200,
  23. height: 100,
  24. margin: const EdgeInsets.only(bottom: 16),
  25. decoration: ShapeDecoration(shape: WeirdBorder(radius: 16, pathWidth: 8), color: Colors.green),
  26. ),
  27. Container(
  28. width: 300,
  29. height: 200,
  30. decoration: ShapeDecoration(shape: WeirdBorder(radius: 12, pathWidth: 2), color: Colors.blue),
  31. ),
  32. ],
  33. ),
  34. );
  35. }
  36. }
  37. class WeirdBorder extends ShapeBorder {
  38. final double radius;
  39. final double pathWidth;
  40. WeirdBorder({@required this.radius, this.pathWidth = 1});
  41. @override
  42. EdgeInsetsGeometry get dimensions => EdgeInsets.zero;
  43. @override
  44. Path getInnerPath(Rect rect, {TextDirection textDirection}) {
  45. return Path()
  46. ..fillType = PathFillType.evenOdd
  47. ..addPath(getOuterPath(rect, textDirection: textDirection), Offset.zero);
  48. }
  49. @override
  50. Path getOuterPath(Rect rect, {TextDirection textDirection}) => _createPath(rect);
  51. @override
  52. void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {}
  53. @override
  54. ShapeBorder scale(double t) => WeirdBorder(radius: radius);
  55. Path _createPath(Rect rect) {
  56. final innerRadius = radius + pathWidth;
  57. final innerRect = Rect.fromLTRB(rect.left + pathWidth, rect.top + pathWidth, rect.right - pathWidth, rect.bottom - pathWidth);
  58. final outer = Path.combine(PathOperation.difference, Path()..addRect(rect), _createBevels(rect, radius));
  59. final inner = Path.combine(PathOperation.difference, Path()..addRect(innerRect), _createBevels(rect, innerRadius));
  60. return Path.combine(PathOperation.difference, outer, inner);
  61. }
  62. Path _createBevels(Rect rect, double radius) {
  63. return Path()
  64. ..addOval(Rect.fromCircle(center: Offset(rect.left, rect.top), radius: radius))
  65. ..addOval(Rect.fromCircle(center: Offset(rect.left + rect.width, rect.top), radius: radius))
  66. ..addOval(Rect.fromCircle(center: Offset(rect.left, rect.top + rect.height), radius: radius))
  67. ..addOval(Rect.fromCircle(center: Offset(rect.left + rect.width, rect.top + rect.height), radius: radius));
  68. }
  69. }

字符串
x1c 0d1x的数据

展开查看全部
92dk7w1h

92dk7w1h2#

你也可以使用fw_ticket包。

ua4mk5z4

ua4mk5z43#

如果你想创建一个自定义票,每个角落都可以独立定制。我有一些东西。
这就是结果:


的数据
这里是代码。

形状

  1. import 'package:flutter/material.dart';
  2. class SwTicketBorder extends ShapeBorder {
  3. final double radius;
  4. final Color? fillColor;
  5. final double borderWidth;
  6. final Color? borderColor;
  7. final bool topLeft;
  8. final bool topRight;
  9. final bool bottomLeft;
  10. final bool bottomRight;
  11. const SwTicketBorder({
  12. required this.radius,
  13. this.fillColor,
  14. this.borderWidth = 1.0,
  15. this.borderColor,
  16. this.topLeft = true,
  17. this.topRight = true,
  18. this.bottomLeft = true,
  19. this.bottomRight = true,
  20. });
  21. @override
  22. EdgeInsetsGeometry get dimensions => EdgeInsets.all(borderWidth);
  23. @override
  24. Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
  25. return Path()
  26. ..fillType = PathFillType.evenOdd
  27. ..addPath(getOuterPath(rect, textDirection: textDirection), Offset.zero);
  28. }
  29. @override
  30. Path getOuterPath(Rect rect, {TextDirection? textDirection}) =>
  31. _createPath(rect);
  32. @override
  33. void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {
  34. if (fillColor == null && borderColor == null) return;
  35. if (fillColor != null) {
  36. final fillPaint = Paint()
  37. ..color = fillColor! // Use the provided fillColor
  38. ..style = PaintingStyle.fill;
  39. final fillPath = getInnerPath(rect, textDirection: textDirection);
  40. canvas.drawPath(fillPath, fillPaint);
  41. }
  42. if (borderColor != null) {
  43. final borderPaint = Paint()
  44. ..color = borderColor!
  45. ..style = PaintingStyle.stroke
  46. ..strokeWidth = borderWidth;
  47. final borderPath = getOuterPath(rect, textDirection: textDirection);
  48. canvas.drawPath(borderPath, borderPaint);
  49. }
  50. }
  51. Path _createPath(Rect rect) {
  52. // Inset the rect by the pathWidth so the border is inside the rect.
  53. Rect insetRect = rect.deflate(borderWidth);
  54. // The path for the 'ticket' shape
  55. Path path = Path();
  56. // The distance from the corner to start the curve for the inverted corners
  57. double inset = radius;
  58. // Move to the start point
  59. path.moveTo(insetRect.left + inset, insetRect.top);
  60. // Top line and top-right inverted corner
  61. path.lineTo(insetRect.right - inset, insetRect.top);
  62. path.arcToPoint(
  63. Offset(insetRect.right, insetRect.top + inset),
  64. radius: Radius.circular(inset),
  65. clockwise: !topRight,
  66. );
  67. // Right line and bottom-right inverted corner
  68. path.lineTo(insetRect.right, insetRect.bottom - inset);
  69. path.arcToPoint(
  70. Offset(insetRect.right - inset, insetRect.bottom),
  71. radius: Radius.circular(inset),
  72. clockwise: !bottomRight,
  73. );
  74. // Bottom line and bottom-left inverted corner
  75. path.lineTo(insetRect.left + inset, insetRect.bottom);
  76. path.arcToPoint(
  77. Offset(insetRect.left, insetRect.bottom - inset),
  78. radius: Radius.circular(inset),
  79. clockwise: !bottomLeft,
  80. );
  81. // Left line and top-left inverted corner
  82. path.lineTo(insetRect.left, insetRect.top + inset);
  83. path.arcToPoint(
  84. Offset(insetRect.left + inset, insetRect.top),
  85. radius: Radius.circular(inset),
  86. clockwise: !topLeft,
  87. );
  88. // Close the path
  89. path.close();
  90. return path;
  91. }
  92. @override
  93. ShapeBorder scale(double t) {
  94. return SwTicketBorder(
  95. radius: radius * t,
  96. borderWidth: borderWidth * t,
  97. borderColor: borderColor,
  98. topLeft: topLeft,
  99. topRight: topRight,
  100. bottomLeft: bottomLeft,
  101. bottomRight: bottomRight,
  102. );
  103. }
  104. }

字符串

使用示例

  1. width: double.infinity,
  2. decoration: const ShapeDecoration(
  3. shape: SwTicketBorder(
  4. radius: 16,
  5. fillColor: Colors.grey,
  6. borderColor: Colors.yellow,
  7. borderWidth: 4,
  8. bottomLeft: true,
  9. bottomRight: true,
  10. topLeft: false,
  11. topRight: false,
  12. ),
  13. ),
  14. padding: const EdgeInsets.symmetric(
  15. horizontal: 16,
  16. vertical: 24,
  17. ),
  18. child: const Column(
  19. children: [
  20. Text(
  21. "This is a ticket",
  22. style: TextStyle(
  23. fontSize: 24,
  24. fontWeight: FontWeight.w600,
  25. ),
  26. ),
  27. Text(
  28. "And this is its description",
  29. style: TextStyle(
  30. fontSize: 16,
  31. ),
  32. ),
  33. ],
  34. ),
  35. )

展开查看全部

相关问题