skip to Main Content

Current output:

enter image description here

Expected output:

enter image description here


Code:

Align(
  alignment: Alignment.topRight,
  child: Container(
    padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20),
    margin: EdgeInsets.only(right: 12, top: 8),
    decoration: BoxDecoration(
      color: Color(0xFF486993),
      borderRadius: BorderRadius.all(Radius.circular(20)),
    ),
    child: Text("This is my message"),
  ),
)

3

Answers


  1. Here you are:

    import 'package:flutter/material.dart';
    
    void main() => runApp(
        MyApp()
    );
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Padding(
            padding: EdgeInsets.all(7),
            child: Align(
              alignment: Alignment.centerRight,
              child: Stack(
                children: [
                  Container(
                    padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20),
                    decoration: BoxDecoration(
                      color: Color(0xFF486993),
                      borderRadius: BorderRadius.all(Radius.circular(20)),
                    ),
                    child: Row(
                      mainAxisSize: MainAxisSize.min,
                      children: <Widget>[
                        RichText(
                          text: TextSpan(
                            children: <TextSpan>[
                              TextSpan(
                                text: 'This is telegram message   ',
                                style: TextStyle(
                                    color: Colors.white,
                                    fontSize: 14.0
                                ),
                              ),
                              TextSpan(
                                text: '3:16 PM',
                                style: TextStyle(
                                    color: Colors.grey,
                                    fontSize: 12.0,
                                    fontStyle: FontStyle.italic
                                ),
                              ),
                            ],
                          ),
                        ),
                        Icon(Icons.check, color: Color(0xFF7ABAF4), size: 16,)
                      ]
                    ),
                  ),
                  Positioned(
                    bottom: 0,
                    right: 0,
                    child: CustomPaint(
                      painter: ChatBubbleTriangle(),
                    )
                  )
                ]
              )
            ),
          ),
        );
      }
    }
    
    class ChatBubbleTriangle extends CustomPainter {
      @override
      void paint(Canvas canvas, Size size) {
        var paint = Paint()..color = Color(0xFF486993);
    
        var path = Path();
        path.lineTo(-15, 0);
        path.lineTo(0, -15);
        path.lineTo(0, 0);
        canvas.drawPath(path, paint);
      }
    
      @override
      bool shouldRepaint(CustomPainter oldDelegate) {
        return true;
      }
    }
    
    

    You will have to change paint method, because now it’s just a triangle.

    Otherwise, it looks as you requested.

    Login or Signup to reply.
  2. Trying to recreate Telegram layout myself I came up with this to make the shape;

    enum _TailDirection { right, left }
    
    class ChatBubblePainter extends CustomPainter {
      ChatBubblePainter({this.color, this.isSentByMe});
    
      final Color color;
      final bool isSentByMe;
    
      @override
      void paint(Canvas canvas, Size size) {
        final paint = Paint()..color = color;
    
        Path paintBubbleTail(_TailDirection direction) {
          double startingPoint;
          double point;
          double endPoint;
          double curvePoint;
          if (direction == _TailDirection.right) {
            startingPoint = size.width - 5;
            point = size.width + 10;
            endPoint = size.width + 3;
            curvePoint = size.width;
          }
          if (direction == _TailDirection.left) {
            startingPoint = 5;
            point = -10;
            endPoint = -3;
            curvePoint = 0;
          }
          return Path()
            ..moveTo(startingPoint, size.height)
            ..lineTo(point, size.height)
            ..quadraticBezierTo(endPoint, size.height, curvePoint, size.height - 10);
        }
    
        final RRect bubbleBody = RRect.fromRectAndRadius(
            Rect.fromLTWH(0, 0, size.width, size.height), Radius.circular(5.0));
        final Path bubbleTail = isSentByMe
            ? paintBubbleTail(_TailDirection.right)
            : paintBubbleTail(_TailDirection.left);
    
        canvas.drawRRect(bubbleBody, paint);
        canvas.drawPath(bubbleTail, paint);
      }
    
      @override
      bool shouldRepaint(CustomPainter oldDelegate) {
        // TODO: implement shouldRepaint
        return true;
      }
    }
    
    Login or Signup to reply.
  3. Here is what exactly needed to create neat speech bubble in flutter.

    first create a custom painter class that extends Painter class

    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(5, size.height - 5)
              ..quadraticBezierTo(-5, size.height, -16, size.height - 4)
              ..quadraticBezierTo(-5, size.height - 5, 0, size.height - 17);
          }
          if (isOwn) {
            path = Path()
              ..moveTo(size.width - 6, size.height - 4)
              ..quadraticBezierTo(
                  size.width + 5, size.height, size.width + 16, size.height - 4)
              ..quadraticBezierTo(
                  size.width + 5, size.height - 5, size.width, size.height - 17);
          }
          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;
      }
    }
    

    then use it in your chat screen. please note that this screen for only demo purpose so you can modify it according to your needs.

    class ChatSampleWidget extends StatefulWidget {
      @override
      _ChatSampleWidgetState createState() => _ChatSampleWidgetState();
    }
    
    class _ChatSampleWidgetState extends State<ChatSampleWidget> {
      TextEditingController _editingController = TextEditingController();
      FocusNode _focusNode = FocusNode();
      final TextStyle textStyle = TextStyle(color: Colors.white);
      @override
      void initState() {
        super.initState();
      }
    
      @override
      dispose() {
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Chatter'),
          ),
          body: SafeArea(
            child: Stack(
              children: <Widget>[
                Container(
                  padding: EdgeInsets.all(20),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                   
                    children: <Widget>[
                      Row(
                        mainAxisAlignment: MainAxisAlignment.start,
                        children: <Widget>[
                          CustomPaint(
                              painter: CustomChatBubble(isOwn: false),
                              child: Container(
                                  padding: EdgeInsets.all(8),
                                  child: Text(
                                    'Message from someone else n Says sometihngs',
                                    style: textStyle,
                                  ))),
                        ],
                      ),
                      SizedBox(
                        height: 5,
                      ),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.start,
                        children: <Widget>[
                          CustomPaint(
                              painter:
                                  CustomChatBubble(color: Colors.grey, isOwn: false),
                              child: Container(
                                  padding: EdgeInsets.all(10),
                                  child: FlutterLogo())),
                        ],
                      ),
                      SizedBox(
                        height: 5,
                      ),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.end,
                        children: <Widget>[
                          CustomPaint(
                              painter:
                                  CustomChatBubble(color: Colors.green, isOwn: true),
                              child: Container(
                                  padding: EdgeInsets.all(8),
                                  child: Text(
                                    'Message from me',
                                    style: textStyle,
                                  ))),
                        ],
                      )
                    ],
                  ),
                ),
                Positioned(
                    bottom: 0,
                    child: Container(
                      padding: EdgeInsets.all(8),
                      width: MediaQuery.of(context).size.width,
                      color: Colors.grey.withOpacity(0.1),
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceAround,
                        children: <Widget>[
                          Flexible(
                            child: TextField(
                              controller: _editingController,
                              focusNode: _focusNode,
                              decoration:
                                  InputDecoration(hintText: 'Say something...'),
                            ),
                          ),
                          IconButton(
                              icon: Icon(
                                Icons.send,
                                size: 30,
                              ),
                              onPressed: () {
                                print(_editingController.text);
                              })
                        ],
                      ),
                    ))
              ],
            ),
          ),
        );
      }
    }
    

    this is how it looks;

    ScreenShot

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search