fluttercanvaschatcustom-painting

How to draw tail end for container in Flutter using Custom painter


I have a chat screen which have the chatItem box with tail end like this

Need to have that tail end in receiver side and sender side as well as I am currently using custom painter to this. And couldn't able to figure this out.

enter image description here

`class CustomChatBubble extends CustomPainter {CustomChatBubble({this.color, @required this.isOwn});
final Color color;
final bool isOwn;

@override
void paint(Canvas canvas, Size size) {
final paint = Paint()..color = color ?? Colors.blue;

Path paintBubbleTail() {
  Path path;
  if (!isOwn) {
    path = Path()
      ..moveTo(0, size.height)
      ..relativeMoveTo(0,5)
      ..quadraticBezierTo(10, size.height , 0, size.height - 5);
  }
  if (isOwn) {
    path = Path()
      ..moveTo(0, size.height)
      ..relativeMoveTo(0,5)
      ..quadraticBezierTo(10, size.height , 0, size.height - 5);
  }
  return path;
}

final RRect bubbleBody = RRect.fromRectAndRadius(
    Rect.fromLTWH(0, 0, size.width, size.height), Radius.circular(16));
final Path bubbleTail = paintBubbleTail();

canvas.drawRRect(bubbleBody, paint);
canvas.drawPath(bubbleTail, paint);
}

@override
bool shouldRepaint(CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return true;
}
}`

This is the class I used to do isOwn is for toggle between sender and receiver


Solution

  • Here is the path for your case:

        
    class CustomChatBubble extends CustomPainter {
      CustomChatBubble({this.color, @required this.isOwn});
      final Color color;
      final bool isOwn;
    
      @override
      void paint(Canvas canvas, Size size) {
        final paint = Paint()
          ..color = color ?? Colors.blue
          ..style = PaintingStyle.fill;
    
        Path path;
        double triangleHeight = 10.0;
        double triangleWidth = 10.0;
        double roundedBorder = 5.0;
    
        Path drawBubbleBody() {
          if (!isOwn) {
            path = Path()
              ..lineTo(0, size.height)
              ..lineTo(triangleWidth, size.height - triangleHeight)
              ..lineTo(size.width - roundedBorder, size.height - triangleHeight)
              ..quadraticBezierTo(size.width, size.height - triangleHeight,
                  size.width, size.height - triangleHeight - roundedBorder)
              ..lineTo(size.width, roundedBorder)
              ..quadraticBezierTo(size.width, 0, size.width - roundedBorder, 0);
            path.close();
          }
          if (isOwn) {
            path = Path()
              ..moveTo(size.width - roundedBorder, 0)
              ..lineTo(roundedBorder, 0)
              ..quadraticBezierTo(0, 0, 0, roundedBorder)
              ..lineTo(0, size.height - triangleHeight - roundedBorder)
              ..quadraticBezierTo(0, size.height - triangleHeight, roundedBorder,
                  size.height - triangleHeight)
              ..lineTo(size.width - triangleWidth, size.height - triangleHeight)
              ..lineTo(size.width, size.height)
              ..lineTo(size.width, roundedBorder)
              ..quadraticBezierTo(size.width, 0, size.width - roundedBorder, 0);
          }
          return path;
        }
    
        canvas.drawPath(drawBubbleBody(), paint);
      }
    
      @override
      bool shouldRepaint(CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
        return true;
      }
    }
    

    In case you want to reproduce:

        import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Material App',
          home: Scaffold(
            appBar: AppBar(
              title: Text('Material App Bar'),
            ),
            body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  CustomPaint(
                    painter: CustomChatBubble(isOwn: true, color: Colors.grey),
                    child: Container(
                      width: 200,
                      height: 50,
                    ),
                  ),
                  CustomPaint(
                    painter: CustomChatBubble(isOwn: false, color: Colors.orange),
                    child: Container(
                      width: 200,
                      height: 50,
                    ),
                  )
                ],
              ),
            ),
          ),
        );
      }
    }
    

    Result : enter image description here