如何用Dart实现Flutter Container波浪边框?求可行方案
Flutter Container波浪边框实现方案

一、自定义实现(无需第三方包)
用Stack+CustomPaint是实现这种波浪边框更靠谱的方式,比单纯堆Container灵活多了。核心是自己写CustomPainter绘制波浪路径,再叠加在内容容器上。
完整代码示例:
import 'package:flutter/material.dart'; class WaveBorderContainer extends StatelessWidget { final Widget child; final Color borderColor; final double borderWidth; final double waveHeight; final double waveCount; const WaveBorderContainer({ super.key, required this.child, this.borderColor = Colors.blue, this.borderWidth = 2.0, this.waveHeight = 8.0, this.waveCount = 6.0, }); @override Widget build(BuildContext context) { return Stack( children: [ // 底层内容容器 child, // 叠加波浪边框 Positioned.fill( child: CustomPaint( painter: WaveBorderPainter( borderColor: borderColor, borderWidth: borderWidth, waveHeight: waveHeight, waveCount: waveCount, ), ), ), ], ); } } class WaveBorderPainter extends CustomPainter { final Color borderColor; final double borderWidth; final double waveHeight; final double waveCount; WaveBorderPainter({ required this.borderColor, required this.borderWidth, required this.waveHeight, required this.waveCount, }); @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = borderColor ..style = PaintingStyle.stroke ..strokeWidth = borderWidth; final path = Path(); final waveWidth = size.width / waveCount; // 画顶部波浪 path.moveTo(0, 0); for (int i = 0; i <= waveCount.toInt(); i++) { final isEven = i % 2 == 0; final x = i * waveWidth; final y = isEven ? 0 : waveHeight; if (i == 0) { path.moveTo(x, y); } else { final controlX = (x - waveWidth / 2); final controlY = isEven ? waveHeight : 0; path.quadraticBezierTo(controlX, controlY, x, y); } } // 画右侧竖边 path.lineTo(size.width, size.height); // 画底部波浪 for (int i = waveCount.toInt(); i >= 0; i--) { final isEven = i % 2 == 0; final x = i * waveWidth; final y = isEven ? size.height : size.height - waveHeight; final controlX = (x - waveWidth / 2); final controlY = isEven ? size.height - waveHeight : size.height; path.quadraticBezierTo(controlX, controlY, x, y); } // 画左侧竖边闭合路径 path.lineTo(0, 0); canvas.drawPath(path, paint); } @override bool shouldRepaint(covariant WaveBorderPainter oldDelegate) { return oldDelegate.borderColor != borderColor || oldDelegate.borderWidth != borderWidth || oldDelegate.waveHeight != waveHeight || oldDelegate.waveCount != waveCount; } } // 调用示例 class DemoPage extends StatelessWidget { const DemoPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: WaveBorderContainer( borderColor: Colors.orange, waveHeight: 10, waveCount: 8, child: Container( width: 300, height: 200, color: Colors.white, alignment: Alignment.center, child: const Text("波浪边框容器"), ), ), ), ); } }
二、第三方包快速实现
嫌自己写麻烦的话,用flutter_custom_clippers包就行,它内置了多种波浪形状的裁剪器,能快速凑出类似效果。
步骤:
- 先在
pubspec.yaml加依赖:
dependencies: flutter_custom_clippers: ^2.1.0
- 实现代码:
import 'package:flutter/material.dart'; import 'package:flutter_custom_clippers/flutter_custom_clippers.dart'; class WaveBorderDemo extends StatelessWidget { const WaveBorderDemo({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: SizedBox( width: 300, height: 200, child: Stack( children: [ // 内容容器 Container( width: 300, height: 200, color: Colors.white, alignment: Alignment.center, child: const Text("第三方包实现波浪边框"), ), // 外层波浪边框 ClipPath( clipper: WaveClipperTwo(), // 换WaveClipperOne能得到不同波浪样式 child: Container( width: 300, height: 200, decoration: BoxDecoration( border: Border.all(color: Colors.blue, width: 2), ), ), ), ], ), ), ), ); } }
如果需要更贴合你要的效果,可以试试调整裁剪器的参数,或者组合多个裁剪器使用。
内容的提问来源于stack exchange,提问作者Toby Yhs
相关产品推荐
相关产品推荐

