最近在做需求的時候設(shè)計師做了一個背景不規(guī)則的icon,如下圖:

企業(yè)微信20240708-174145.png
由于之后背景的漸變,描邊的顏色和內(nèi)部的字體可能都會變化,所以不采用直接切圖的方式來做。
如果直接使用flutter的decoration來做的話沒有辦法直接實現(xiàn),所以就決定用自定義painter和clipper的方法實現(xiàn)了
第一步,很簡單的畫Container的漸變背景,用decoration直接實現(xiàn)
Container(
width: 200,
height: 100,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Color(0xFFFFD5D5),
Color(0xFFFFECE6),
],
),
),
)
很簡單,如圖所示:

11.jpg
第二步,通過ClipPath來裁剪背景,因為左側(cè)是一個半圓,所以半圓的半徑就是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, //注意要旋轉(zhuǎn)90度才可以是左側(cè)的半圓
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
所以內(nèi)部采用了自定義CustomPaint的Painter的方式來實現(xiàn)子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,要繼續(xù)畫直線。
效果如下圖:

11.jpg
這樣就實現(xiàn)了不規(guī)則圖形和描邊的繪制~~