Flutter 初识:高级控件

Form

Form 是 Flutter 框架中用于组装和管理表单控件的容器。它提供了一种便捷的方法来进行表单验证和状态管理

属性解析

const Form({
    super.key,
    required this.child,
    this.canPop,
    this.onPopInvoked,
    @Deprecated(
      'Use canPop and/or onPopInvoked instead. '
      'This feature was deprecated after v3.12.0-1.0.pre.',
    )
    this.onWillPop,
    this.onChanged,
    AutovalidateMode? autovalidateMode,
  })
  • child (Widget): 表单的子控件,是必填项。
  • canPop (bool?): 指定是否可以弹出(pop)当前路由,这通常用于自定义处理用户尝试返回时的行为。如果为 true,则在调用 Navigator.pop 时会检查此回调。
  • onPopInvoked (void Function()? onPopInvoked): 当 canPop 为 true 时,如果用户尝试返回,会触发这个回调函数。
  • onWillPop (Future Function()? onWillPop): 这是一个过时的参数,用于拦截返回按钮的点击事件。在v3.12.0-1.0.pre之后已被弃用,推荐使用 canPop 和 onPopInvoked 替代。
  • onChanged (VoidCallback?): 当表单字段的值发生变化时调用的回调函数。
  • autovalidateMode (AutovalidateMode?): 自动验证模式,默认为 AutovalidateMode.disabled。可选值有:
    • AutovalidateMode.disabled: 关闭自动验证,只在调用 validate 方法时进行验证。
    • AutovalidateMode.always: 始终进行自动验证。
    • AutovalidateMode.onUserInteraction: 用户交互后进行自动验证。

示例

class FormExample extends StatefulWidget {
  @override
  _FormExampleState createState() => _FormExampleState();
}

class _FormExampleState extends State<FormExample> {
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Form 示例')),
        body: Form(
          key: _formKey,
          autovalidateMode: AutovalidateMode.onUserInteraction,
          onChanged: () {
            // 当表单字段的值发生变化时执行的代码
            print("Form changed");
          },
          canPop: true, // 在 Navigator.pop 调用时检查
          onPopInvoked: (bool didPop) {
            // 当用户尝试返回时执行的回调函数
            print("User tried to pop the form");
          },
          child: Column(
            children: <Widget>[
              TextFormField(
                decoration: InputDecoration(labelText: '用户名'),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return '请输入用户名';
                  }
                  return null;
                },
              ),
              TextFormField(
                decoration: InputDecoration(labelText: '密码'),
                obscureText: true,
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return '请输入密码';
                  }
                  return null;
                },
              ),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 16.0),
                child: ElevatedButton(
                  onPressed: () {
                    if (_formKey.currentState!.validate()) {
                      // 如果表单验证通过,则执行相关操作
                      ScaffoldMessenger.of(context).showSnackBar(
                        SnackBar(content: Text('正在处理数据')),
                      );
                    }
                  },
                  child: Text('提交'),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

在这里插入图片描述

 
 

FutureBuilder

FutureBuilder 是 Flutter 框架中用于处理异步操作结果的控件。它允许你在等待 Future 完成时显示不同的界面,并根据 Future 的状态更新界面

属性解析

const FutureBuilder({
    super.key,
    required this.future,
    this.initialData,
    required this.builder,
  });
  • future (Future?): 表示将来会完成并返回数据的 Future 对象。当该 Future 变化时,FutureBuilder 会进行重新构建。
  • initialData (T?): 在 Future 完成之前用作初始数据的值。
  • builder (AsyncWidgetBuilder): 构建器函数,根据 AsyncSnapshot 状态构建小部件。这个构建器会频繁调用,所以要确保其实现高效。

示例

class FutureBuilderExample extends StatelessWidget {
  // 模拟一个耗时的异步操作
  Future<String> _fetchData() async {
    await Future.delayed(Duration(seconds: 2)); // 模拟网络延迟
    return '加载完毕的数据';
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('FutureBuilder 示例')),
        body: FutureBuilder<String>(
          future: _fetchData(), // 异步操作
          initialData: '正在加载...', // 初始数据
          builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
            // 根据连接状态构建不同的UI
            if (snapshot.connectionState == ConnectionState.waiting) {
              return CircularProgressIndicator(); // 显示进度条
            } else if (snapshot.hasError) {
              return Text('错误: ${snapshot.error}');
            } else {
              return Text('结果: ${snapshot.data}');
            }
          },
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个 FutureBuilder 小部件,用于异步加载数据。模拟的 _fetchData 函数表示一个耗时的异步操作(例如从网络获取数据),它会在两秒钟之后返回一个字符串结果。

FutureBuilder 使用了三个主要属性:

  • future: 指定了要等待的 Future 对象,即 _fetchData() 方法。
  • initialData: 提供了加载期间显示的初始数据 “正在加载…”。
  • builder: 一个函数,根据 AsyncSnapshot 构建不同的 UI。该函数检查 snapshot.connectionState 来决定当前的状态,并相应地显示进度条、错误信息或最终结果。
     

使用指南

  • 初始化数据: 如果你希望在 Future 完成之前显示某些初始数据,可以设置 initialData 属性。
  • 处理各种状态: 在 builder 函数中,你需要处理 AsyncSnapshot 的各种状态,包括 connectionState、hasData、hasError 等,以便显示适当的 UI。
  • 性能优化: 由于 builder 函数会频繁调用,因此请确保其实现足够高效。

 
通过以上方法,FutureBuilder 能帮助你优雅地处理异步操作,并根据操作状态动态更新界面。

   

StreamBuilder

StreamBuilder 是 Flutter 框架中用于处理和显示流数据的控件。它允许你监听流(Stream)的数据变化,并根据流的最新状态更新界面。

属性解析

const StreamBuilder({
    super.key,
    this.initialData,
    required super.stream,
    required this.builder,
  })
  • stream (Stream?): 表示将会提供连续数据的 Stream 对象。当该 Stream 发送新的数据时,StreamBuilder 会进行重新构建。
  • initialData (T?): 在 Stream 提供数据之前用作初始数据的值。
  • builder (AsyncWidgetBuilder): 构建器函数,根据 AsyncSnapshot 状态构建小部件。这个构建器会频繁调用,所以要确保其实现高效。

示例

class StreamBuilderExample extends StatelessWidget {
  // 创建一个每秒钟发出一个整数的流
  Stream<int> _timerStream() async* {
    int counter = 0;
    while (true) {
      await Future.delayed(Duration(seconds: 1));
      yield counter++;
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('StreamBuilder 示例')),
        body: StreamBuilder<int>(
          stream: _timerStream(), // 流对象
          initialData: 0, // 初始数据
          builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return CircularProgressIndicator(); // 显示进度条
            } else if (snapshot.hasError) {
              return Text('错误: ${snapshot.error}');
            } else {
              return Text('计时器: ${snapshot.data} 秒');
            }
          },
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个 StreamBuilder 小部件,用于显示一个秒表计时器。模拟的 _timerStream 函数表示一个每秒钟发出一个整数的流,它会在每一秒钟之后发送一个递增的计数。

StreamBuilder 使用了三个主要属性:

  • stream: 指定了要监听的 Stream 对象,即 _timerStream() 方法。

  • initialData: 提供了流开始发送数据之前显示的初始数据 0。

  • builder: 一个函数,根据 AsyncSnapshot 构建不同的 UI。该函数检查 snapshot.connectionState 来决定当前的状态,并相应地显示进度条、错误信息或最新的秒表计数。
     
    使用指南

  • 初始化数据: 如果你希望在 Stream 开始发送数据之前显示某些初始数据,可以设置 initialData 属性。

  • 处理各种状态: 在 builder 函数中,你需要处理 AsyncSnapshot 的各种状态,包括 connectionState、hasData、hasError 等,以便显示适当的 UI。

  • 性能优化: 由于 builder 函数会频繁调用,因此请确保其实现足够高效。
     
    通过以上方法,StreamBuilder 能帮助你优雅地处理流数据,并根据流的最新状态动态更新界面。

 
 

CustomPaint

CustomPaint 是 Flutter 框架中用于自定义绘制的控件。它允许你在画布上绘制任意内容,可以用来实现复杂的图形和效果。

属性解析

const CustomPaint({
    super.key,
    this.painter,
    this.foregroundPainter,
    this.size = Size.zero,
    this.isComplex = false,
    this.willChange = false,
    super.child,
  })
  • painter (CustomPainter?): 绘制背景的 CustomPainter 对象。
  • foregroundPainter (CustomPainter?): 绘制前景的 CustomPainter 对象,比 painter 层级更高,会覆盖在子组件之上。
  • size (Size): 指定画布的大小,默认为 Size.zero,通常会自动调整大小以适应其子组件。
  • isComplex (bool): 提示绘制内容是否复杂。设置为 true 可以提示框架进行一些优化。
  • willChange (bool): 提示绘制内容是否会发生变化。如果设置为 true,Flutter 将不会对该区域进行缓存,以便重新绘制。

示例

class CustomPaintExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('CustomPaint 示例')),
        body: CustomPaint(
          size: Size(200, 200), // 画布的大小
          painter: MyBackgroundPainter(), // 背景画家
          foregroundPainter: MyForegroundPainter(), // 前景画家
          child: Center(
            child: Text('绘制示例'),
          ),
        ),
      ),
    );
  }
}

// 实现一个自定义画家类用于绘制背景
class MyBackgroundPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.lightBlue
      ..style = PaintingStyle.fill;

    // 绘制一个圆形
    canvas.drawCircle(Offset(size.width / 2, size.height / 2), 50, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

// 实现一个自定义画家类用于绘制前景
class MyForegroundPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 4.0;

    // 绘制一个矩形边框
    canvas.drawRect(
        Rect.fromLTWH(20, 20, size.width - 40, size.height - 40), paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

在这个示例中,我们创建了一个 CustomPaint 小部件,用于自定义绘制内容。我们定义了两个自定义画家类 MyBackgroundPainter 和 MyForegroundPainter,分别用于绘制背景和前景。

  • painter: 我们指定了 MyBackgroundPainter 用来绘制背景,它会在画布中心绘制一个蓝色填充的圆形。
  • foregroundPainter: 我们指定了 MyForegroundPainter 用来绘制前景,它会在画布上绘制一个红色的矩形边框。
  • size: 我们设置了画布的大小为 200x200。
  • child: 我们添加了一个子组件 Center(child: Text(‘绘制示例’)),它会显示在自定义绘制内容的中间。

 
使用指南

  • 创建自定义画家: 继承 CustomPainter 类,并实现 paint 方法来进行自定义绘制。
    设置 shouldRepaint: 覆盖 shouldRepaint 方法以指示何时需要重绘。通常,如果绘制内容不变,则返回 false。
  • 组合使用: 你可以同时使用 painter 和 foregroundPainter 来绘制不同层级的内容,并通过 child 添加子组件。
    通过以上方法,CustomPaint 能帮助你轻松实现复杂的自定义绘制效果。

在这里插入图片描述

 
 

Placeholder

Placeholder 是 Flutter 中用于占位的控件,通常在布局开发过程中临时使用。当你还没决定或实现具体的子控件时,可以使用 Placeholder 来占位。

属性解析

const Placeholder({
    super.key,
    this.color = const Color(0xFF455A64), // Blue Grey 700
    this.strokeWidth = 2.0,
    this.fallbackWidth = 400.0,
    this.fallbackHeight = 400.0,
    this.child
  })
  • color (Color): 占位符线条的颜色。默认值为 Color(0xFF455A64)(蓝灰色 700)。
  • strokeWidth (double): 占位符线条的宽度。默认值为 2.0。
  • fallbackWidth (double): 当没有子组件提供宽度约束时使用的默认宽度。默认值为 400.0。
  • fallbackHeight (double): 当没有子组件提供高度约束时使用的默认高度。默认值为 400.0。
  • child (Widget?): 子组件。如果提供了子组件,Placeholder 会根据子组件的大小进行调整。

示例

class WidgetPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Placeholder 示例')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              PlaceholderExample(),
              SizedBox(height: 20),
              Container(
                width: 200,
                height: 200,
                child: Placeholder(
                  color: Colors.red,
                  strokeWidth: 4.0,
                  fallbackWidth: 200.0,
                  fallbackHeight: 200.0,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class PlaceholderExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Placeholder(
      color: Colors.blue, // 设置占位符颜色
      strokeWidth: 5.0, // 设置占位符线条宽度
      fallbackWidth: 150.0, // 设置默认宽度
      fallbackHeight: 150.0, // 设置默认高度
    );
  }
}

在这个示例中,我们展示了两个 Placeholder 控件,一个通过单独的小部件类 PlaceholderExample 实现,另一个直接在布局中创建。我们演示了如何设置自定义颜色、线条宽度以及默认宽高。

  • color: 我们设置了不同的颜色,第一个 Placeholder 使用蓝色,第二个使用红色。
  • strokeWidth: 调整了线条宽度,第一个 Placeholder 的线条宽度为 5.0,第二个为 4.0。
  • fallbackWidth 和 fallbackHeight: 第一个 Placeholder 的默认宽高均为 150.0,第二个为 200.0。

 
使用指南

  • 临时占位 : 在开发布局时,使用 Placeholder 可以帮助你暂时占据空间,便于后续替换成实际的子组件。
  • 调试布局: 如果你需要查看某些区域的布局效果,但还未完成具体实现,可以使用 Placeholder。
  • 自定义样式: 通过设置 color、strokeWidth 等属性,使得 Placeholder 更加符合你的设计需求。

 
通过以上方法,Placeholder 能帮助你在开发阶段更好地构建和调试布局。
在这里插入图片描述

 
 

RepaintBoundary

RepaintBoundary 是 Flutter 中用于优化绘制性能的一个小部件。它可以创建一个新的绘制边界,使得其中的子树独立于父组件进行重绘,从而减少不必要的重绘操作,提升性能

属性解析

const RepaintBoundary({ super.key, super.child });
  • child (Widget?): 要显示在这个 RepaintBoundary 里的子组件。

示例

class WidgetPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('RepaintBoundary 示例')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              // 使用 RepaintBoundary 包裹第一个组件
              RepaintBoundary(
                child: ColoredBoxExample(color: Colors.blue),
              ),
              SizedBox(height: 20),
              // 未使用 RepaintBoundary 包裹第二个组件
              ColoredBoxExample(color: Colors.red),
            ],
          ),
        ),
      ),
    );
  }
}

class ColoredBoxExample extends StatefulWidget {
  final Color color;

  ColoredBoxExample({required this.color});

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

class _ColoredBoxExampleState extends State<ColoredBoxExample> {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 100,
      height: 100,
      color: widget.color,
      child: Center(
        child: Text(
          '色块',
          style: TextStyle(color: Colors.white),
        ),
      ),
    );
  }

  @override
  void didUpdateWidget(ColoredBoxExample oldWidget) {
    super.didUpdateWidget(oldWidget);
    print('Color Changed to ${widget.color}');
  }
}

在这里插入图片描述

在这个示例中,我们创建了两个彩色方块,一个被 RepaintBoundary 包裹,另一个没有包裹。通过比较两者的重绘行为,我们可以更好地理解 RepaintBoundary 的用途。

  • child: 我们将第一个 ColoredBoxExample 组件作为 RepaintBoundary 的子组件,以便隔离其重绘操作。
  • 无 RepaintBoundary: 第二个组件未使用 RepaintBoundary,因此如果外部布局发生变化,它也可能需要重绘。

 
使用指南

  • 优化性能: 如果某个区域的重绘代价较高且频繁,可以考虑用 RepaintBoundary 包裹,减少不必要的重绘操作。
  • 隔离复杂绘制: 对一些复杂的绘制或者动画,可以使用 RepaintBoundary 隔离开,以免影响整个界面的重绘性能。
  • 调试绘制边界: 你可以开启Flutter的调试模式并设置 debugRepaintRainbowEnabled 为 true,以可视化重绘边界并帮助调试。

 
以下是如何启用重绘边界调试:

import 'package:flutter/material.dart';

void main() {
  debugRepaintRainbowEnabled = true;
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('RepaintBoundary 示例')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              RepaintBoundary(
                child: ColoredBoxExample(color: Colors.blue),
              ),
              SizedBox(height: 20),
              ColoredBoxExample(color: Colors.red),
            ],
          ),
        ),
      ),
    );
  }
}

通过以上方法,RepaintBoundary 能帮你有效地控制和优化重绘行为,从而提升应用性能。

 
 

ClipRRect

ClipRRect 是 Flutter 中用于将子组件剪裁为圆角矩形的一个小部件。它可以对其子组件应用圆角效果,并且可以自定义圆角半径和剪裁行为

属性解析

const ClipRRect({
    super.key,
    this.borderRadius = BorderRadius.zero,
    this.clipper,
    this.clipBehavior = Clip.antiAlias,
    super.child,
  })
  • borderRadius (BorderRadius): 圆角的半径,可以通过 BorderRadius.circular(double radius) 等方式来设置。默认为 BorderRadius.zero,即无圆角。
  • clipper (CustomClipper?): 自定义的剪裁器,如果提供了 clipper,则使用该剪裁器来决定如何剪裁。
  • clipBehavior (Clip): 剪裁行为,控制剪裁的抗锯齿效果等。默认为 Clip.antiAlias。
  • child (Widget?): 要显示在这个 ClipRRect 里的子组件。

示例

class WidgetPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('ClipRRect 示例')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              ClipRRectExample(),
              SizedBox(height: 20),
              ClipRRect(
                borderRadius: BorderRadius.circular(30), // 设置圆角半径
                clipBehavior: Clip.antiAlias, // 设置剪裁行为
                child: Container(
                  width: 150,
                  height: 150,
                  color: Colors.blue,
                  child: Center(
                    child: Text(
                      '圆角矩形',
                      style: TextStyle(color: Colors.white),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class ClipRRectExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ClipRRect(
      borderRadius: BorderRadius.circular(20), // 设置圆角半径
      clipBehavior: Clip.hardEdge, // 设置剪裁行为
      child: Image.network(
        'https://via.placeholder.com/150',
        width: 150,
        height: 150,
        fit: BoxFit.cover,
      ),
    );
  }
}

在这里插入图片描述

在这个示例中,我们展示了两个 ClipRRect 小部件,一个用于显示圆角图像,另一个用于显示带圆角的文本容器。

  • borderRadius: 我们分别设置了不同的圆角半径,第一个 ClipRRect 的半径为 20.0,第二个为 10.0。
  • clipBehavior: 我们将 clipBehavior 设置为 Clip.antiAlias,以启用抗锯齿效果,使得圆角边缘更加平滑。
  • child: 第一个 ClipRRect 包裹了一张网络图像,第二个包裹了一个带背景颜色和内边距的文本容器。

 
使用指南

  • 创建圆角效果: 当你需要创建带圆角的图像或其他组件时,可以使用 ClipRRect 并设置合适的 borderRadius。
  • 自定义裁剪: 如果你需要更复杂的裁剪行为,可以提供一个自定义的 clipper 来控制裁剪区域。
  • 优化性能: 根据具体需求选择合适的 clipBehavior,例如 Clip.none 可以跳过裁剪以提升性能,但需要确保内容不会超出边界。

 
使用自定义 Clipper

下面展示如何使用自定义 CustomClipper 来裁剪一个不规则的形状:

class WidgetPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('ClipRRect 自定义 Clipper 示例')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              // 使用 ClipRRect 和自定义 Clipper 裁剪图像
              ClipRRect(
                clipper: MyCustomClipper(), // 使用自定义 Clipper
                child: Image.network(
                  'https://via.placeholder.com/150',
                  width: 150,
                  height: 150,
                  fit: BoxFit.cover,
                ),
              ),
              SizedBox(height: 20),
            ],
          ),
        ),
      ),
    );
  }
}

class MyCustomClipper extends CustomClipper<RRect> {
  @override
  RRect getClip(Size size) {
    return RRect.fromRectAndCorners(
      Rect.fromLTWH(0, 0, size.width, size.height),
      topLeft: Radius.circular(30),
      topRight: Radius.circular(30),
      bottomLeft: Radius.circular(10),
      bottomRight: Radius.circular(50),
    );
  }

  @override
  bool shouldReclip(CustomClipper<RRect> oldClipper) {
    return false;
  }
}

在这里插入图片描述

 
 

ClipOval

ClipOval 是 Flutter 中用于将子组件裁剪成椭圆或圆形状的小部件。它通常用于创建圆形头像、按钮或其他需要圆形/椭圆形效果的组件

属性解析

 const ClipOval({
    super.key,
    this.clipper,
    this.clipBehavior = Clip.antiAlias,
    super.child,
  })
  • clipper (CustomClipper ?): 自定义的裁剪行为。如果提供,它会覆盖默认的椭圆裁剪行为。
  • clipBehavior (Clip): 裁剪行为,默认为 Clip.antiAlias,可以选择是否启用抗锯齿等。
  • child (Widget?): 要显示在这个 ClipOval 里的子组件。

示例

class WidgetPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('ClipOval 示例')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              // 使用 ClipOval 包裹图像
              ClipOval(
                clipBehavior: Clip.antiAlias, // 设置裁剪行为
                child: Image.network(
                  'https://via.placeholder.com/150',
                  width: 150,
                  height: 150,
                  fit: BoxFit.cover,
                ),
              ),
              SizedBox(height: 20),
              // 使用 ClipOval 包裹文本
              ClipOval(
                clipBehavior: Clip.antiAlias, // 设置裁剪行为
                child: Container(
                  color: Colors.blue,
                  padding: EdgeInsets.all(16.0),
                  child: Text(
                    '圆形容器',
                    style: TextStyle(color: Colors.white),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

在这里插入图片描述
在这个示例中,我们展示了两个 ClipOval 小部件,一个用于显示圆形图像,另一个用于显示带背景颜色和内边距的圆形文本容器。

  • clipBehavior: 我们将 clipBehavior 设置为 Clip.antiAlias,以启用抗锯齿效果,使得圆形边缘更加平滑。

  • child: 第一个 ClipOval 包裹了一张网络图像,第二个包裹了一个带背景颜色和内边距的文本容器。
     
    使用指南

  • 创建圆形效果: 当你需要创建圆形的图像或其他组件时,可以使用 ClipOval 来实现。

  • **自定义裁剪: 如果你需要椭圆形或更复杂的裁剪行为,可以提供一个自定义的 clipper 来控制裁剪区域。

  • 优化性能: 根据具体需求选择合适的 clipBehavior,例如 Clip.none 可以跳过裁剪以提升性能,但需要确保内容不会超出边界。
     
    使用自定义 Clipper

下面展示如何使用自定义 CustomClipper 来裁剪一个不规则的形状:

class WidgetPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('ClipOval 自定义 Clipper 示例')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              // 使用 ClipOval 和自定义 Clipper 裁剪图像
              ClipOval(
                clipper: MyCustomClipper(), // 使用自定义 Clipper
                child: Image.network(
                  'https://via.placeholder.com/150',
                  width: 150,
                  height: 150,
                  fit: BoxFit.cover,
                ),
              ),
              SizedBox(height: 20),
            ],
          ),
        ),
      ),
    );
  }
}

class MyCustomClipper extends CustomClipper<Rect> {
  @override
  Rect getClip(Size size) {
    return Rect.fromLTWH(0, 0, size.width * 0.8, size.height); // 自定义矩形
  }

  @override
  bool shouldReclip(CustomClipper<Rect> oldClipper) {
    return false;
  }
}

在这里插入图片描述

 
 

ClipPath: 自定义路径裁剪,用于根据任意路径裁剪子组件。

ClipPath 是 Flutter 中用于根据自定义路径裁剪子组件的小部件。它允许你创建任意形状的裁剪效果,通过提供一个自定义的 CustomClipper 来定义裁剪路径

属性解析

 const ClipPath({
    super.key,
    this.clipper,
    this.clipBehavior = Clip.antiAlias,
    super.child,
  })
  • clipper (CustomClipper ?): 自定义的裁剪器,用于定义裁剪路径。
  • clipBehavior (Clip): 裁剪行为,默认为 Clip.antiAlias,可以选择是否启用抗锯齿等。
  • child (Widget?): 要显示在这个 ClipPath 里的子组件。

示例


class WidgetPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('ClipPath 示例')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              // 使用 ClipPath 和自定义 Clipper 裁剪图像
              ClipPath(
                clipper: StarClipper(), // 使用自定义 Clipper
                clipBehavior: Clip.antiAlias, // 设置裁剪行为
                child: Image.network(
                  'https://via.placeholder.com/150',
                  width: 150,
                  height: 150,
                  fit: BoxFit.cover,
                ),
              ),
              SizedBox(height: 20),
              // 使用 ClipPath 和自定义 Clipper 裁剪文本容器
              ClipPath(
                clipper: WaveClipper(), // 使用自定义 Clipper
                clipBehavior: Clip.antiAlias, // 设置裁剪行为
                child: Container(
                  color: Colors.blue,
                  padding: EdgeInsets.all(16.0),
                  child: Text(
                    '波浪形状容器',
                    style: TextStyle(color: Colors.white),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

// 创建一个星形的Clipper
class StarClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    final path = Path();
    double x = size.width / 2;
    double y = size.height / 2;
    double radius = size.width / 2;

    for (int i = 0; i < 5; i++) {
      path.lineTo(
        x + radius * Math.cos((18 + i * 72) * Math.pi / 180),
        y - radius * Math.sin((18 + i * 72) * Math.pi / 180),
      );
      path.lineTo(
        x + radius / 2.5 * Math.cos((54 + i * 72) * Math.pi / 180),
        y - radius / 2.5 * Math.sin((54 + i * 72) * Math.pi / 180),
      );
    }
    path.close();
    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) {
    return false;
  }
}

// 创建一个波浪形的Clipper
class WaveClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    final path = Path();
    path.lineTo(0, size.height); // Start at bottom left
    path.quadraticBezierTo(
        size.width / 4, size.height - 40, size.width / 2, size.height);
    path.quadraticBezierTo(
        size.width * 3 / 4, size.height + 40, size.width, size.height);
    path.lineTo(size.width, 0); // Top right
    path.close();
    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) {
    return false;
  }
}

在这里插入图片描述
在这个示例中,我们展示了两个 ClipPath 小部件,一个用于创建星形裁剪效果,另一个用于创建波浪形裁剪效果。

  • clipper: 我们分别创建了两个 CustomClipper 子类 StarClipper 和 WaveClipper,用于定义星形和波浪形的裁剪路径。
  • clipBehavior: 我们将 clipBehavior 设置为 Clip.antiAlias,以启用抗锯齿效果,使得裁剪边缘更加平滑。
  • child: 第一个 ClipPath 包裹了一张网络图像,第二个包裹了一个带背景颜色和内边距的文本容器。

 
使用指南

  • 创建自定义形状: 当你需要创建任意形状的裁剪效果时,可以使用 ClipPath 并提供一个自定义的 CustomClipper
  • 实现复杂裁剪: 通过自定义 clipper,你可以实现非常复杂和灵活的裁剪形状,以满足不同的设计需求。
  • 优化性能: 根据具体需求选择合适的 clipBehavior,例如 Clip.none 可以跳过裁剪以提升性能,但需要确保内容不会超出边界。
     
     
  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值