注意:无特殊说明,Flutter版本及Dart版本以下:微信
- Flutter版本: 1.12.13+hotfix.5
- Dart版本: 2.7.0
ClipRect组件使用矩形裁剪子组件,一般状况下,ClipRect做用于CustomPaint
、 CustomSingleChildLayout
、 CustomMultiChildLayout
、 Align
、 Center
、 OverflowBox
、 SizedOverflowBox
组件,例如ClipRect做用于Align,能够仅显示上半部分,代码以下:ide
ClipRect( child: Align( alignment: Alignment.topCenter, heightFactor: 0.5, child: Container( height: 150, width: 150, child: Image.asset( 'images/1.png', fit: BoxFit.cover, ), ), ), )
全图效果:性能
裁剪效果:学习
clipper
参数定义裁剪规则,下面具体介绍。动画
clipBehavior
参数定义了裁剪的方式,只有子控件超出父控件的范围才有裁剪的说法,各个方式说明以下:ui
none
慢一点,但比其余方式快。antiAliasWithSaveLayer
快,比hardEdge
慢,一般用于处理圆形和弧形裁剪。ClipRRect组件能够对子组件进行圆角裁剪,默认圆角半径为0,注意ClipRRect有2个R,不是上面介绍的ClipRect。this
用法以下:.net
ClipRRect( borderRadius: BorderRadius.circular(20), child: Container( height: 150, width: 150, child: Image.asset( 'images/1.png', fit: BoxFit.cover, ), ), )
效果如图:code
ClipOval裁剪为椭圆形,椭圆形的大小为正切父组件,所以若是父组件为正方形,切出来是圆形,用法以下:blog
ClipOval( child: Container( height: 150, width: 250, child: Image.asset( 'images/1.png', fit: BoxFit.cover, ), ), )
效果以下:
ClipPath组件根据路径进行裁剪,咱们自定义裁剪路径也可使用系统提供的,用法以下:
ClipPath.shape( shape: StadiumBorder(), child: Container( height: 150, width: 250, child: Image.asset( 'images/1.png', fit: BoxFit.cover, ), ), )
shape
参数是ShapeBorder类型,系统已经定义了不少形状,介绍以下:
RoundedRectangleBorder:圆角矩形
ContinuousRectangleBorder:直线和圆角平滑连续的过渡,和RoundedRectangleBorder相比,圆角效果会小一些。
StadiumBorder:相似于足球场的形状,两端半圆。
BeveledRectangleBorder:斜角矩形。效果如图:
CustomClipper并非一个组件,而是一个abstract
(抽象)类,使用CustomClipper能够绘制出任何咱们想要的形状,好比三角形,代码以下:
@override Widget build(BuildContext context) { return Center( child: ClipPath( clipper: TrianglePath(), child: Container( height: 150, width: 250, child: Image.asset( 'images/1.png', fit: BoxFit.cover, ), ), ), ); }
自定义TrianglePath代码以下:
class TrianglePath extends CustomClipper<Path>{ @override Path getClip(Size size) { var path = Path(); path.moveTo(size.width/2, 0); path.lineTo(0, size.height); path.lineTo(size.width, size.height); return path; } @override bool shouldReclip(CustomClipper<Path> oldClipper) { return true; } }
效果以下:
咱们还能够绘制五角星,代码以下:
class StarPath extends CustomClipper<Path> { StarPath({this.scale = 2.5}); final double scale; double perDegree = 36; /// 角度转弧度公式 double degree2Radian(double degree) { return (pi * degree / 180); } @override Path getClip(Size size) { var R = min(size.width / 2, size.height / 2); var r = R / scale; var x = size.width / 2; var y = size.height / 2; var path = Path(); path.moveTo(x, y - R); path.lineTo(x - sin(degree2Radian(perDegree)) * r, y - cos(degree2Radian(perDegree)) * r); path.lineTo(x - sin(degree2Radian(perDegree * 2)) * R, y - cos(degree2Radian(perDegree * 2)) * R); path.lineTo(x - sin(degree2Radian(perDegree * 3)) * r, y - cos(degree2Radian(perDegree * 3)) * r); path.lineTo(x - sin(degree2Radian(perDegree * 4)) * R, y - cos(degree2Radian(perDegree * 4)) * R); path.lineTo(x - sin(degree2Radian(perDegree * 5)) * r, y - cos(degree2Radian(perDegree * 5)) * r); path.lineTo(x - sin(degree2Radian(perDegree * 6)) * R, y - cos(degree2Radian(perDegree * 6)) * R); path.lineTo(x - sin(degree2Radian(perDegree * 7)) * r, y - cos(degree2Radian(perDegree * 7)) * r); path.lineTo(x - sin(degree2Radian(perDegree * 8)) * R, y - cos(degree2Radian(perDegree * 8)) * R); path.lineTo(x - sin(degree2Radian(perDegree * 9)) * r, y - cos(degree2Radian(perDegree * 9)) * r); path.lineTo(x - sin(degree2Radian(perDegree * 10)) * R, y - cos(degree2Radian(perDegree * 10)) * R); return path; } @override bool shouldReclip(StarPath oldClipper) { return oldClipper.scale != this.scale; } }
scale
参数表示间隔的点到圆心的缩放比例,五角星效果以下:
下面用动画动态设置scale
,代码以下:
class StartClip extends StatefulWidget { @override State<StatefulWidget> createState() => _StartClipState(); } class _StartClipState extends State<StartClip> with SingleTickerProviderStateMixin { AnimationController _controller; Animation _animation; @override void initState() { _controller = AnimationController(duration: Duration(seconds: 2), vsync: this) ..addStatusListener((status) { if (status == AnimationStatus.completed) { _controller.reverse(); } else if (status == AnimationStatus.dismissed) { _controller.forward(); } }); _animation = Tween(begin: 1.0, end: 4.0).animate(_controller); _controller.forward(); super.initState(); } @override Widget build(BuildContext context) { return Center( child: AnimatedBuilder( animation: _animation, builder: (context, child) { return ClipPath( clipper: StarPath(scale: _animation.value), child: Container( height: 150, width: 150, color: Colors.red, ), ); }), ); } }
效果以下:
今天的文章对你们是否有帮助?若是有,请在文章底部留言和点赞,大家的留言、点赞和转发关注是我持续更新的动力!
欢迎您的加入Flutter的微信交流群(<font color='red'>mqd_zzy</font>),欢迎您的加入,让咱们一块儿学习,一块儿进步,开始咱们的故事,生活不止眼前的苟且,还有诗和《远方》。
固然我也很是但愿您关注我我的的公众号,里面有各类福利等着你们哦。