flutter wrap text instead of overflow
Asked Answered
I

9

71

When creating a Text widget with a long string in Flutter, it wraps its text when put directly in a Column. However, when it is inside Column-Row-Column, the text overflows the side of the screen.

How do I wrap text inside a Column-Row-Column? And what is the reason for this difference? It would seem logical to me that any child of the upper column would have the same width? Why is the width unbounded?

I tried putting the text in Expanded, Flexible, Container and FittedBox, based on other answers, but it leads to new errors I don't understand.

Example:

MaterialApp(
  title: 'Text overflow',
  home: Scaffold(
    appBar: AppBar(title: Text("MyApp"),),
    body: Column(
      children: <Widget>[
        Row(
          children: <Widget>[
            // The long text inside this column overflows. Remove the row and column above this comment and the text wraps.
            Column(
              children: <Widget>[
                Text("Short text"),
                Text("Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. ")
              ],
            ),
          ],
        ),
      ],
    ),
  ), 
)
Instable answered 11/2, 2019 at 15:40 Comment(1)
"Why is the width unbounded?". See https://mcmap.net/q/276258/-flutter-how-to-fix-quot-a-renderflex-overflowed-by-pixels-quot-errorJacquline
G
127

Row and Column are Flex widget and don't scroll, if there is not enough space flutter raises an overflow error.

If this occurs an Expanded or a Flexible widget may be used to wrap a long text.

In the docs it is not clearly stated, but beyond expanding to fill the available space in the main axis, Expanded and Flexible wraps in the cross-axis direction.

The long story

A step by step approach may help to understand the problem.

First, consider this scenario:

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Text overflow',
      home: Scaffold(
        appBar: AppBar(
          title: Text("MyApp"),
        ),
        body: Column(
          children: List.generate(100, (idx) => Text("Short text"))
        ),
      ),
    );
  }
}

It is a column widget that overflows on vertical direction as clearly reported by flutter:

I/flutter ( 8390): The following message was thrown during layout:
I/flutter ( 8390): A RenderFlex overflowed by 997 pixels on the bottom.
I/flutter ( 8390): 
I/flutter ( 8390): The overflowing RenderFlex has an orientation of Axis.vertical.

Now, a Row inside a Column:

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Text overflow',
      home: Scaffold(
        appBar: AppBar(title: Text("MyApp"),),
        body: Column(
          children: <Widget>[
            Row(
              children: <Widget>[
                Text(String.fromCharCodes(List.generate(100, (i) => 65)))
              ],
            ),
          ],
        ),
      ),
    );
  }
}

Now the overflow problem appears on the right side.

I have inserted a Row in a Column just to resemble your case, but the exact same problem emerge if you use a simple Row widget: Row and Column are both Flex widgets:

  • they layout their children in one direction;
  • they do not scroll, so if the children occupy more space than available an overflow error is raised;

The Expanded widget

Consider this layout, a row with two items, stiched togheter

Column(
  children: <Widget>[
    Row(
      children: <Widget>[Text('AAAA'), Text('ZZZZ')],
    ),
  ],
),

Now the first item Expanded to fill all the available space:

Column(
  children: <Widget>[
    Row(
      children: <Widget>[
        Expanded(child: Text('AAAA')),
        Text('ZZZZ')],
    ),
  ],
),

Finally, when you expand a very long string you will notice that the text wraps in the cross-axis direction:

Column(
  children: <Widget>[
    Row(
      children: <Widget>[
        Expanded(child: Text(String.fromCharCodes(List.generate(100, (i) => 65)))),
        Text('ZZZZ')],
    ),
  ],
),
Ganger answered 12/2, 2019 at 12:41 Comment(6)
You can take screen shot from the emulator instead of print screen then crop :)Accelerometer
This doesn't work for me, My tree (simplified) is: Scaffold > StreamBuilder > Column > Card > Padding > Row > Column > Column > Row > TextAnathema
Finally figured it out. When you add a widget even an empty text, now it will calculate end of the width.Audi
This answer is nicely written, and long, and starts promising, but then doesn't actually explain the effect at all :/Aseptic
Not worked for me. I am using Container -> Text. ThanksTreva
A good explanation with an example. After going through it I found to use Expanded Widget.Schlesien
N
69

You need to wrap the last Column with - Expanded or Flexible widget.

That Way Column can take up the required available space for the text.

body: Column(
        children: <Widget>[
          Row(
            children: <Widget>[
              // The long text inside this column overflows. Remove the row and column above this comment and the text wraps.
              Expanded(
                child: Column(
                  children: <Widget>[
                    Text("Short text"),
                    Text(
                        "Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. ")
                  ],
                ),
              ),
            ],
          ),
        ],
      ),
Noblewoman answered 11/2, 2019 at 15:59 Comment(8)
I see it works, but I don't understand it. Why is the available space infinite in the first place?Instable
The only solution that worked for me, after trying 10+ different ones!Galba
Incredible. It works but I don't understand why too :)Baroja
Thanks! I swear I was trying this last night and wasn't working but now it is - always the way when I'm tired!Jampan
Tried for several hours and finally this helped. Thank you.Shirr
Thank you finally something that actually worksLandside
Not solved my problem, getting another issue now "Incorrect use of ParentDataWidget."Treva
Wow, after trying other solutions, this one finally worked. ThanksMerciful
O
15

To avoid overflow for the texts in Row or Columns. Make sure you wrap the text under Flexible or Expanded widgets. After wrapping the text under one of the above widget, it will will wrap the big text into multiple lines. Sharing an Example :

Before Expanded widget:

return  Center(child:
        Container(
        padding: EdgeInsets.only(left: 50, right: 50),
          child: Row(
           mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Container(
                height: 200,
                 child: Text('It is a multiline text It does not  auto warp the text.', textAlign: TextAlign.center,style: TextStyle(fontSize: 20.0, color: Colors.white)),

          )
          ],
        ))
      );

Screenshot :

enter image description here

After Wapping inside Expanded :

  return  Center(
        child: Padding(padding:  EdgeInsets.only(left: 50, right: 50),
          child:  Row(
            mainAxisAlignment: MainAxisAlignment.center,

            children: <Widget>[
              Expanded(

                  child: Text('It is a multiline text It does not  auto warp the text.', textAlign: TextAlign.center,style: TextStyle(fontSize: 20.0, color: Colors.white))),
            ],
          ),
        )
      );

Screenshot : enter image description here

Orman answered 8/11, 2019 at 21:22 Comment(0)
V
12

Use Flexible Widget on Column as it's taking only the required space available.

Column(
      children: <Widget>[
        Row(
          children: <Widget>[
            // The long text inside this column overflows. Remove the row and column above this comment and the text wraps.
            Flexible(
              child: Column(
                children: <Widget>[
                Text("Short text"),
                  Text(
                      "Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. ")
                ],
              ),
            ),
          ],
        ),
      ],
    ),

Output:

enter image description here

Victualage answered 5/7, 2020 at 15:57 Comment(0)
D
5

Flutter provides a very useful Widget called Wrap, that can easily wrap its children horizontally and as well as vertically.

Wrap(
  direction: Axis.horizontal, //default
  alignment: WrapAlignment.center,
  children: [
    Text(),   //you can use any other widget
    Text(),
    Text(),
    Text(),
    Text(),
  ],
),
Deirdredeism answered 16/6, 2020 at 10:29 Comment(1)
Funny that this doesn't have more votes. Thank you!Arrack
P
4

Use Expanded as I used and solved the problem... Expanded solves this text-overflow problem if used in a proper way. Below is my code:

Row(
                              children: <Widget>[
                                Expanded(
                                  flex: 1,
                                  child: Icon(
                                    Icons.watch_later_outlined,
                                    size: 25,
                                    color: Colors.blueAccent,
                                  ),
                                ),
                                Expanded(
                                  flex: 5,
                                  child: Text("Write your long text here"
                                  ),
                                ), // name
                              ]),
Pneumococcus answered 29/1, 2021 at 8:28 Comment(0)
Y
1

As many have pointed out, Flexible should work, but... If you have multiple levels of Row, you will need to put Flexible in all of them, not only in the closest row, example:

@override
Widget build(BuildContext context) {
  super.build(context);
  return Container(
    child: IntrinsicHeight(
      child: Row(
        children: [
          // ...
          Flexible( // <-- THE OUTER ROW MUST ALSO CONTAIN `FLEXIBLE` !!
            child: Column(
              children: [
                // ...
                Row(
                  children: [
                    Text('Short Text'),
                    // ...
                    Flexible( // <-- THE `FLEXIBLE` OF THE INNER ROW WILL NOW WORK !!
                      child: Text(
                        'Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. ',
                        overflow: TextOverflow.ellipsis,
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ],
      ),
    ),
  );
}

Also, avoid using 10+ levels of indentation, create getters or methods to abstract each "small component logic" instead. I used it this way just to explain the solution better.

Youngster answered 27/2, 2023 at 16:52 Comment(0)
B
0

I think you can simply put softWrap of the Text widget to true and also provide an overflow other than ellipsis. I think this can highly help to automatically move overflow text to next line. this is an example

Text(
        "Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. Very long text. ",
        overflow: TextOverflow.visible,
        softWrap: true,
      )
Bookbinding answered 10/1 at 9:58 Comment(0)
N
-10
    SizedBox(height:100 , width:MediaQuery.of(context).of.size.width ,
  child:  Text( "I have read and agree to the end  user agreement",
    overflow: TextOverflow.clip)),

output

Nourishment answered 30/3, 2022 at 6:37 Comment(1)
\n is not a good solution for this. this only works when you specify text device-dependent how do you manage \n when you have dynamic long texts?Thesis

© 2022 - 2024 — McMap. All rights reserved.