Search code examples
fluttercontainers

Flutter Container - How to align child text without changing container width?


I am trying to build something similar to a chat bubble, where each chat bubble would have text aligned normally, and timestamp aligned to the bottom right of the bubble. The size of the bubble must expand with the text, and should not take more space than necessary.

In order to do this I used a Column with two Container children. The second child would be having the timestamp.

When I do this without adding "alignment" property to the second Container child, the bubble size correctly shrinks/expands to the text, like so:

enter image description here

But when I add alignment: Alignment.bottomRight to the second container, the bubble size expands to fill the entire width of the screen.

enter image description here

Is there a way to align the "7:30 PM" text to the bottom right of the bubble without expanding the bubble size?

Scaffold(
        body: Container(
          decoration: BoxDecoration(
            color: Colors.blue,
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Container(
                child: Text(
                  "Without Alignment",
                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
                ),
              ),
              Container(
//                alignment: Alignment.bottomRight,
                decoration: BoxDecoration(
                  border: Border.all(),
                ),
                child: Text(
                  "7:30 PM",
                  textDirection: TextDirection.rtl,
                  textAlign: TextAlign.right,
                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
                ),
              ),
            ],
          ),
        ),
      ),

Solution

  • This may help you

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: MainWidget(),
        );
      }
    }
    
    class MainWidget extends StatefulWidget {
      @override
      _MainWidgetState createState() => _MainWidgetState();
    }
    
    class _MainWidgetState extends State<MainWidget> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: ListView(
            shrinkWrap: true,
            children: <Widget>[
              ReceivedMessageBubble(
                message:
                    "This is a demo message send by XXXX. So don't reply it. Trying to making it multiple lines. You can increase it",
                time: "12:45 PM",
              ),
              SendMessageBubble(
                message:
                    "Oh!!! OK",
                time: "12:45 PM",
              ),
            ],
          ),
        );
      }
    }
    
    class SendMessageBubble extends StatelessWidget {
      final String message;
      final String time;
    
      const SendMessageBubble({
        Key key,
        this.message,
        this.time,
      })  : assert(message != null),
            assert(time != null),
            super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return LayoutBuilder(
          builder: (context, constraints) {
            double maxBubbleWidth = constraints.maxWidth * 0.7;
            return Align(
              alignment: Alignment.centerRight,
              child: ConstrainedBox(
                constraints: BoxConstraints(maxWidth: maxBubbleWidth),
                child: Container(
                  decoration: BoxDecoration(
                    color: Colors.blue[300],
                    borderRadius: const BorderRadius.only(
                      topLeft: Radius.circular(10.0),
                      topRight: Radius.circular(0.0),
                      bottomLeft: Radius.circular(10.0),
                      bottomRight: Radius.circular(10.0),
                    ),
                  ),
                  margin: const EdgeInsets.all(10.0),
                  padding: const EdgeInsets.all(10.0),
                  child: IntrinsicWidth(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.end,
                      children: <Widget>[
                        Text(message),
                        const SizedBox(height: 5.0),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.start,
                          children: <Widget>[
                            Text(
                              time,
                              style: const TextStyle(
                                color: Colors.black54,
                                fontSize: 10.0,
                              ),
                            ),
                          ],
                        )
                      ],
                    ),
                  ),
                ),
              ),
            );
          },
        );
      }
    }
    
    class ReceivedMessageBubble extends StatelessWidget {
      final String message;
      final String time;
    
      const ReceivedMessageBubble({
        Key key,
        this.message,
        this.time,
      })  : assert(message != null),
            assert(time != null),
            super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return LayoutBuilder(
          builder: (context, constraints) {
            double maxBubbleWidth = constraints.maxWidth * 0.7;
            return Align(
              alignment: Alignment.centerLeft,
              child: ConstrainedBox(
                constraints: BoxConstraints(
                  maxWidth: maxBubbleWidth,
                ),
                child: Container(
                  decoration: BoxDecoration(
                    color: Colors.grey[300],
                    borderRadius: const BorderRadius.only(
                      topLeft: Radius.circular(0.0),
                      topRight: Radius.circular(10.0),
                      bottomLeft: Radius.circular(10.0),
                      bottomRight: Radius.circular(10.0),
                    ),
                  ),
                  margin: const EdgeInsets.all(10.0),
                  padding: const EdgeInsets.all(10.0),
                  child: IntrinsicWidth(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text(message,),
                        const SizedBox(height: 5.0),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.end,
                          children: <Widget>[
                            Text(
                              time,
                              style: const TextStyle(
                                color: Colors.black54,
                                fontSize: 10.0,
                              ),
                            ),
                          ],
                        )
                      ],
                    ),
                  ),
                ),
              ),
            );
          },
        );
      }
    }
    

    Here is the Demo DartPad