老孟導讀: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: () {},)
若是設置的半徑比控件還大,就會變成菱形:編輯器
3RaisedButton( shape: BeveledRectangleBorder( side: BorderSide(width: 1, color: Colors.red), borderRadius: BorderRadius.circular(100)), child: Text('老孟'), onPressed: () {},)
同理,若是半徑設置爲0,就是矩形。ide
RaisedButton( shape: BeveledRectangleBorder( side: BorderSide(width: 1, color: Colors.red), borderRadius: BorderRadius.circular(0)), child: Text('老孟'), onPressed: () {},)
Border
Border容許單獨設置每個邊上的線條樣式.佈局
RaisedButton( shape: Border( top: BorderSide(color: Colors.red,width: 2) ), child: Text('老孟'), onPressed: () {},)
設置所有性能
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: () {}, )
BorderDirectional
BorderDirectional和Border基本同樣,區別就是BorderDirectional帶有閱讀方向,大部分國家閱讀是從左到右,但有的國家是從右到左的,好比阿拉伯等。flex
RaisedButton( shape: BorderDirectional( start: BorderSide(color: Colors.red,width: 2), end: BorderSide(color: Colors.blue,width: 2), ), child: Text('老孟'), onPressed: () {},)
CircleBorder
圓形動畫
RaisedButton( shape: CircleBorder(side: BorderSide(color: Colors.red)), child: Text('老孟'), onPressed: () {},)
ContinuousRectangleBorder
連續的圓角矩形,直線和圓角平滑連續的過渡,和RoundedRectangleBorder相比,圓角效果會小一些。ui
RaisedButton( shape: ContinuousRectangleBorder( side: BorderSide(color: Colors.red), borderRadius: BorderRadius.circular(20)), child: Text('老孟'), onPressed: () {},)
RoundedRectangleBorder
圓角矩形this
RaisedButton( shape: RoundedRectangleBorder( side: BorderSide(color: Colors.red), borderRadius: BorderRadius.circular(10)), child: Text('老孟'), onPressed: () {},)
StadiumBorder
相似足球場的形狀,兩邊圓形,中間矩形
RaisedButton( shape: StadiumBorder( side: BorderSide(color: Colors.red),), child: Text('老孟'), onPressed: () {},)
OutlineInputBorder
帶外邊框
RaisedButton( shape: OutlineInputBorder( borderSide: BorderSide(color: Colors.red), borderRadius: BorderRadius.circular(10), ), child: Text('老孟'), onPressed: () {},)
UnderlineInputBorder
下劃線邊框
RaisedButton( shape: UnderlineInputBorder( borderSide: BorderSide(color: Colors.red), ), child: Text('老孟'), onPressed: () {},)
ClipRect
ClipRect組件使用矩形裁剪子組件,一般狀況下,ClipRect做用於CustomPaint
、 CustomSingleChildLayout
、 CustomMultiChildLayout
、 Align
、 Center
、 OverflowBox
、 SizedOverflowBox
組件,例如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(lao_meng_qd)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。