Flutter 裁剪类组件 最全总结

前端之家收集整理的这篇文章主要介绍了Flutter 裁剪类组件 最全总结前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

注意:无特殊说明,Flutter版本及Dart版本如下:

  • Flutter版本: 1.12.13+hotfix.5
  • Dart版本: 2.7.0

ClipRect

ClipRect组件使用矩形裁剪子组件,通常情况下,ClipRect作用于CustomPaintCustomSingleChildLayoutCustomMultiChildLayoutAlignCenterOverflowBoxSizedOverflowBox组件,例如ClipRect作用于Align,可以仅显示上半部分,代码如下:

  1. ClipRect(
  2. child: Align(
  3. alignment: Alignment.topCenter,heightFactor: 0.5,child: Container(
  4. height: 150,width: 150,child: Image.asset(
  5. 'images/1.png',fit: BoxFit.cover,),)

全图效果

裁剪效果

clipper参数定义裁剪规则,下面具体介绍。

clipBehavior参数定义了裁剪的方式,只有子控件超出父控件的范围才有裁剪的说法,各个方式说明如下:

  • none:不裁剪,系统默认值,如果子组件不超出边界,此值没有任何性能消耗。
  • hardEdge:裁剪但不应用抗锯齿,速度比none慢一点,但比其他方式快。
  • antiAlias:裁剪而且抗锯齿,此方式看起来更平滑,比antiAliasWithSaveLayer快,比hardEdge慢,通常用于处理圆形和弧形裁剪。
  • antiAliasWithSaveLayer:裁剪、抗锯齿而且有一个缓冲区,此方式很慢,用到的情况比较少。

ClipRRect

ClipRRect组件可以对子组件进行圆角裁剪,默认圆角半径为0,注意ClipRRect有2个R,不是上面介绍的ClipRect。

用法如下:

  1. ClipRRect(
  2. borderRadius: BorderRadius.circular(20),child: Container(
  3. height: 150,child: Image.asset(
  4. 'images/1.png',)

效果如图:

ClipOval

ClipOval裁剪为椭圆形,椭圆形的大小为正切父组件,因此如果父组件为正方形,切出来是圆形,用法如下:

  1. ClipOval(
  2. child: Container(
  3. height: 150,width: 250,)

效果如下:

ClipPath

ClipPath组件根据路径进行裁剪,我们自定义裁剪路径也可以使用系统提供的,用法如下:

  1. ClipPath.shape(
  2. shape: StadiumBorder(),)

shape参数是ShapeBorder类型,系统已经定义了很多形状,介绍如下:

  • RoundedRectangleBorder:圆角矩形

  • ContinuousRectangleBorder:直线和圆角平滑连续的过渡,和RoundedRectangleBorder相比,圆角效果会小一些。

  • StadiumBorder:类似于足球场的形状,两端半圆。

  • BeveledRectangleBorder:斜角矩形。效果如图:

  • CircleBorder:圆形。

CustomClipper

CustomClipper并不是一个组件,而是一个abstract(抽象)类,使用CustomClipper可以绘制出任何我们想要的形状,比如三角形,代码如下:

  1. @override
  2. Widget build(BuildContext context) {
  3. return Center(
  4. child: ClipPath(
  5. clipper: TrianglePath(),child: Container(
  6. height: 150,child: Image.asset(
  7. 'images/1.png',);
  8. }

自定义TrianglePath代码如下:

  1. class TrianglePath extends CustomClipper<Path>{
  2. @override
  3. Path getClip(Size size) {
  4. var path = Path();
  5. path.moveTo(size.width/2,0);
  6. path.lineTo(0,size.height);
  7. path.lineTo(size.width,size.height);
  8. return path;
  9. }
  10. @override
  11. bool shouldReclip(CustomClipper<Path> oldClipper) {
  12. return true;
  13. }
  14. }

效果如下:

我们还可以绘制五角星,代码如下:

  1. class StarPath extends CustomClipper<Path> {
  2. StarPath({this.scale = 2.5});
  3. final double scale;
  4. double perDegree = 36;
  5. /// 角度转弧度公式
  6. double degree2Radian(double degree) {
  7. return (pi * degree / 180);
  8. }
  9. @override
  10. Path getClip(Size size) {
  11. var R = min(size.width / 2,size.height / 2);
  12. var r = R / scale;
  13. var x = size.width / 2;
  14. var y = size.height / 2;
  15. var path = Path();
  16. path.moveTo(x,y - R);
  17. path.lineTo(x - sin(degree2Radian(perDegree)) * r,y - cos(degree2Radian(perDegree)) * r);
  18. path.lineTo(x - sin(degree2Radian(perDegree * 2)) * R,y - cos(degree2Radian(perDegree * 2)) * R);
  19. path.lineTo(x - sin(degree2Radian(perDegree * 3)) * r,y - cos(degree2Radian(perDegree * 3)) * r);
  20. path.lineTo(x - sin(degree2Radian(perDegree * 4)) * R,y - cos(degree2Radian(perDegree * 4)) * R);
  21. path.lineTo(x - sin(degree2Radian(perDegree * 5)) * r,y - cos(degree2Radian(perDegree * 5)) * r);
  22. path.lineTo(x - sin(degree2Radian(perDegree * 6)) * R,y - cos(degree2Radian(perDegree * 6)) * R);
  23. path.lineTo(x - sin(degree2Radian(perDegree * 7)) * r,y - cos(degree2Radian(perDegree * 7)) * r);
  24. path.lineTo(x - sin(degree2Radian(perDegree * 8)) * R,y - cos(degree2Radian(perDegree * 8)) * R);
  25. path.lineTo(x - sin(degree2Radian(perDegree * 9)) * r,y - cos(degree2Radian(perDegree * 9)) * r);
  26. path.lineTo(x - sin(degree2Radian(perDegree * 10)) * R,y - cos(degree2Radian(perDegree * 10)) * R);
  27. return path;
  28. }
  29. @override
  30. bool shouldReclip(StarPath oldClipper) {
  31. return oldClipper.scale != this.scale;
  32. }
  33. }

scale参数表示间隔的点到圆心的缩放比例,五角星效果如下:

下面用动画动态设置scale代码如下:

  1. class StartClip extends StatefulWidget {
  2. @override
  3. State<StatefulWidget> createState() => _StartClipState();
  4. }
  5. class _StartClipState extends State<StartClip>
  6. with SingleTickerProviderStateMixin {
  7. AnimationController _controller;
  8. Animation _animation;
  9. @override
  10. void initState() {
  11. _controller =
  12. AnimationController(duration: Duration(seconds: 2),vsync: this)
  13. ..addStatusListener((status) {
  14. if (status == AnimationStatus.completed) {
  15. _controller.reverse();
  16. } else if (status == AnimationStatus.dismissed) {
  17. _controller.forward();
  18. }
  19. });
  20. _animation = Tween(begin: 1.0,end: 4.0).animate(_controller);
  21. _controller.forward();
  22. super.initState();
  23. }
  24. @override
  25. Widget build(BuildContext context) {
  26. return Center(
  27. child: AnimatedBuilder(
  28. animation: _animation,builder: (context,child) {
  29. return ClipPath(
  30. clipper: StarPath(scale: _animation.value),child: Container(
  31. height: 150,color: Colors.red,);
  32. }),);
  33. }
  34. }

效果如下:

今天的文章对大家是否有帮助?如果有,请在文章底部留言和点赞,你们的留言、点赞和转发关注是我持续更新的动力!

欢迎您的加入Flutter的微信交流群(mqd_zzy),欢迎您的加入,让我们一起学习,一起进步,开始我们的故事,生活不止眼前的苟且,还有诗和《远方》。

当然我也非常希望您关注我个人的公众号,里面有各种福利等着大家哦。

更多相关阅读:

猜你在找的Flutter相关文章