老孟导读:Flutter中很多组件都有一个叫做
shape
的属性,类型是ShapeBorder
,比方Button类、Card等组件,shape
示意控件的形态,零碎曾经为咱们提供了很多形态,对于没有此属性的组件,能够应用 Clip 类组件进行裁减。
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,就是矩形。
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带有浏览方向,大部分国家浏览是从左到右,但有的国家是从右到左的,比方阿拉伯等。
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相比,圆角成果会小一些。
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
参数定义裁剪规定,上面具体介绍。
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,
),
),
)
成果如图:
<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组件依据门路进行裁剪,咱们自定义裁剪门路也能够应用零碎提供的,用法如下:
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:斜角矩形。成果如图:
<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并不是一个组件,而是一个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;
/// 角度转弧度公式
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
参数示意距离的点到圆心的缩放比例,五角星成果如下:
<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%;” />
上面用动画动静设置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个控件用法):http://laomengit.com
欢送退出Flutter交换群(微信:laomengit)、关注公众号【老孟Flutter】:
发表回复