I am trying to display some children inside a column, they are properties of an object. However, one of the properties sometimes has a null value, so I want to make a validation. If the value of this property is null, I don't want to display anything. The answer it's not as easy as saying "just use a ternary operator and put an empty Container() instead". The container takes up space even if it is almost imperceptible. The same happens with Visibility. Empty Text, works the same. And so on. Here is my code:
Container(
height: heightOfContext,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(5.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: FittedBox(
fit: BoxFit.fill,
child: FadeInImage(
placeholder: AssetImage(
"assets/images/loading.png"),
image: NetworkImage(
products[index].file_url),
),
),
),
),
///HERE IS THE ISSUE, AT THE LAST CHILD
Expanded(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: [
Text(
'Modelo: ${products[index].description}',
style: TextStyle(
fontWeight: FontWeight.bold),
),
Text(
'Producto: ${products[index].colorName}'),
Text(
'Color: ${products[index].price}'),
Text(
'Categoría: ${products[index].categoryName}'),
productsSearchList[index].catalogue != null
? Text(
'Catálogo: ${products[index].catalogue}')
: Container(),
],
),
),
),
],
),
),
There are 2 options to fix this:
Did you try SizedBox.shrink or Container(height: 0, width: 0)?
The easiest way is to use an if statement within the column:
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: [
Text(
'Modelo: ${products[index].description}',
style: TextStyle(
fontWeight: FontWeight.bold),
),
Text(
'Producto: ${products[index].colorName}'),
Text(
'Color: ${products[index].price}'),
Text(
'Categoría: ${products[index].categoryName}'),
if(productsSearchList[index].catalogue != null) Text(
'Catálogo: ${products[index].catalogue}')
],
),
You can define a boolean variable mean
If data fetched correctly set that variable true and show your container if not ,means that variable is false then dont show the container.(with ?: operators)
Related
I'm trying to make a menu for a reastaurant like this one : -
I'm using Flutter and this is my code:
return Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
title: Row(
children: [
Expanded(child: Text( text, style: style, )),
const SizedBox( width: 15 ),
Text( '\$ $price', style: style,),
],
),
),
Divider( color: Colors.white.withOpacity( 0.5 ),),
],
);
But this is the result that I'm getting : -
Please, any help will be welcome.
And thanks in advance.
The result that you want to achieve can be done just by using the row widget, you don't have to wrap it up with ListTile. I am writing the code snippet of Row widget for you. You can copy paste it and it will work. Additionally I see that you are generating it in the column widget. If you have a dynamic array then I suggest that you use ListView Divider instead. It will have a divider to add between your rows as well. You can find more about it on flutter official documentation.
Row(
children:[
//You may add some padding to Text for better looking UI.
Text("Chicken Masala"),
Expanded(child:Divider()),
Text("180")
])
Just replace your column's children with this row and you will be able to see it.
I solved your issue like this:
Output of your issue : -
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
title: Row(
children: [
const Text(
'Cheese Burger',
),
Expanded(child: Text('.' * 100, maxLines: 1)),
const Text(
'\$ 10',
),
],
),
),
const SizedBox(
height: 10,
),
ListTile(
title: Row(
children: [
const Text(
'Chicken Masala Soup',
),
Expanded(child: Text('.' * 100, maxLines: 1)),
const Text(
'\$ 10',
),
],
),
),
],
),
#Ramji, #Dhruvil Patel, I try your code and it work fine, but it was making an overflow when the text was long, so I made some changes in your example and I got what I was looking for.
Thanks a lot for you help.
Here is what I dit.
return SizedBox(
width: double.infinity,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
Expanded( child: Text( text, style: style, maxLines: 2, overflow: TextOverflow.ellipsis, ) ),
],),
Row(
children: [
Expanded(
child: Text(
'.' * 150,
style: style,
maxLines: 1,
overflow: TextOverflow.fade,)),
SizedBox(
width: 80,
child: Text(
'\$ $price',
style: style,
textAlign: TextAlign.right,)),
],
),
// Divider( color: Colors.white.withOpacity( 0.5 ),),
],
),
);
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,
),
);
The layout have uses column with Text and Image. The data change based from a list and some text/image are nil. How to make the container takes the same height when only one data is present?
Thanks.
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
color: Colors.red,
child: Column(
children: [
Text(
'This is Container/Column1. It have two widgets, Text and Image. How to make the height of the container same even if one the the widget is removed/null?',
),
Image.asset('assets/index.jpg')
],
),
),
Container(
color: Colors.green,
child: Column(
children: [
Text('This is Container/Column2. This will have additional widgets.'),
SizedBox(
width: double.maxFinite,
child: TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundColor: Colors.white,
),
child: Text('Next Button',
),),),],),),],),
first approach: add a fixed height to your container
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
// this will give the container a fixed height of 0.4 from the screen height
height: MediaQuery.of(context).size.height * 0.4,
color: Colors.red,
child: Column(
children: [
Text(
'This is Container/Column1. It have two widgets, Text and Image. How to make the height of the container same even if one the the widget is removed/null?',
),
Image.asset('assets/index.jpg')
],
),
),
Container(
color: Colors.green,
child: Column(
children: [
Text('This is Container/Column2. This will have additional widgets.'),
SizedBox(
width: double.maxFinite,
child: TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundColor: Colors.white,
),
child: Text(
'Next Button',
),
),
),
],
),
),
],
),
second approach: if one of them is null add a SizedBox() with your prefered height
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height * 0.4,
color: Colors.red,
child: Column(
children: [
someCondition ? Text(
'This is Container/Column1. It have two widgets, Text and Image. How to make the height of the container same even if one the the widget is removed/null?',
) : SizedBox(height : 40)
someCondition ? Image.asset('assets/index.jpg') : SizedBox(height : 40)
],
),
),
Container(
color: Colors.green,
child: Column(
children: [
Text('This is Container/Column2. This will have additional widgets.'),
SizedBox(
width: double.maxFinite,
child: TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundColor: Colors.white,
),
child: Text(
'Next Button',
),
),
),
],
),
),
],
);
One way is to wrap column with Expanded. Second is to have fixed height for contained. If you have this problem with ListView inside another widget and have problems, use shrinkWrap as true inside a ListView. And again for your problem (which person above failed to understand) is that you need or fixed value for height or use Expanded (as much space as possible) or Flexible (least space possible).
I try to fit my Cloum child of the expantion Card into his expanded Container. It always overflow his Card perent.
I tried a few things like putting the container in a FittedBox but nothing is working. So my goal is to make the column alway fitting in the expanded part of the card, or that the Card expand more if there are to many children in the Column. Can anybuddy tell me this magic trick? Thanks a lot !
enter image description here
ExpansionCard(
leading: CircleAvatar(
child: Text('1000'),
backgroundColor: Colors.black,
),
borderRadius: 20,
background: Image.asset(
"assets/images/unnamed.jpg",
fit: BoxFit.cover,
),
title: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("Freefly Sprung mit Carlo ",
style: jumpCardHeaderStyle),
Text(
DateFormat.yMMMd().format(DateTime.now()),
style: jumpCardDateStyle,
),
],
),
),
children: <Widget>[
FittedBox(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 7),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Exit Alt. : 4000m", style: kJumpTextStyle),
Divider(),
Text("Dpl. Alt. 1000m", style: kJumpTextStyle),
Divider(),
Text("Time FF 42sec", style: kJumpTextStyle),
Text("AVG.Speed T 127MPH", style: kJumpTextStyle),
Text("AVG.Speed T 127MPH", style: kJumpTextStyle),
],
),
),
),
)
],
),
Have you tried to use a card that has a Wrap object as a child? This should allow you to contain everything you need
Card(
child: Wrap(
children: []
))
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.