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

Flutter中如何创建带圆角、带模糊效果的自定义裁剪形状?

Creating a Custom Rounded, Blurred Shape in Flutter

Absolutely! Flutter gives you all the tools you need to clip a custom shape, add a blur effect, and define rounded corners—let’s break down how to pull this off step by step:

Key Components You’ll Use

  • ClipPath: Clips any widget to a custom shape defined by a CustomClipper<Path>.
  • BackdropFilter: Applies a blur effect to the content behind the widget (perfect for that frosted glass look).
  • CustomClipper<Path>: Lets you define your exact desired shape, including rounded corners where you need them.

Step 1: Build Your Custom Clipper with Rounded Corners

First, create a CustomClipper class to outline your target shape. We’ll use Path.arcToPoint() to add smooth rounded corners to each edge.

For example, here’s a clipper for a marker-style shape with rounded edges:

class CustomMarkerClipper extends CustomClipper<Path> {
  final double borderRadius;

  CustomMarkerClipper({this.borderRadius = 16.0});

  @override
  Path getClip(Size size) {
    final path = Path();
    
    // Start at top-left rounded corner
    path.moveTo(borderRadius, 0);
    // Draw top edge to top-right rounded corner
    path.lineTo(size.width - borderRadius, 0);
    path.arcToPoint(
      Offset(size.width, borderRadius),
      radius: Radius.circular(borderRadius),
      clockwise: true,
    );
    // Draw slanted right edge to bottom-right rounded corner
    path.lineTo(size.width * 0.8, size.height - borderRadius);
    path.arcToPoint(
      Offset(size.width * 0.8 - borderRadius, size.height),
      radius: Radius.circular(borderRadius),
      clockwise: true,
    );
    // Draw bottom edge to bottom-left rounded corner
    path.lineTo(borderRadius, size.height);
    path.arcToPoint(
      Offset(0, size.height - borderRadius),
      radius: Radius.circular(borderRadius),
      clockwise: true,
    );
    // Draw left edge back to starting point
    path.lineTo(0, borderRadius);
    path.arcToPoint(
      Offset(borderRadius, 0),
      radius: Radius.circular(borderRadius),
      clockwise: true,
    );

    return path;
  }

  @override
  bool shouldReclip(covariant CustomMarkerClipper oldClipper) {
    return oldClipper.borderRadius != borderRadius;
  }
}

Step 2: Combine Clipping and Blur

Wrap your content (or a semi-transparent backdrop) with ClipPath and BackdropFilter to get the blurred, clipped shape. A semi-transparent fill will help the blur effect stand out against the background:

ClipPath(
  clipper: CustomMarkerClipper(borderRadius: 20),
  child: BackdropFilter(
    filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
    child: Container(
      width: 300,
      height: 150,
      decoration: BoxDecoration(
        color: Colors.white.withOpacity(0.2), // Soft semi-transparent fill
        border: Border.all(color: Colors.white.withOpacity(0.3)),
      ),
      child: const Center(
        child: Text(
          "Blurred Custom Shape",
          style: TextStyle(color: Colors.white, fontSize: 18),
        ),
      ),
    ),
  ),
)

Step 3: Full Working Example

Here’s a complete screen that uses a background image to showcase the blur effect clearly:

import 'dart:ui';
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Stack(
          children: [
            // Background image to show blur effect
            Image.network(
              'https://picsum.photos/800/1200',
              fit: BoxFit.cover,
              width: double.infinity,
              height: double.infinity,
            ),
            // Blurred custom shape positioned in the center
            Center(
              child: ClipPath(
                clipper: CustomMarkerClipper(borderRadius: 20),
                child: BackdropFilter(
                  filter: ImageFilter.blur(sigmaX: 12, sigmaY: 12),
                  child: Container(
                    width: 320,
                    height: 160,
                    decoration: BoxDecoration(
                      color: Colors.blueGrey.withOpacity(0.15),
                      border: Border.all(color: Colors.white.withOpacity(0.4)),
                    ),
                    child: const Padding(
                      padding: EdgeInsets.all(16.0),
                      child: Text(
                        "This is a custom rounded blurred shape!",
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: 20,
                          fontWeight: FontWeight.w500,
                        ),
                        textAlign: TextAlign.center,
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// Include the CustomMarkerClipper class from Step 1 here
class CustomMarkerClipper extends CustomClipper<Path> {
  final double borderRadius;

  CustomMarkerClipper({this.borderRadius = 16.0});

  @override
  Path getClip(Size size) {
    final path = Path();
    
    path.moveTo(borderRadius, 0);
    path.lineTo(size.width - borderRadius, 0);
    path.arcToPoint(
      Offset(size.width, borderRadius),
      radius: Radius.circular(borderRadius),
      clockwise: true,
    );
    path.lineTo(size.width * 0.8, size.height - borderRadius);
    path.arcToPoint(
      Offset(size.width * 0.8 - borderRadius, size.height),
      radius: Radius.circular(borderRadius),
      clockwise: true,
    );
    path.lineTo(borderRadius, size.height);
    path.arcToPoint(
      Offset(0, size.height - borderRadius),
      radius: Radius.circular(borderRadius),
      clockwise: true,
    );
    path.lineTo(0, borderRadius);
    path.arcToPoint(
      Offset(borderRadius, 0),
      radius: Radius.circular(borderRadius),
      clockwise: true,
    );

    return path;
  }

  @override
  bool shouldReclip(covariant CustomMarkerClipper oldClipper) {
    return oldClipper.borderRadius != borderRadius;
  }
}

Quick Tips

  • Adjust Blur Strength: Tweak sigmaX and sigmaY in ImageFilter.blur()—higher values mean a more intense blur.
  • Optimize Performance: BackdropFilter can be resource-heavy. Limit its size to only the area you need, and avoid nesting multiple instances.
  • Customize the Shape: Modify the getClip() method in CustomMarkerClipper to match your exact design. Use Path methods like quadraticBezierTo() or arcTo() to create any curve or angle.

内容的提问来源于stack exchange,提问作者Rafiqul Hasan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:54:02