Flutter自定義Painter和Clipper實現(xiàn)Container的不規(guī)則背景

最近在做需求的時候設(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ī)則圖形和描邊的繪制~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容