Flutter自定义裁剪路径插件custom_clippers的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter自定义裁剪路径插件custom_clippers的使用

custom_clippers 是一个包含多种自定义裁剪器(clippers)的Flutter插件,可以用于创建具有独特形状的UI元素。通过将这些裁剪器应用到 ClipPath 小部件中,您可以轻松地实现各种视觉效果。

开始使用

添加依赖

在您的 pubspec.yaml 文件中添加 custom_clippers 作为依赖:

dependencies:
  custom_clippers: ^1.0.0

然后执行 flutter pub get 来安装插件。

导入包

在需要使用裁剪器的地方导入 custom_clippers 包:

import 'package:custom_clippers/custom_clippers.dart';

使用示例

下面是一个完整的示例代码,展示了如何使用 custom_clippers 插件来创建不同的裁剪效果。我们将创建一个应用程序,其中包含多个不同类型的裁剪器。

示例代码

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Custom Clippers Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: ClippersPage(title: 'Custom Clippers Demo'),
    );
  }
}

class ClippersPage extends StatefulWidget {
  ClippersPage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _ClippersPageState createState() => _ClippersPageState();
}

class _ClippersPageState extends State<ClippersPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: ListView(
        padding: EdgeInsets.all(20),
        physics: BouncingScrollPhysics(),
        children: [
          /// Multiple Points Clipper bottom only with height of points as 50
          ClipPath(
            clipper: MultiplePointsClipper(Sides.bottom, heightOfPoint: 50),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.red,
              alignment: Alignment.center,
              child: Text(
                'Multiple Points Clipper Bottom Only',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Multiple Points Clipper vertical with number of points as 50
          ClipPath(
            clipper: MultiplePointsClipper(Sides.vertical, numberOfPoints: 50),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.green,
              alignment: Alignment.center,
              child: Text(
                'Multiple Points Clipper Vertical',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Multiple Rounded Points Clipper bottom only with number of points as 30
          ClipPath(
            clipper: MultipleRoundedPointsClipper(Sides.bottom, numberOfPoints: 30),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.blue,
              alignment: Alignment.center,
              child: Text(
                'Multiple Rounded Points Clipper Bottom Only',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Multiple Rounded Points Clipper vertical with height of points as 50
          ClipPath(
            clipper: MultipleRoundedPointsClipper(Sides.vertical, heightOfPoint: 50),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.yellow,
              alignment: Alignment.center,
              child: Text(
                'Multiple Rounded Points Clipper Vertical',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Ticket Pass Clipper
          ClipPath(
            clipper: TicketPassClipper(),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.red,
              alignment: Alignment.center,
              child: Text(
                'Ticket Pass Clipper',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Ticket Pass Clipper with position as 80 and hole radius as 40
          ClipPath(
            clipper: TicketPassClipper(position: 80, holeRadius: 40),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.green,
              alignment: Alignment.center,
              child: Text(
                'Ticket Pass Clipper with Custom Position',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Directional Wave Clipper
          ClipPath(
            clipper: DirectionalWaveClipper(),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.blue,
              alignment: Alignment.center,
              child: Text(
                'Directional Wave Clipper Bottom Left',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Directional Wave Clipper with vertical position as VerticalPosition.TOP
          ClipPath(
            clipper: DirectionalWaveClipper(verticalPosition: VerticalPosition.top),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.yellow,
              alignment: Alignment.center,
              child: Text(
                'Directional Wave Clipper Top Left',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Directional Wave Clipper with horizontal position as HorizontalPosition.RIGHT
          ClipPath(
            clipper: DirectionalWaveClipper(horizontalPosition: HorizontalPosition.right),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.red,
              alignment: Alignment.center,
              child: Text(
                'Directional Wave Clipper Bottom Right',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Directional Wave Clipper with vertical position as VerticalPosition.TOP  and  horizontal position as HorizontalPosition.RIGHT
          ClipPath(
            clipper: DirectionalWaveClipper(
                verticalPosition: VerticalPosition.top,
                horizontalPosition: HorizontalPosition.right),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.green,
              alignment: Alignment.center,
              child: Text(
                'Directional Wave Clipper Top Right',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Sin Cosine Wave Clipper
          ClipPath(
            clipper: SinCosineWaveClipper(),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.blue,
              alignment: Alignment.center,
              child: Text(
                'Sin Cosine Wave Clipper Bottom Left',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Sin Cosine Wave Clipper with vertical position as VerticalPosition.TOP
          ClipPath(
            clipper: SinCosineWaveClipper(verticalPosition: VerticalPosition.top),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.yellow,
              alignment: Alignment.center,
              child: Text(
                'Sin Cosine Wave Clipper Top Left',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Sin Cosine Wave with horizontal position as HorizontalPosition.RIGHT
          ClipPath(
            clipper: SinCosineWaveClipper(horizontalPosition: HorizontalPosition.right),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.red,
              alignment: Alignment.center,
              child: Text(
                'Sin Cosine Wave Clipper Bottom Right',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Sin Cosine Wave Clipper with vertical position as VerticalPosition.TOP  and  horizontal position as HorizontalPosition.RIGHT
          ClipPath(
            clipper: SinCosineWaveClipper(
                verticalPosition: VerticalPosition.top,
                horizontalPosition: HorizontalPosition.right),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.green,
              alignment: Alignment.center,
              child: Text(
                'Sin Cosine Wave Clipper Top Right',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Three Rounded Edges Message Clipper Sender Side
          ClipPath(
            clipper: ThreeRoundedEdgesMessageClipper(MessageType.send),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.blue,
              alignment: Alignment.center,
              child: Text(
                'Three Rounded Edges Message Clipper Sender',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Three Rounded Edges Message Clipper Receiver Side
          ClipPath(
            clipper: ThreeRoundedEdgesMessageClipper(MessageType.receive),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.yellow,
              alignment: Alignment.center,
              child: Text(
                'Three Rounded Edges Message Clipper Receiver',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Diagonal Rounded Edges Message Clipper Sender Side
          ClipPath(
            clipper: DiagonalRoundedEdgesMessageClipper(MessageType.send),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.red,
              alignment: Alignment.center,
              child: Text(
                'Diagonal Rounded Edges Message Clipper Sender',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Diagonal Rounded Edges Message Clipper Receiver Side
          ClipPath(
            clipper: DiagonalRoundedEdgesMessageClipper(MessageType.receive),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.green,
              alignment: Alignment.center,
              child: Text(
                'Diagonal Rounded Edges Message Clipper Receiver',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Lower Nip Message Clipper Sender Side
          ClipPath(
            clipper: LowerNipMessageClipper(MessageType.send),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.blue,
              alignment: Alignment.center,
              child: Text(
                'Lower Nip Message Clipper Sender',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Lower Nip Message Clipper Receiver Side
          ClipPath(
            clipper: LowerNipMessageClipper(MessageType.receive),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.yellow,
              alignment: Alignment.center,
              child: Text(
                'Lower Nip Message Clipper Receiver',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Upper Nip Message Clipper Sender Side
          ClipPath(
            clipper: UpperNipMessageClipper(MessageType.send),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.red,
              alignment: Alignment.center,
              child: Text(
                'Upper Nip Message Clipper Sender',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Upper Nip Message Clipper Receiver Side
          ClipPath(
            clipper: UpperNipMessageClipper(MessageType.receive),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.green,
              alignment: Alignment.center,
              child: Text(
                'Upper Nip Message Clipper Receiver',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Upper Nip Message Clipper Two Sender Side
          ClipPath(
            clipper: UpperNipMessageClipperTwo(MessageType.send),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.blue,
              alignment: Alignment.center,
              child: Text(
                'Upper Nip Message Clipper Two Sender',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),

          /// Upper Nip Message Clipper Two Receiver Side
          ClipPath(
            clipper: UpperNipMessageClipperTwo(MessageType.receive),
            child: Container(
              height: 160,
              padding: EdgeInsets.all(20),
              color: Colors.yellow,
              alignment: Alignment.center,
              child: Text(
                'Upper Nip Message Clipper Two Receiver',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          SizedBox(height: 20),
        ],
      ),
    );
  }
}

输出效果

该示例代码将展示多种不同类型的裁剪效果,包括但不限于:

  • 多点裁剪器(Multiple Points Clipper)
  • 圆角多点裁剪器(Multiple Rounded Points Clipper)
  • 票据裁剪器(Ticket Pass Clipper)
  • 方向波浪裁剪器(Directional Wave Clipper)
  • 正弦余弦波浪裁剪器(Sin Cosine Wave Clipper)
  • 消息气泡裁剪器(Message Clipper)

每种裁剪器都提供了独特的视觉效果,适用于不同的UI设计需求。

支持的裁剪器

以下是 custom_clippers 插件支持的一些裁剪器及其效果图:

custom_clipper1 custom_clipper2 custom_clipper3 custom_clipper4 custom_clipper5 custom_clipper6

希望这个指南能帮助您更好地理解和使用 custom_clippers 插件。如果您有任何问题或需要进一步的帮助,请随时提问!


更多关于Flutter自定义裁剪路径插件custom_clippers的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自定义裁剪路径插件custom_clippers的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter中使用custom_clippers插件来创建自定义裁剪路径的示例代码。首先,你需要确保在pubspec.yaml文件中添加了custom_clippers依赖项:

dependencies:
  flutter:
    sdk: flutter
  custom_clippers: ^x.y.z  # 替换为最新的版本号

然后,运行flutter pub get来安装依赖项。

以下是一个示例代码,展示如何使用custom_clippers来创建一个自定义裁剪路径的按钮:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Custom Clippers Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Custom Clippers Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            CustomClipperButton(
              child: Text('Custom Clipper Button'),
              clipper: DiamondClipper(),
            ),
            SizedBox(height: 20),
            CustomClipperButton(
              child: Text('Star Clipper Button'),
              clipper: StarClipper(),
            ),
          ],
        ),
      ),
    );
  }
}

class CustomClipperButton extends StatelessWidget {
  final Widget child;
  final CustomClipper<Rect> clipper;

  CustomClipperButton({required this.child, required this.clipper});

  @override
  Widget build(BuildContext context) {
    return ClipPath(
      clipper: clipper,
      child: Material(
        color: Colors.blue,
        elevation: 5.0,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(10.0),
        ),
        child: InkWell(
          onTap: () {
            print('Button tapped!');
          },
          child: Center(
            child: child,
          ),
        ),
      ),
    );
  }
}

// 自定义钻石形状裁剪器
class DiamondClipper extends CustomClipper<Rect> {
  @override
  Rect getClip(Size size) {
    double width = size.width;
    double height = size.height;
    double aspectRatio = width / height;

    double halfWidth = width / 2.0;
    double halfHeight = height / 2.0;

    double diamondWidth = aspectRatio > 1 ? halfHeight * 2 : halfWidth * 2 / aspectRatio;
    double diamondHeight = aspectRatio > 1 ? halfWidth * 2 * aspectRatio : halfHeight * 2;

    double left = (width - diamondWidth) / 2.0;
    double top = (height - diamondHeight) / 2.0;

    Path path = Path();
    path.moveTo(left + diamondWidth / 2.0, top);
    path.lineTo(left, top + diamondHeight / 2.0);
    path.lineTo(left + diamondWidth / 2.0, top + diamondHeight);
    path.lineTo(left + diamondWidth, top + diamondHeight / 2.0);
    path.close();

    return path.getBounds();
  }

  @override
  bool shouldReclip(CustomClipper<Rect> oldDelegate) => oldDelegate != this;
}

// 自定义星形裁剪器
class StarClipper extends CustomClipper<Rect> {
  @override
  Rect getClip(Size size) {
    double width = size.width;
    double height = size.height;
    double radius = Math.min(width, height) / 2.0;

    Path path = Path();
    path.moveTo(radius, 0);
    for (int i = 0; i < 5; i++) {
      double angle = 2 * Math.pi / 5 * i + Math.pi / 2;
      double outerX = radius + radius * 0.5 * Math.cos(angle - Math.pi / 5);
      double outerY = radius + radius * 0.5 * Math.sin(angle - Math.pi / 5);
      double innerX = radius + radius * 0.2 * Math.cos(angle);
      double innerY = radius + radius * 0.2 * Math.sin(angle);
      if (i == 0) {
        path.moveTo(outerX, outerY);
      } else {
        path.lineTo(outerX, outerY);
      }
      path.lineTo(innerX, innerY);
    }
    path.close();

    return path.getBounds();
  }

  @override
  bool shouldReclip(CustomClipper<Rect> oldDelegate) => oldDelegate != this;
}

这个示例代码展示了如何使用custom_clippers来创建两个自定义裁剪按钮:一个是钻石形状,另一个是星形。你可以根据需要自定义裁剪路径以满足你的应用需求。请注意,这里的DiamondClipperStarClipper只是示例,你可以根据具体需求进一步调整裁剪路径。

回到顶部