4

A lot of native mobile chat messengers, like telegram, whatsapp, etc, implement this wrapping behaviour: wrapping time label to a new line when there is no enough room for text.

Simple chat bubble consist of two parts: Text and time label. In simple case, they are almost positioned on the same baseline. Even when the text is multiline (baseline with last line). But in some cases, when there is no free space and the texts are trying to intersect, an indent is added at the bottom of bubble.

It will be simple to understand, if I show it by pictures and videos: enter image description here

And 2 videos:

multiline https://youtu.be/eigLIHWaub8

singleline https://youtu.be/9GMDFYwMqdU

How to implement it on Flutter?

nail
  • 715
  • 7
  • 20

2 Answers2

13

You can use Stack with fake placeholder for time (or another info) on first layer and real positioned text on the second layer.

    class CustomCard extends StatelessWidget {


     final String msg;
      final String additionalInfo;

      CustomCard({
        @required this.msg,
        this.additionalInfo = ""
      });

      @override
      Widget build(BuildContext context) {
        return Card(
          child: Stack(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: RichText(
                  text: TextSpan(
                    children: <TextSpan>[

                  //real message
                  TextSpan(
                    text: msg + "    ",
                    style: Theme.of(context).textTheme.subtitle,
                  ),

                  //fake additionalInfo as placeholder
                  TextSpan(
                      text: additionalInfo,
                      style: TextStyle(
                          color: Color.fromRGBO(255, 255, 255, 1)
                      )
                  ),
                ],
              ),
            ),
          ),

          //real additionalInfo
          Positioned(
            child: Text(
              additionalInfo,
              style: TextStyle(
                fontSize: 12.0,
              ),
            ),
            right: 8.0,
            bottom: 4.0,
          )
        ],
      ),
    );
 }

And result can looks like: result screenshot

MariaM
  • 148
  • 5
  • While this is as close as possible to the desired result, it is still not as it was asked. In the example screenshot, the width of the bubbles is still "fluid", while on your example, when the text wraps, it takes the full width, resulting in a wrong behaviour. I know this has over 3 years, but is there any better way to do this? – Pablo Zehle Feb 22 '22 at 19:18
7

You can do something very similar using Wrap widget but not exactly the same behavior :

Card(
            color: Colors.greenAccent,
            child: Wrap(
              alignment: WrapAlignment.end,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Text(
                      "Text message in multi-lines and it looks similar to what's in the picture "),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Text("10:0 PM"),
                ),
              ],
            ),
          ), 

enter image description here

Raouf Rahiche
  • 28,948
  • 10
  • 85
  • 77
  • 1
    It's very similar - yes, but not the same. Question is how to do the same. This problem is more complex and with widgets that I know it is not solvable – nail Oct 23 '18 at 17:40