You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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包就行,它内置了多种波浪形状的裁剪器,能快速凑出类似效果。

步骤:

  1. 先在pubspec.yaml加依赖:
dependencies:
  flutter_custom_clippers: ^2.1.0
  1. 实现代码:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 05:15:35