【Flutter 实战】各类各样形状的组件


老孟导读:Flutter中不少组件都有一个叫作shape的属性,类型是ShapeBorder,好比Button类、Card等组件,shape表示控件的形状,系统已经为咱们提供了不少形状,对于没有此属性的组件,可使用 Clip 类组件进行裁减。web

BeveledRectangleBorder

斜角矩形边框,用法以下:微信

RaisedButton( shape: BeveledRectangleBorder( side: BorderSide(width: 1, color: Colors.red), borderRadius: BorderRadius.circular(10)), child: Text('老孟'), onPressed: () {},)
image-20200522172909192

若是设置的半径比控件还大,就会变成菱形编辑器

 3RaisedButton( shape: BeveledRectangleBorder( side: BorderSide(width: 1, color: Colors.red), borderRadius: BorderRadius.circular(100)), child: Text('老孟'), onPressed: () {},)
image-20200522173147073

同理,若是半径设置为0,就是矩形。ide

RaisedButton( shape: BeveledRectangleBorder( side: BorderSide(width: 1, color: Colors.red), borderRadius: BorderRadius.circular(0)), child: Text('老孟'), onPressed: () {},)
image-20200522173458904

Border

Border容许单独设置每个边上的线条样式.布局

RaisedButton( shape: Border( top: BorderSide(color: Colors.red,width: 2) ), child: Text('老孟'), onPressed: () {},)
image-20200522173801387

设置所有性能

RaisedButton( shape: Border( top: BorderSide(color: Colors.red,width: 10), right: BorderSide(color: Colors.blue,width: 10), bottom: BorderSide(color: Colors.yellow,width: 10), left: BorderSide(color: Colors.green,width: 10), ), child: Text('老孟'), onPressed: () {}, )
image-20200522182443777

BorderDirectional

BorderDirectionalBorder基本同样,区别就是BorderDirectional带有阅读方向,大部分国家阅读是从左到右,但有的国家是从右到左的,好比阿拉伯等。flex

RaisedButton( shape: BorderDirectional( start: BorderSide(color: Colors.red,width: 2), end: BorderSide(color: Colors.blue,width: 2), ), child: Text('老孟'), onPressed: () {},)
image-20200522182150780

CircleBorder

圆形动画

RaisedButton( shape: CircleBorder(side: BorderSide(color: Colors.red)), child: Text('老孟'), onPressed: () {},)
image-20200522182549205

ContinuousRectangleBorder

连续的圆角矩形,直线和圆角平滑连续的过渡,和RoundedRectangleBorder相比,圆角效果会小一些。ui

RaisedButton( shape: ContinuousRectangleBorder( side: BorderSide(color: Colors.red), borderRadius: BorderRadius.circular(20)), child: Text('老孟'), onPressed: () {},)
image-20200522182922984

RoundedRectangleBorder

圆角矩形this

RaisedButton( shape: RoundedRectangleBorder( side: BorderSide(color: Colors.red), borderRadius: BorderRadius.circular(10)), child: Text('老孟'), onPressed: () {},)
image-20200522183032650

StadiumBorder

相似足球场的形状,两边圆形,中间矩形

RaisedButton( shape: StadiumBorder( side: BorderSide(color: Colors.red),), child: Text('老孟'), onPressed: () {},)
image-20200522183814823

OutlineInputBorder

带外边框

RaisedButton( shape: OutlineInputBorder( borderSide: BorderSide(color: Colors.red), borderRadius: BorderRadius.circular(10), ), child: Text('老孟'), onPressed: () {},)
image-20200522184044810

UnderlineInputBorder

下划线边框

RaisedButton( shape: UnderlineInputBorder( borderSide: BorderSide(color: Colors.red), ), child: Text('老孟'), onPressed: () {},)
image-20200522184216659

ClipRect

ClipRect组件使用矩形裁剪子组件,一般状况下,ClipRect做用于CustomPaintCustomSingleChildLayoutCustomMultiChildLayoutAlignCenterOverflowBoxSizedOverflowBox组件,例如ClipRect做用于Align,能够仅显示上半部分,代码以下:

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参数定义了裁剪的方式,只有子控件超出父控件的范围才有裁剪的说法,各个方式说明以下:

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

ClipRRect

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

用法以下:

ClipRRect( borderRadius: BorderRadius.circular(20), child: Container( height: 150, width: 150, child: Image.asset( 'images/1.png', fit: BoxFit.cover, ), ),)

效果如图:

ClipOval

ClipOval裁剪为椭圆形,椭圆形的大小为正切父组件,所以若是父组件为正方形,切出来是圆形,用法以下:

ClipOval( child: Container( height: 150, width: 250, child: Image.asset( 'images/1.png', fit: BoxFit.cover, ), ),)

效果以下:

ClipPath

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:斜角矩形。效果如图:

  • CircleBorder:圆形。

CustomClipper

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

@overrideWidget 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」
让你天天进步一点点


本文分享自微信公众号 - 老孟Flutter(lao_meng_qd)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索