Reputation: 4177
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. ")
],
),
],
),
],
),
),
)
Upvotes: 73
Views: 106303
Reputation: 35
I have recreated the Column Row Column arrangement. I have added Expanded before the 2nd Column and it works fine.
I am using Vidution, a Flutter UI Design Tool.
Here is the link
https://vidution.com/flutter#/project?id:e03bc1a8-7206-4a93-8550-693941c2bc8a
import 'package:flutter/material.dart';
class OverflowPractice extends StatefulWidget {
const OverflowPractice({super.key});
@override
State<OverflowPractice> createState() => _OverflowPracticeState();
}
class _OverflowPracticeState extends State<OverflowPractice> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).colorScheme.surface,
appBar: AppBar(title: const Text('Overflow Practice'), centerTitle: true),
body: const Column(
children: [
Row(
children: [
Expanded(
child: Column(
children: [
Text(
'Very long text. Very long text. Very long text. Very long text. Very long text. Very long text.',
),
],
),
),
Text('Short text'),
],
),
],
),
);
}
}
Upvotes: 0
Reputation: 415
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)),
Upvotes: -10
Reputation: 41
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,
)
Upvotes: 0
Reputation: 18983
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.
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:
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')],
),
],
),
Upvotes: 130
Reputation: 4365
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.
Upvotes: 1
Reputation: 7973
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(),
],
),
Upvotes: 5
Reputation: 1865
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
]),
Upvotes: 4
Reputation: 34270
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:
Upvotes: 12
Reputation: 5712
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 :
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))),
],
),
)
);
Upvotes: 15
Reputation: 51316
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. ")
],
),
),
],
),
],
),
Upvotes: 70