79092190

Date: 2024-10-16 01:38:54
Score: 2
Natty:
Report link

I was able to implement it in my own way and share it with you.Better.I'm sure there is a better way.If you have a better way, please let me know.

class BorderBubblePainter extends CustomPainter {
  BorderBubblePainter({
    this.color = Colors.red,
  });

  final Color color;

  @override
  void paint(Canvas canvas, Size size) {
    final width = size.width;
    // Equivalent to width since it is circular.
    // Define a variable with a different name for easier understanding.
    final height = width;
    const strokeWidth = 1.0;

    final paint = Paint()
      ..isAntiAlias = true
      ..color = color
      ..strokeWidth = strokeWidth
      ..style = PaintingStyle.stroke;

    final triangleH = height / 10;
    final triangleW = width / 8;

    // NOTE: Set up a good beginning and end.
    const startAngle = 7;
    // NOTE: The height is shifted slightly upward to cover the circle.
    final heightPadding = triangleH / 10;

    final center = Offset(width / 2, height / 2);
    final radius = (size.width - strokeWidth) / 2;

    final trianglePath = Path()
      ..moveTo(width / 2 - triangleW / 2, height - heightPadding)
      ..lineTo(width / 2, triangleH + height)
      ..lineTo(width / 2 + triangleW / 2, height - heightPadding)
      ..addArc(
        Rect.fromCircle(center: center, radius: radius),
        // θ*π/180=rad
        (90 + startAngle) * pi / 180,
        (360 - (2 * startAngle)) * pi / 180,
      );

    canvas.drawPath(trianglePath, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

usage

class BubbleWidget extends StatelessWidget {
  const BubbleWidget({
    super.key,
  });

  static const double _width = 100.0;
  static const double _height = 108.0;

  @override
  Widget build(BuildContext context) {
    return Stack(
      clipBehavior: Clip.none,
      alignment: Alignment.center,
      children: [
        SizedBox(
          width: _width,
          height: _height,
          child: CustomPaint(
            painter: BorderBubblePainter(),
          ),
        ),
        Transform.translate(
          offset: const Offset(
            0,
            -(_height - _width) / 2,
          ),
          child: Icon(
            Icons.check,
            color: Theme.of(context).colorScheme.primary,
            size: 16,
          ),
        ),
      ],
    );
  }
}
Reasons:
  • RegEx Blacklisted phrase (2.5): please let me know
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (0.5):
Posted by: Yone