註意:無特殊說明,Flutter版本及Dart版本如下: Flutter版本: 1.12.13+hotfix.5 Dart版本: 2.7.0 ClipRect ClipRect組件使用矩形裁剪子組件,通常情況下,ClipRect作用於 、 、 、 、 、 、 組件,例如ClipRect作用於Alig ...
註意:無特殊說明,Flutter版本及Dart版本如下:
- Flutter版本: 1.12.13+hotfix.5
- Dart版本: 2.7.0
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可以繪製出任何我們想要的形狀,比如三角形,代碼如下:
@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的微信交流群(mqd_zzy),歡迎您的加入,讓我們一起學習,一起進步,開始我們的故事,生活不止眼前的苟且,還有詩和《遠方》。
當然我也非常希望您關註我個人的公眾號,裡面有各種福利等著大家哦。