老孟導(dǎo)讀:Flutter中很多組件都有一個(gè)叫做
shape
的屬性蜈敢,類型是ShapeBorder
羞酗,比如Button類、Card等組件核行,shape
表示控件的形狀,系統(tǒng)已經(jīng)為我們提供了很多形狀蹬耘,對于沒有此屬性的組件芝雪,可以使用 Clip 類組件進(jìn)行裁減。
BeveledRectangleBorder
斜角矩形邊框综苔,用法如下:
RaisedButton(
shape: BeveledRectangleBorder(
side: BorderSide(width: 1, color: Colors.red),
borderRadius: BorderRadius.circular(10)),
child: Text('老孟'),
onPressed: () {},
)
如果設(shè)置的半徑比控件還大惩系,就會變成菱形:
3RaisedButton(
shape: BeveledRectangleBorder(
side: BorderSide(width: 1, color: Colors.red),
borderRadius: BorderRadius.circular(100)),
child: Text('老孟'),
onPressed: () {},
)
同理位岔,如果半徑設(shè)置為0,就是矩形堡牡。
RaisedButton(
shape: BeveledRectangleBorder(
side: BorderSide(width: 1, color: Colors.red),
borderRadius: BorderRadius.circular(0)),
child: Text('老孟'),
onPressed: () {},
)
Border
Border允許單獨(dú)設(shè)置每一個(gè)邊上的線條樣式.
RaisedButton(
shape: Border(
top: BorderSide(color: Colors.red,width: 2)
),
child: Text('老孟'),
onPressed: () {},
)
設(shè)置全部
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基本一樣抒抬,區(qū)別就是BorderDirectional帶有閱讀方向,大部分國家閱讀是從左到右晤柄,但有的國家是從右到左的擦剑,比如阿拉伯等。
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
連續(xù)的圓角矩形芥颈,直線和圓角平滑連續(xù)的過渡惠勒,和RoundedRectangleBorder相比裸弦,圓角效果會小一些窿春。
RaisedButton(
shape: ContinuousRectangleBorder(
side: BorderSide(color: Colors.red),
borderRadius: BorderRadius.circular(20)),
child: Text('老孟'),
onPressed: () {},
)
RoundedRectangleBorder
圓角矩形
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,
),
),
),
)
全圖效果:
<img src="https://img-blog.csdnimg.cn/20200324160500474.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrczE5ODc=,size_16,color_FFFFFF,t_70" style="zoom:50%;" />
裁剪效果:
<img src="https://img-blog.csdnimg.cn/20200324160537832.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrczE5ODc=,size_16,color_FFFFFF,t_70" style="zoom:50%;" />
clipper
參數(shù)定義裁剪規(guī)則献丑,下面具體介紹。
clipBehavior
參數(shù)定義了裁剪的方式侠姑,只有子控件超出父控件的范圍才有裁剪的說法创橄,各個(gè)方式說明如下:
- none:不裁剪,系統(tǒng)默認(rèn)值莽红,如果子組件不超出邊界妥畏,此值沒有任何性能消耗。
- hardEdge:裁剪但不應(yīng)用抗鋸齒安吁,速度比
none
慢一點(diǎn)醉蚁,但比其他方式快。 - antiAlias:裁剪而且抗鋸齒鬼店,此方式看起來更平滑网棍,比
antiAliasWithSaveLayer
快,比hardEdge
慢妇智,通常用于處理圓形和弧形裁剪滥玷。 - antiAliasWithSaveLayer:裁剪捌锭、抗鋸齒而且有一個(gè)緩沖區(qū),此方式很慢罗捎,用到的情況比較少观谦。
ClipRRect
ClipRRect組件可以對子組件進(jìn)行圓角裁剪,默認(rèn)圓角半徑為0桨菜,注意ClipRRect有2個(gè)R豁状,不是上面介紹的ClipRect。
用法如下:
ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Container(
height: 150,
width: 150,
child: Image.asset(
'images/1.png',
fit: BoxFit.cover,
),
),
)
效果如圖:
<img src="https://img-blog.csdnimg.cn/20200324160615913.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrczE5ODc=,size_16,color_FFFFFF,t_70" style="zoom:50%;" />
ClipOval
ClipOval裁剪為橢圓形倒得,橢圓形的大小為正切父組件泻红,因此如果父組件為正方形,切出來是圓形霞掺,用法如下:
ClipOval(
child: Container(
height: 150,
width: 250,
child: Image.asset(
'images/1.png',
fit: BoxFit.cover,
),
),
)
效果如下:
<img src="https://img-blog.csdnimg.cn/20200324160734820.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrczE5ODc=,size_16,color_FFFFFF,t_70" style="zoom:50%;" />
ClipPath
ClipPath組件根據(jù)路徑進(jìn)行裁剪谊路,我們自定義裁剪路徑也可以使用系統(tǒng)提供的,用法如下:
ClipPath.shape(
shape: StadiumBorder(),
child: Container(
height: 150,
width: 250,
child: Image.asset(
'images/1.png',
fit: BoxFit.cover,
),
),
)
shape
參數(shù)是ShapeBorder類型菩彬,系統(tǒng)已經(jīng)定義了很多形狀缠劝,介紹如下:
RoundedRectangleBorder:圓角矩形
ContinuousRectangleBorder:直線和圓角平滑連續(xù)的過渡,和RoundedRectangleBorder相比骗灶,圓角效果會小一些惨恭。
StadiumBorder:類似于足球場的形狀,兩端半圓耙旦。
-
BeveledRectangleBorder:斜角矩形脱羡。效果如圖:
<img src="https://img-blog.csdnimg.cn/20200324160806686.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrczE5ODc=,size_16,color_FFFFFF,t_70" style="zoom:50%;" />
CircleBorder:圓形。
CustomClipper
CustomClipper并不是一個(gè)組件免都,而是一個(gè)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;
}
}
效果如下:
<img src="https://img-blog.csdnimg.cn/20200324160835511.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrczE5ODc=,size_16,color_FFFFFF,t_70" style="zoom:50%;" />
我們還可以繪制五角星脓规,代碼如下:
class StarPath extends CustomClipper<Path> {
StarPath({this.scale = 2.5});
final double scale;
double perDegree = 36;
/// 角度轉(zhuǎn)弧度公式
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
參數(shù)表示間隔的點(diǎn)到圓心的縮放比例,五角星效果如下:
<img src="https://img-blog.csdnimg.cn/2020032416085643.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmdrczE5ODc=,size_16,color_FFFFFF,t_70" style="zoom:50%;" />
下面用動(dòng)畫動(dòng)態(tài)設(shè)置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博客地址(330個(gè)控件用法):http://laomengit.com
歡迎加入Flutter交流群(微信:laomengit)抖拦、關(guān)注公眾號【老孟Flutter】: