Flutter Custom paint stack object over object

710 Views Asked by At

Is it possible to achieve or stack paint object over another like this. I tried many resources for custom painter but was not able to stack the text in center of the circle and applying gradient behind circle. Help appreciated.

Custom Paint Shape

2

There are 2 best solutions below

1
On BEST ANSWER

You don't need Custom paint to achieve this. You can create the layout using stack like the following

Stack(
          children: [
            Container(
              decoration: BoxDecoration(
                  gradient: LinearGradient(
                      colors: [
                        Colors.orangeAccent.withOpacity(0.4),
                        Colors.transparent
                      ],
                      begin: Alignment.bottomCenter,
                      end: Alignment.topCenter,
                      stops: [0.4, 1])),
              width: 100,
              height: 200,
            ),
            Container(
              decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: Colors.deepPurple,
                  border: Border.all(color: Colors.white, width: 3)),
              width: 100,
              height: 100,
              child: Center(
                  child: Text(
                "80",
                style: TextStyle(
                    fontSize: 30,
                    fontWeight: FontWeight.w900,
                    color: Colors.white),
              )),
            ),
          ],
        )

preview

0
On

You can use Kaushik's answer, it's simpler and straight forward. However, if you have to use CustomPaint, here's how I would do it:

@override
void paint(Canvas canvas, Size size) {
  // top left point of shader rectangle
  var pointA = Offset(size.width * 0.2, 0);
  // define rectangle
  var rect = pointA & Size(size.width * 0.6, size.height);

  // Define a paint with shader
  final Paint shaderPaint = Paint()
    ..color = Colors.yellow
    ..style = PaintingStyle.fill
    ..strokeWidth = 1
    ..shader = const LinearGradient(
        begin: Alignment.topCenter,
        end: Alignment.bottomCenter,
        colors: [
          Colors.deepPurple,
          Colors.yellow,
        ]).createShader(rect);
  // draw rectangle
  canvas.drawRect(rect, shaderPaint);

  // paint for circle
  final Paint circlePaintFill = Paint()
    ..color = Colors.deepPurple
    ..style = PaintingStyle.fill;
  final Paint circlePaintStroke = Paint()
    ..color = Colors.white
    ..style = PaintingStyle.stroke
    ..strokeWidth = 5;

  // draw circle
  canvas.drawCircle(Offset(size.width * 0.5, size.height * 0.3),
      size.width * 0.3, circlePaintFill);
  canvas.drawCircle(Offset(size.width * 0.5, size.height * 0.3),
      size.width * 0.3, circlePaintStroke);

  //draw text
  const textStyle = TextStyle(
      color: Colors.white, fontSize: 60, fontWeight: FontWeight.bold);
  const textSpan = TextSpan(
    text: '80',
    style: textStyle,
  );
  final textPainter = TextPainter(
    text: textSpan,
    textDirection: TextDirection.ltr,
  );
  textPainter.layout(
    minWidth: 0,
    maxWidth: size.width,
  );
  // position of text
  final xCenter = (size.width - textPainter.width) / 2;
  final yCenter = (size.height * 0.6 - textPainter.height) / 2;
  final offset = Offset(xCenter, yCenter);
  textPainter.paint(canvas, offset);
}

You'll have to adjust the size value inside custom painter based on the size you define outside the custom painter