效果图
一般实现方式
- ClipPath
- CustomClipper
贝塞尔曲线
/// 一般的方式class OldMyWidget extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("ClipRRect Demo")),body: Center(// 这里使用 ClipPathchild: ClipPath(clipper:ClipperPath(),child: Container(width: 400,height: 200,color: Colors.blue,alignment: Alignment.center,child: Text('Flutter\n\nClipRRect',textAlign: TextAlign.center,),),),),);}}/// 创建剪裁路径class ClipperPath extends CustomClipper<Path> {@overridePath getClip(Size size) {var path = Path();path.lineTo(0.0, size.height - 50);var firstControlPoint = Offset(size.width / 4, size.height);var firstPoint = Offset(size.width / 2, size.height);path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,firstPoint.dx, firstPoint.dy);var secondControlPoint = Offset(size.width - (size.width / 4), size.height);var secondPoint = Offset(size.width, size.height - 50);path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,secondPoint.dx, secondPoint.dy);path.lineTo(size.width, 0.0);path.close();return path;}@overridebool shouldReclip(CustomClipper<Path> oldClipper) => false;}
效果
简单的实现方式
ClipRRect
- BorderRadius ```dart
class MyWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(“ClipRRect Demo”)), body: Center( /// 这里使用 ClipRRect child: ClipRRect( /// 设置剪裁半径 /// 顶部是 10 圆形 /// 底部是 x:200 和 y:50 半径的椭圆 borderRadius: BorderRadius.vertical( top: Radius.circular(10), bottom: Radius.elliptical(200, 50), ), child: Container( width: 400, height: 200, color: Colors.blue, alignment: Alignment.center, child: Text( ‘Flutter\n\nClipRRect’, textAlign: TextAlign.center, ), ), ), ), ); } } ```
效果
在线查看效果
- https://dartpad.cn/6cc7f861940123eb0ffa3ab19e3349b0?null_safety=true
总结
虽然两种方式都可以实现想要的效果,但是从代码量上有非常大的差别,后者清晰明了,不用过多的封装,前者控制点自由,样式可以更多,但是需要编写许多的计算逻辑和封装才可以。
语雀内容
