最近在做需求的时候设计师做了一个背景不规则的icon,如下图:
企业微信20240708-174145.png
由于之后背景的渐变,描边的颜色和内部的字体可能都会变化,所以不采用直接切图的方式来做。
如果直接使用flutter的decoration来做的话没有办法直接实现,所以就决定用自定义painter和clipper的方法实现了
第一步,很简单的画Container的渐变背景,用decoration直接实现
Container(
width: 200,
height: 100,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Color(0xFFFFD5D5),
Color(0xFFFFECE6),
],
),
),
)
很简单,如图所示:
11.jpg
第二步,通过ClipPath来裁剪背景,因为左侧是一个半圆,所以半圆的半径就是Container高度的一半
class MyClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
Path path = Path();
path.moveTo(0, 0);
final center = Offset(size.height / 2, size.height / 2);
final radius = math.min(size.width, size.height) / 2;
path.arcTo(
Rect.fromCircle(center: center, radius: radius),
math.pi / 2, //注意要旋转90度才可以是左侧的半圆
math.pi,
true,
);
path.close();
path.moveTo(size.height / 2, size.height);
path.lineTo(size.width - 15, size.height);
path.lineTo(size.width, 0);
path.lineTo(size.height / 2, 0);
return path;
}
@override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
return true;
}
}
背景完成后如图:
11.png
这里需要注意一下,这里如果直接使用decoration的border属性,border也会被Cliper裁减掉,如下图:
11.png
所以内部采用了自定义CustomPaint的Painter的方式来实现子widget和border,代码如下:
class MyPainter extends CustomPainter {
final myPaint = Paint()
..color = Colors.black
..isAntiAlias = true
..strokeWidth = 5
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
@override
void paint(Canvas canvas, Size size) {
Path path = Path();
path.moveTo(0, 0);
final center = Offset(size.height / 2, size.height / 2);
final radius = math.min(size.width, size.height) / 2;
path.arcTo(
Rect.fromCircle(center: center, radius: radius),
math.pi / 2,
math.pi,
true,
);
path.moveTo(size.height / 2, size.height);
path.lineTo(size.width - 15, size.height);
path.lineTo(size.width, 0);
path.lineTo(size.height / 2, 0);
canvas.drawPath(path, myPaint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
几乎和背景的Cliper的path一样,主要是在画完圆弧之后path不要close,要继续画直线。
效果如下图:
11.jpg
这样就实现了不规则图形和描边的绘制~~