Flutter - How to stretch Column inside Row to maximum available height? - flutter

I need create this UI in my flutter app:
It is row for my list. This is my code:
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
CachedNetworkImage(
imageUrl: photoUrl,
imageBuilder: (context, imageProvider) => Container(
height: 112,
width: 90,
),
),
const SizedBox(
width: 14,
),
Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${title}',
),
Align(
alignment: Alignment.centerLeft,
child: SizedBox(
width: descriptionWidth,
child: Text(
'${shortDescription}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
),
Text(
'${footer}',
),
],
)
],
);
I need the test block to occupy a height equal to the image. but when the text is all in the middle, it takes up a lot less height. this is an example of how my code works now:
how do I fix this? How to stretch Column inside Row to maximum available height?
I tried several options but then it breaks the display of multi-line text.

While height is fixed, you can wrap Column with SizedBox(height:112) and to control textOverflow, wrap SizedBox with Expanded.
Expanded(
child: SizedBox(
height: 112,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Full method
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
/// replace with image
height: 112,
width: 90,
color: Colors.red,
),
const SizedBox(
width: 14,
),
Expanded(
child: SizedBox(
height: 112,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${title}',
),
Flexible(
child: Text(
'${shortDescription}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
Text(
'${footer}',
),
],
),
),
)
],
);

For Maximum Height You can use
Expanded(
child : --- your child widget
)
or
Flexible(
child: -- your child widget
)
A widget that expands a child of a Row, Column, or Flex so that the child fills the available space.
Using an Expanded widget makes a child of a Row, Column, or Flex expand to fill the available space along the main axis (e.g., horizontally for a Row or vertically for a Column). If multiple children are expanded, the available space is divided among them according to the flex factor.
An Expanded widget must be a descendant of a Row, Column, or Flex, and the path from the Expanded widget to its enclosing Row, Column, or Flex must contain only StatelessWidgets or StatefulWidgets (not other kinds of widgets, like RenderObjectWidgets).

First of all, you need to fixed the card height for better positioning of your text with the card image and then expand your column to dynamically handle the multiline of text. ANd you don't need to use the align widget
try the below code
Container(
height: 112, // here you fixed the container height
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
CachedNetworkImage(
imageUrl:
"https://avatars.githubusercontent.com/u/26745548?v=4",
imageBuilder: (context, imageProvider) => Container(
height: 112,
width: 90,
),
),
const SizedBox(
width: 14,
),
Expanded(
// here expand your column
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'title',
),
Text(
'{shortDescription 23487509387 2039487502930349857 03984 5 30498 503498 503948 70293847 50923487503}',
),
Text(
'footer',
),
],
),
)
],
),
)
output:

Related

Text Overflowing in a Row, Flutter

I'm having issues with the layout because of the long text, I've tried using Expanded / Flexible with the text that is causing the issue to fill the space it needs but it's overflowing. I know the question is asked hundred times, but I don't understand where is the mistake. I tried applying to both Expanded / Flexible to all of the Row/Columns individually and too all at the same time (mostly I was trying out layouts to try to fix it), and I still have the issue... I even tried to use the FittedBox with fit: BoxFit.(all of them).
Container(
alignment: Alignment.centerLeft,
child: Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Icon(Icons.directions_car),
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Text 1"),
SizedBox(
height: 4,
),
Text('TEXT 2'),
],
),
SizedBox(
width: 27,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('1 World Way, Los Angeles, CA 90045, USA',
textAlign: TextAlign.left,
),
SizedBox(
height: 4,
),
Text('FLIGHT 3231'),
],
),
],
),
],
),
],
),
);
By my understanding, and do correct me if I'm wrong, applying Expanded / Flexible, Flexible takes only the needed space, and Expanded takes all available space, respecting the flex factor. So most of the time I use the Flexible widget, but this time it is not working.
Thanks in advance for the help!
Try using Expanded widget with flex value set as per the expectation of UI filling.
Sample Code:
Center(
child: Container(
height: 80,
color: Colors.yellow,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(Icons.bus_alert),
),
Expanded(
flex: 1,
child: Container(
width: 1,
color: Colors.green,
child: Column(
children: [Text("Text 1"), Text("Text 1")],
),
)),
Expanded(
flex: 3,
child: Container(
color: Colors.blue,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text("1 World Way, Los Angeles, CA 90045, USA"),
Text("FLIGHT 3231"),
],
),
))
],
),
))
Note: There is a limitation for the text content using. We need to make sure to set the height according to the expected text length.
You can use Flexible or Expanded Widget You should try to below code :
Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.blue,
),
borderRadius: BorderRadius.circular(15.0),
),
margin: EdgeInsets.all(16.0),
child: Container(
padding: EdgeInsets.all(8.0),
alignment: Alignment.centerLeft,
child: Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(Icons.directions_car),
SizedBox(
width: 10,
),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Text 1"),
SizedBox(
height: 4,
),
Text('TEXT 2'),
],
),
),
SizedBox(
width: 27,
),
Flexible(
child: Container(
child: Column(
children: [
Text(
'1 World Way, Los Angeles, CA 90045, USA',
textAlign: TextAlign.left,
),
SizedBox(
height: 4,
),
Text(
'FLIGHT 3231',
textAlign: TextAlign.left,
),
],
),
),
),
],
),
],
),
),
),
Your screen like this :
wrap it by a container with fixed width and then use auto_sized_text. Or you can wrap your Text widget by FittedBox by fixed width. it would do the same approach. Feel free to add maxLine, minFontSize and maxFontSize' in auto_sized_text. Using ExpandedorFlexible` only affects the size of the container when your text length is lower than the given width, and It does not help you in this situation.
If the text is really long, then using Expanded will wrap the text according to the parent widget, thus leading to change in the font size. You might consider using ellipsis.
return Container(
width:300 //give a width of your choice
child: Text('Any long text',
overflow:TextOverflow.ellipsis,
),
);

Completely center Widget in Flutter

I started to develop in Flutter recently and I am having difficulties in centralizing a Widget completely in the available space of View.
This is how it looks:
And here's what I want to achieve:
And here's my code:
LayoutBuilder(builder:
(BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Column(children: [
NavHeader("Deposit"),
BalanceHeader(widget.usd),
]),
Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"How much do you want deposit?",
style:(
...
),
),
Container(
alignment: Alignment.center,
width: width * 0.4,
margin: EdgeInsets.only(top: 10),
child: Row(
...
),
),
],
),
],
),
),
);
}),
bottomNavigationBar: BottomAppBar(
...
),
),
);
}
By using MainAxisSize.min The height of the Column will be according to the combined height of its children and incoming height from the parent will be ignored. That means your column height has shrinked to its children.
There is you can use MainAxisSize.max instead of MainAxisSize.min to max height of column. And also you have to use mainAxisAlignment: MainAxisAlignment.center for aligning childrens to center of column.
Your Second Column
Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"How much do you want deposit?",
style:(
...
),
),
Container(
alignment: Alignment.center,
width: width * 0.4,
margin: EdgeInsets.only(top: 10),
child: Row(
...
),
),
],
),
Edited Column
Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center
children: [
Text(
"How much do you want deposit?",
style:(
...
),
),
Container(
alignment: Alignment.center,
width: width * 0.4,
margin: EdgeInsets.only(top: 10),
child: Row(
...
),
),
],
),
Well, there is a widget for that!
As for most things in flutter just Wrap the Widgets you want centered inside a Center widget and you should achieve what you want.
Column(
mainAxisAlignment: MainAxisAlignment.center,
children ... Your code
)
You could also wrap your widget with the Column widget and it will work only for the X coordinates.
(It has already been stated but poorly)

Flutter - Expanded within Flexible

My Row is composed of two Flexible and one of them is a Column I would like this column to take all the available vertical space like in my original design.
I tried to wrap the Column with an Expanded but it seems that I can't. I tried the property Flexible.tight of the flexible but it didn't work.
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
flex: 2,
child: SizedBox(
height: 130.0,
width: 130.0,
child: ClipRRect(
borderRadius: BorderRadius.circular(35.0),
child: CachedNetworkImage(
imageUrl: fakeOffers[index].imageUrl,
fit: BoxFit.cover,
placeholder: (context, url) => MC_Shimmer(),
),
),
),
),
Flexible(
flex: 3,
fit: FlexFit.tight,
child: Container(
child: Padding(
padding: const EdgeInsets.only(left: 15.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
fakeOffers[index].title,
style: MC_favoriteOfferTitle,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
Text(
fakeOffers[index].price.toStringAsFixed(0) + ' €',
style: MC_priceGradientDetail,
),
Text(
fakeOffers[index],
style: MC_favoriteOfferMeta,
),
],
),
),
),
)
],
);
You need to drop the first Flexible (it's fixed size anyway) and convert the second Flexible to an Expanded. This will let this Expanded take up all remaining space. Then, your column needs to take up all available space using CrossAxisAlignment.stretch.
So to solve the problem I just set the height of the column to 130.0 as I have a fixed size image.

Word-wrapping do not working with long text

Here is my widget:
return Card(
child: Container(
height: 150,
child: Row(
children: <Widget>[
Placeholder(
fallbackHeight: 100,
fallbackWidth: 100,
),
Container(
width: _deviceHeight,
color: Colors.red,
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Flexible(
child: Text(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasssssaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
overflow: TextOverflow.ellipsis,
maxLines: 4,
)),
// Expanded(flex: 8, child: Text("bbb")),
Flexible(child: Text("bbb")),
// Flexible(child: Text("aaa")),
],
),
)
],
),
));
I expected that text will be placed on new line, but I am getting overflow:
Wrap your inner Container with an Expanded to provide it with the available parent constraints, otherwise the Container has infinite height and will result in an overflow (because you are on landscape).
Expanded(
child: Container(
width: _deviceHeight,
color: Colors.red,
child: Column(
...
You could wrap the second element of the Row with Flexible, like this:
Row(
children: <Widget>[
Placeholder(..),
Flexible(
child: Container(
color: Colors.red,
child: Column(...
Inside the Row you need Placeholder to keep its width and Container width to be flexible.
Edit: And you should remove the width of the Container, since it would be flexible and it should take as much as possible to fit the screen.

Flutter put row into row

I need to create the following:
I could do it with code:
Row(
children: <Widget>[
Container(
width: 30
),
Column(
children: <Widget>[
Text("label"),
Container(
width: screenSize.width - 30, // <- this is problem
child: Row(
children: <Widget>[
Expanded( child: TextField() ),
Expanded( child: TextField() ),
],
),
),
],
),
],
);
Is it possible to do it in a different way, namely the line width: screenSize.width - 30?
You can use crossAxisAlignment inside Column widget and make it Stretch to get all remaining width in screen
Row(
children: <Widget>[
Container(
width: 30
),
Column(
crossAxisAlignment: CrossAxisAlignment.stretch, // <- Add this
children: <Widget>[
Text("label"),
Container(
child: Row(
children: <Widget>[
Expanded( child: TextField() ),
Expanded( child: TextField() ),
],
),
),
],
),],);
[Please read official flutter documentation of Column widget]
Column Widget
CrossAxisAlignment
Solution
Row(
children: <Widget>[
Container(
color: Colors.red,
width: 50,
),
Expanded(
child: Column(
children: <Widget>[
Text("label"),
Expanded(
child: Row(
children: <Widget>[
Expanded(
child: TextField()
),
Expanded(
child: TextField()
),
],
),
),
],
),
),
],
);
Explanation
It is about where you place Expanded instances.
You have a row, which can fill its parent if it included an Expanded child. So we defined the size of one of its children (Container), and the other is simply Expanded. The same goes for the Column child ..
Maybe starting with a simpler example makes it easier to understand. Please refer to this useful answer.
Output
P.S. Welcome to StackOverFlow, Dmitry!