Text inside nested Row is not wrapping unless enclosing column is wrapped in Flexible widget - flutter

The text inside my Text widget is not wrapping, even when wrapped in a Flexible widget. I found a workaround but it involves wrapping a Column widget inside a Flexible widget which I am not sure is best practice.
I have seen many similar answers online, but none for my exact problem. It is relevant that my text widget in question is nested inside the following hierachy Row -> Column -> Row
A rough idea of how this layout should look:
Here is the original code. When run the text overflows the screen rather than wrapping.
Row(
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("top column"),
Row(
children: [
Text("left row"),
Text(
"this is the text that needs to wrap, this is the text that needs to wrap",
),
],
),
],
crossAxisAlignment: CrossAxisAlignment.start,
),
Text("right side"),
],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
);
Here is code that solves my problem, but it involves wrapping both the Text widget AND the outer Column widget in a Flexible widget:
Row(
children: [
Flexible( // added Flexible widget, but doesn't seem correct.
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("top column"),
Row(
children: [
Text("left row"),
Flexible( // added Flexible widget
child: Text(
"this is the text that needs to wrap, this is the text that needs to wrap",
),
)
],
),
],
crossAxisAlignment: CrossAxisAlignment.start,
),
),
Text("right side"),
],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
);
Is there a better way to achieve this wrapping or is enclosing the Column in a Flexible widget a satisfactory approach?

Your approach is right, here's why :
You managed to the problem of the inner Row long text by wrap it into a Flexible,to prevent an overflow in the horizontal axis.This works perfectly if this is your whole tree,but this isn't the case.
Up on your widget tree there is no horizontal constraint limiting the width of children.Column wraps in the vertical axis, so the children of the upper-most Row one with fixed width (Text("right side")) and the other is unbounded one (Column).
When you wrapped the Column with Flexible, it made children bounded horizontally. Another approach would be to use a Container, but it is not the best one as it needs you to give the width before build.

Related

i need to remove this text over flow in flutter. how can i do that?

I am facing error in the Text widget which is in Column.
body: Padding(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.songModel.displayNameWOExt, <------- here is my text
),
Text(
widget.songModel.artist.toString(),
overflow: TextOverflow.fade,
),
],
),
],
), ), );
This is what happened to me
This is what i need look like
Wrap the Text that is inside a Row widget with an Expanded widget:
Expanded(child: Text(/* Here the text*/),
wrap the text with the container and give a specific size to the container after that use overflow: TextOverflow.fade or any other property of "overflow", because these properties only work when you give a size to textfield but you cant give size to textfield so wrap it with container.
try embedding the Text() widget inside a Expanded() widget expanded documentation
Expanded is a widget that expands a child of a Row, Column, or Flex so that the child fills the available space.

Flutter text widget: achieve horizontal vertical align; left-align horizontal

Good evening Stack Overflow.
Any advances on this Flutter code to achieve vertically-centered, but left-aligned text, in a simple full width container?
I found I had to fall back on making a secondary wrapper column around the text, and set BOTH mainAxisAlignment.center (for horizontal centering) and crossAxisalignment.start (to get left alignment).
I don;t want to set the Main column's axis alignments, as there will be other text widgets with different text alignments.
For the wrapper column I made it seems I can't just set mainAxisAlignment.center (for horizontal center) and then force textAlign.left in the Text widget itself. Surprised by that.
Anyway, the below code works, but surely there's a more efficient way?
body: SafeArea(
child: Column( //<-MAIN column for everything on the page
children: <widget> [
// A container for my text widget
Container(
height: 50;
width: double.infinity,
Child: Column( //<- had to make another wrapper column.
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
Children: [
Text('mytext')
]
),
) //container
] //children
)) //Main column and SafeArea
Cheers.
wrap your Text Widget in an Align Widget and set the alignment to centerLeft

Is there any possibility to align to the screen center the second element of a Row

I have a Row with three elements. I want to have the second element right in the middle of the space occupied by the row and not depending on the first element of the row. I've tried like this but seems that the _buildLogo widget is center align between the end of first element and the starting point of the third element.
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_buildCancelButton(),
_buildLogo(),
_buildExtraText(),
],
),
I've also tried with a Stack/Row combination but then I have problems with the vertical alignment.
child: Stack(
children: [
_buildLogo(),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_buildCancelButton(),
_buildExtraText(),
],
),
),
],
I will attach a picture with my result.
Adding Spacer() between the _buildLogo() will lead with the same result.
_buildCancelButton(),
Spacer(),
_buildLogo(),
Spacer(),
_buildExtraText(),
I think your logo actually is in the middle, but it kind a looks a little bit off, because of the icon on the left side. Maybe a 'dumb' beginner-solution is adding some sapces after the 'AirDolomiti'-text (like this: 'AirDolomiti ').
Did this help or did I missunderstand your question?
Use Spacer(). It will align your 2nd widget in center.
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
_buildCancelButton(),
Spacer(), //add it here
_buildLogo(),
Spacer(), // add it here
_buildExtraText(),
],
),
Note: the buildLogo's horizontal alignment will depend on first and third widget's width
If Left and right widget are same size then the middle widget will be in center. So make it equal, use sizedbox.

Flutter: How to add a column widget inside a bottom navigation bar

I've tried the following and got the out, but the body went blank.
Is there any way to add a coloumn or a listview inside a bottom navigation bar
Column(
mainAxisAlignment:MainAxisAlignment.end,
children: <Widget>[
Row(
children: <Widget>[
Expanded(
//button1
),
Expanded(
//button2
),
Expanded(
//button3)
),
Row(
children: <Widget>[
Expanded(
//button4
),
Expanded(
//button5)
],
)
],
),
Apart from the issue posed by Expanded widget (as pointed out in the answer by alexandreohara),
Column's mainAxisSize attribute is set to MainAxisSize.max by default. That means the column will try to occupy all the space available (the entire screen height).
Setting Column's mainAxisSize to MainAxisSize.min will wrap the Column widget to occupy the least possible space(vertically) and not span the entire screen.
Following is the way it can be done:
Column(
mainAxisSize: MainAxisSize.min,
children: [...]
);
There's no problem using a Column in a BottomNavigationBar. I think that your problem is wrapping everything in Expanded. It doesn't know the width of the widgets inside, and because of that, it will return blank.
Try to remove those Expanded widgets and try this:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween
children: [FlatButton(...), FlatButton(...)],
)

Simple Layout Challenge

I am trying to create a Card that displays the score in a game. The card will be more complex than this example, but in the middle of the card I want to have a Row. That Row contains two Columns. The first Column contains two Rows. In each of those two Rows is the team name and the score.
Widget build(BuildContext context) {
return Card(
child: Row(
children: <Widget>[
Column(
children: <Widget>[
Row(
children: <Widget>[
Text('Team A'),
Text('100'),
],
),
Row(
children: <Widget>[
Text('Team B'),
Text('100'),
],
),
],
),
Text('15:00'),
],
),
);
}
Now I want t wrap the Text widgets that display the team name in a Expanded. Once I do that I get a long descriptive error that basically says my Row has a parent that does not have a finite width, but it has a child that is asking to expand and these two are in conflict. I get that they are in conflict. How do I fix it? I definitely don't want to give the parent Widget (the Card) a finite width.
It's not 100% clear what you want the scoreboard to look like - this is an instance where a quick mock-up would be a great help.
However, I can tell you why you're getting an exception.
When you wrap your 'Team A' text in an Expanded, during the layout pass flutter gets confused. The top level row has two items, neither of which define any sort of size, so it makes them as large as possible in the cross axis (vertical) and as small as possible in the main axis (horizontal). This means that they delegate their size to their children.
By wrapping 'Team A' in an Expanded, you're basically telling it:
"Hey you, your parent widget is pretty big. I want you to take up all of it that isn't already being used instead of being how big you would normally be."
It responds with
"Sure boss, but I've just checked and none of my parents actually have
a defined size.... so I don't know what to do. Guess I'll just throw an
exception."
The fix is to size the parent, which in this case is the column that contains the two rows (geez, that's confusing).
I think from your description what you want is for that column to take up as much space as possible, so you just have to wrap it in expanded as well. So if you do this, your problem should resolve itself:
Widget build(BuildContext context) {
return Card(
child: Row(
children: <Widget>[
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
children: <Widget>[
Expanded(child: Text('Team A')),
Text('100'),
],
),
Row(
children: <Widget>[
Expanded(child: Text('Team B')),
Text('100'),
],
),
],
),
),
Text('15:00'),
],
),
);
}
That way, the column containing the two rows expands to take all available space during its layout pass. Once the 'Team A' text gets around to trying its layout pass it can simply size itself (horizontally) to that column.
You can then play around with the flex factor to get everything how you want.
Just an FYI - once you start getting lots of nested containers and rows you might want to consider a CustomMultiChildLayout. It's slightly more manual as you need to do the layout calculations yourself, but it might be easier in the long run depending on how complex your scoreboard is.