I'm trying to use flexible on my text cause it's overflow but for some reason expanded or neither flexible didn't work. But it work on other text widget on different screen. Anyone know why ? How can I fix this ?
return Row(
children: [
/// Ticket Details
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
/// Ticket Title
Flexible(
child: Text(
ticketData['title'],
style: primaryColor700Style.copyWith(
fontSize: fontSize18,
),
),
),
SizedBox(height: 8),
/// Date Created
Text(
'Created : ' +
DateFormat('d MMM y').format(
DateTime.parse(
ticketData['date_created'].toDate().toString(),
),
),
style: primaryColor400Style.copyWith(
fontSize: fontSize12,
),
),
],
),
/// Urgent Icon
if (ticketData['is_urgent'])
Icon(
Icons.warning_rounded,
size: 35,
color: warningColor,
),
],
);
Wrap the column with flexible
Row(
children: [
Flexible(
child: Column(
children:[
Text(),
]
)
)
]
)
Row takes infinite width, To get available width row for next children you can wrap Expanded/ Flexibile/ fixed width widget. You can check this doc more about.
You can find this from Layout algorithm on Row
Expanded, to indicate children that should take all the remaining room.
Flexible, to indicate children that should share the remaining room but that may by sized smaller (leaving some remaining room unused).
Related
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.
I have this small code:
Container(
color: Colors.blue,
child: Row(
children: [
Expanded(
child: Container(
color: Colors.red,
child: const Text('Red text that can be long long long long long'),
),
),
Flexible(
child: Container(
color: Colors.green,
child: const Text('Small text'),
),
),
],
),
),
which renders into this:
Notice how the long text is wrapped even though there is still space around the small text.
I would like the small text to only take the size it needs to let the long text take the rest. And if the small text becomes bigger, its maximum size would be the size of the Flexible widget in the row (half of the Row in my example since both Expanded and Flexible have flex: 1).
If the small text is small enough, it should look like:
| Red text that can be long long long long | Small text |
| long | |
And if the "small" text is long too:
| Red text that can be long | Small text that is also |
| long long long long | very long |
Is there a way to do that?
You can use ConstrainedBox:constraints: BoxConstraints.loose( Size.fromWidth(maxWidth / 2) for green.
body:LayoutBuilder(
builder: (context, constraints) => Row(
children: [
Expanded(
child: Container(
color: Colors.red,
child: const Text(
'Red text that can be long long long lbe long long long lbe long long long long long'),
),
),
ConstrainedBox(
constraints: BoxConstraints.loose(
Size.fromWidth(constraints.maxWidth / 2)),
child: Container(
color: Colors.green,
child: const Text('Smalled g long th xt'),
),
),
],
),
),
In the end I used Yeasin Sheikh's answer so I'm validating it.
But I'm writing this comment to add more precisions on what I have found during my investigations.
At first, I wanted a simple widget like Flexible or Expanded (let's say LooseFlexible) to wrap my widget with:
View upvote and downvote totals.
I have this small code:
Container(
color: Colors.blue,
child: Row(
children: [
Expanded(
child: Container(
color: Colors.red,
child: const Text('Red text that can be long long long long long'),
),
),
LooseFlexible(
flex: 1
child: Container(
color: Colors.green,
child: const Text('Small text'),
),
),
],
),
),
but it seems it would go against the way Flutter works.
I took a look a the flutter class RenderFlex, which is the render object the Flex class (a class that Row and Column are extending) returns in the method createRenderObject.
It has a method _computeSizes, and inside it goes through the children (one by one):
if it does not have a flex value ("normal widget"):
It gives to the child no max constraint for the layout and gets its size.
if it has a flex value (from Flexible or Expanded):
it accumulates in a totalFlex value the some of all the flex (and does not render the child).
Then it goes through all the widgets that have a flex value and gives them as a max constraint (flex / totalFlex) * (maxConstraintOfParent - totalSizeOfNonFlexChildren) and layout them with it.
So each child is layout only once.
If my widget LooseFlexible were to exist, and if we had this code:
Row(
children: [
Expanded(flex: 1),
LooseFlexible(flex: 1),
Expanded(flex: 1),
],
),
Let's say the row has a maxWidth of 300. There is no non-flex children and totalFlex = 3.
The 1st Expanded would be laid out with a maxWidth = 100. Since it is an Expanded its width will be 100.
The Flexible widget is also laid out with a maxWidth = 100. But its size could be 50 (and not 100).
Now comes the turn of the last Expanded, if we want it to take the entire remaining space, its size would be 150 which is not the same as the 1st Expanded with the same flex = 1 value. So the first child would need to be re-laid out, which is not following the flutter way of rendering children only once.
Row(
children: <Widget>[
Expanded(
child:Container(
color: Colors.green,
child: const Text('Small text'),
),
),
Expanded(
child: Container(
color: Colors.red,
child: const Text('Small text'),
),
),
]
)
I'm trying to make a Table with two cells of the same width and height, so that the height depends on the size of the content. However, the smaller TableCell always shrinks:
This is what I'm trying to implement:
Here's the code:
Table(
children: [
TableRow(
children: [
TableCell(
child: Container(
color: Colors.green,
child: Text(
'long text long text long text long text long text long text long text'),
),
),
TableCell(
child: Container(
color: Colors.orange,
child: Text('short text'),
),
),
],
)
],
),
P.S. I could solve it by adding verticalAlignment: TableCellVerticalAlignment.fill, to the smaller cell, but any cell can be the smaller one, depending on the content. When I add this line to both cells, the whole table disappears. The only bypass I could imagine is to calculate the length of the content and find the smaller cell, but I wonder if there is a way to implement this UI directly with Flutter.
Would appreciate any help.
1. Row with IntrinsicHeight
IntrinsicHeight limits the height of the Row to the content size, which however is considered a 'relatively expensive' approach and is not recommended.
IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: Container(
color: Colors.green,
child: Text(
'long text long text long text long text long text',
))),
Expanded(
child: Container(
color: Colors.orange,
child: Text(
'short text',
))),
],
),
),
2. Table with TableCellVerticalAlignment.fill
As mentioned in the question, the .fill option must not be used in the largest TableCell, because in this case the TableRow will have zero height. This is the preferred solution, because it doesn't have the 'expensiveness' issue of the previous one.
final texts = ['long text long text long text long text long text', 'short text'];
final colors = [Colors.green, Colors.orange];
// find the longest text and its index
final max = texts.asMap().entries.reduce(
(a, b) => (a.value.length > b.value.length) ? a : b,
);
return Table(children: [
TableRow(
children: texts
.asMap()
.entries
.map((e) => TableCell(
// use .fill in all cells except the largest
verticalAlignment: (e.key != max.key)
? TableCellVerticalAlignment.fill
: TableCellVerticalAlignment.top,
child: Container(
color: colors[e.key],
child: Text(e.value),
)))
.toList(),
),
]);
I need to fix a minimum width to my Column Widgets. Inside each of them, I have Text Widgets which can be very short or very long. I need to fix a minimum width to them in order to have an acceptable size of Column even if the text is short. The other Column need obviously to adapt himself.
Row(children: [
Column(
children: [
Container(
constraints: BoxConstraints(minWidth: 80), // do not work
child: Text("short text"),
),
],
),
Column(
children: [
Container(
constraints: BoxConstraints(minWidth: 110), // do not work
child: RichText(
text: TextSpan(
text:"very very longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg text")),
),
],
),
],
)
There's probably a dozen ways to do what you want. And likely none of them straightforward or easy to understand. (The subject of constraints & sizes is quite complicated. See this constraints page for more examples & explanations.)
Here's one potential solution.
This will set a minimum width for the blue column (based on stepWidth), but will expand/grow if the text (child) inside wants to.
The yellow column will resize to accommodate the blue column.
class ExpandedRowPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Expanded Row Page'),
),
body: SafeArea(
child: Center(
child: Row(
children: [
IntrinsicWidth(
stepWidth: 100,
// BLUE Column
child: Container(
color: Colors.lightBlueAccent,
child: Column(
children: [
//Text('Short'),
Text('shrt')
],
)
),
),
// YELLOW Column
Flexible(
child: Container(
alignment: Alignment.center,
color: Colors.yellow,
child: Column(
children: [
Text('Very lonnnnnnnnnnnnnnnnnnnnnnnnnnnng texttttttttttttt'),
],
)
),
)
],
)
),
),
);
}
}
You could do the above without a Flexible yellow column, but a very long text child would cause an Overflow warning without a Flexible or Expanded wrapping widget.
A Row widget by itself has an infinite width constraint. So if a child wants to be bigger than screen width, it can, and will cause an overflow. (Try removing Flexible above and rebuild to see.)
Flexible and Expanded, used only inside Row & Column (or Flex, their superclass), checks screen width and other widgets inside a Row, and provides its children with a defined constraint size instead of infinite. Children (inside Flexible/Expanded) can now look up to parent for a constraint and size themselves accordingly.
A Text widget for example, will wrap its text when it's too wide for constraints given by Flexible/Expanded.
use FittedBox();
suppose Example:
Row(
children: [
Column(
children: [
Container(
constraints: BoxConstraints(minWidth: 80), // do not work
child: Text("short text"),
),
],
),
Column(
children: [
Container(
constraints: BoxConstraints(minWidth: 110), // do not work
child:
FittedBox(
child: RichText(
text: TextSpan(
text:
"very very longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg text")),
),
),
],
),
],
);
So I am currently working on an app project and I have arrived at a point where I want to put two text lines within a row on top of each one and other. As an example it should like this
app demo created with figma. So far I have a row in which every element on the same altitude is contained within, but I am having a hard time being able to put 2 elements within a row on top of each other. I have found out this class called Stack but I am having a hard time implementing it. Within my Stack class I have a RichText Class. From the flutter api, what I understand is that you have to use containers (to be able to define the positions). So I wonder if I should switch to container classes right after the Stack class and then within each Container class, I put a RichText? If I could have some advice on this, or simply on how to create something like in the picture it would be great. Thanks in advance.
Added a demo of what you are trying to achieve:
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
// row containing the avatar, name, date and icons (likes and comments)
Row(
children: [
// circle avatart
CircleAvatar(
backgroundColor: Colors.blue,
radius: 25,
),
// spacing
SizedBox(
width: 10,
),
// the name of poster and date in a column
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Claire',
),
Text(
'July 03 at 13:08PM',
),
],
),
// spacer
Spacer(),
// likes icon
Icon(Icons.favorite_border),
Text(
'32',
),
// spacing
SizedBox(
width: 10,
),
// comments icon
Icon(
Icons.comment,
),
Text(
'32',
),
],
),
// spacing
SizedBox(
height: 10,
),
// title text
Text(
'Dorm recommendation',
),
// decription
Text(
'Any recommendations on dorm application? Does anyone know how\'s the facility at Talent Apartment? Are there teamrooms and gym in TA? Also, updates on the location of washers and dryers?',
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
],
),
RESULT: