Flutter: child of ConstrainedBox donot display - flutter

When I set maxHeight of BoxConstraints to 100 or other value, the Image can display. But when I set maxHeight to 0, the Image is not visible. How to make it visible?
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ConstrainedBox(
constraints: BoxConstraints(maxHeight: 0),
child: Row(
children: <Widget>[
Text('world'),
IconButton(icon: Icon(Icons.ac_unit),),
Image.network(
'http://cdn.nanxiongnandi.com/bing/KingfishersTaipei_ZH-CN13235647615_1366x768.jpg'),
],
),
),
),
);
}
result

I see that your image has the problem to load. Check the below code with maxHeight to 100. It is working
return Scaffold(
body: Center(
child: ConstrainedBox(
constraints: BoxConstraints(maxHeight: 100),
child: Row(
children: <Widget>[
Text('world'),
IconButton(
icon: Icon(Icons.ac_unit),
),
Image.network(
'https://raw.githubusercontent.com/flutter/website/master/src/_includes/code/layout/lakes/images/lake.jpg'),
],
),
),
),
);

Related

Flutter: Expanded overriding ConstrainedBox

I need a Column to expand to a constrained width. So it expands until the maxWidth but doesn't mind being smaller if there isn't enough space. But the Expanded ignores the ConstrainedBox.
Row(
children: [
const Spacer(),
Expanded(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 50),
child: Column(
children: [
Expanded(child: Container(color: Colors.red)),
Expanded(child: Container(color: Colors.green)),
],
),
),
),
],
)
Here's my full code for context:
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: GetBuilder<TimerController>(
builder: (_) => CustomBackground(
color: _timerController.currentChild?.color ?? Colors.blue,
child: SafeArea(
child: Center(
child: Padding(
padding:
EdgeInsets.symmetric(horizontal: AppSizes.pagePadding),
child: OrientationBuilder(
builder: (context, orientation) =>
(orientation == Orientation.portrait)
? ConstrainedBox(
constraints: BoxConstraints(
maxWidth: AppSizes.maxWidth,
minWidth: AppSizes.minWidth,
),
child: Column(
children: [
SizedBox(height: AppSizes.pagePadding),
Expanded(child: TimerClock()),
Expanded(
child: Column(
children: [
NameText(),
ControlButtons(),
SizedBox(height: 25),
Expanded(child: QueueList()),
],
),
),
],
),
)
: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: AppSizes.maxWidth,
minWidth: AppSizes.minWidth,
),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: AppSizes.pagePadding),
child: TimerClock(),
),
),
),
SizedBox(width: AppSizes.pagePadding),
Expanded(
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: AppSizes.maxWidth, // this get's ignored
minWidth: AppSizes.minWidth,
),
child: Column(
children: [
Expanded(child: NameText()),
ControlButtons(),
SizedBox(height: 25),
Expanded(child: QueueList()),
],
),
),
),
],
),
),
),
),
),
),
),
),
);
}
And if I remove the Expanded, the Column has a fixed width (maxWidth) and throws an error if there isn't enough space.
Change the outer most Expanded to a Flexible. Then the child ConstrainedBox will be respected.
In my case I also added a width:double.infinity to the child of the Flexible to force the widget to always be as big as the maxWidth, and only reduce its size when there is no space.
My example:
Flexible(
child: Container(
constraints: BoxConstraints(maxWidth: screenWidth * 0.25),
width: double.infinity,
),
);
You are using Expanded in a Column widget which means that it will try to expand to fill the space vertically (based on the height of the parent not its width). As mentioned in the documentation of Expanded:
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).
source
And as you did not precise a maxHeight in your constraints it will be considered as double.infinity.

Flexible scrolling content on overflow

I want to have a container with a flexible body (red) height and a fixed button height (gray).
The complete container should be as small as possible and have a max height.
If the content is overflowing the max height it should be scrollable.
I'm new to flutter, so I have no idea how to achieve this.
I tried it with a ConstraintBox with maxHeight, but then the whole container is bigger then it have to be, when the content is small.
return Container(
child: Column(
children: [
ConstrainedBox(
maxHeight: 400
child: //SomeWidget that could overflow
),
Container(
height: 150,
child: Center(
child: TextButton(child: Text('OK'))
),
)
],
),
);
Can someone help?
You can set constraints of your Container. Also you can use Flexible and SingleChildScrollView
Container(
constraints: BoxConstraints(
maxHeight: 300,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: SingleChildScrollView(
child: Column(
children: [
//SomeWidget that could overflow
],
),
)),
Container(
color: Colors.amber,
height: 150,
child:
Center(child: TextButton(onPressed: () {}, child: Text('OK'))),
)
],
),
)
I've achieved it now, with that code:
Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: SingleChildScrollView(
child: //SomeWidget that could overflow
),
),
Container(
alignment: Alignment.bottomCenter,
child: TextButton(
child: Text('OK')
)
)
]
)
)
According to your UI i think this one will be perfect, and let me know if you need any changes. use constraints to change size.
final widgets = List.generate(
12,
(index) => Container(
height: 100,
color: index % 2 == 0 ? Colors.cyanAccent : Colors.greenAccent,
child: Text("item $index"),
),
);
#override
Widget build(BuildContext context) {
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) => Stack(
children: [
Align(
alignment: Alignment.topCenter,
child: SizedBox(
///* used 90% of screen for items
height: constraints.maxHeight * .9,
child: ListView(
children: [
Center(child: Text("inside listView")),
///your widgets
...widgets,
Center(child: Text("End of listView")),
],
),
),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
color: Colors.grey.withOpacity(.3),
///* used 10% of screen for Button
height: constraints.maxHeight * .1,
child: Center(
child: TextButton(
child: Text('OK'),
onPressed: () {},
),
),
),
),
],
),
),
);
}

ElevatedButton does not accept restrictions of SizedBox

Widget build(BuildContext context) {
var appBar = AppBar();
return Scaffold(
body:
Row(
children: [
Container(
color: Colors.green,
width: 800,
child: SizedBox(
width: 50,
child: ElevatedButton(child: Text("sdf"), onPressed: () {},),
)
),
Container(
child: Text("Hello"),
)
],)
);
}
I expected that size of button will be equal of SizedBox size
I can highly recommend taking a look at this official documentation about constraints: https://flutter.dev/docs/development/ui/layout/constraints
In your case, you have a Row which practically imposes infinite width. The Container as a direct child of your Row can set it's width to whatever you want but the Container will still pass down infinite width (as constraints) from the parent. Therefore you need to tell Flutter at this point, that you want to avoid this implicit given constraint - one working solution would be:
#override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
children: [
Container(
color: Colors.green,
width: 300.0,
child: UnconstrainedBox(
alignment: Alignment.centerLeft,
child: SizedBox(
width: 100.0,
child: ElevatedButton(
onPressed: () {},
child: Text('LOL'),
),
),
),
),
Text('WTF')
],
),
);
}

Unable to Align widget Using Align() Flutter

i am new to flutter and i Need help with align widget
Here have used alignment center for the TabBar widget and
alignment bottomRight for Text widget
and i didnt get the correct result here.
This is the Output image:
Source Code:
Widget build(BuildContext context) {
var screenSize = MediaQuery.of(context);
return SafeArea(
child: DefaultTabController(
length: 2,
child: Scaffold(
backgroundColor: Colors.amber,
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
Align(
*[**alignment: Alignment.bottomRight,**][1]*
child: Text("data"),
),
Align(
***alignment: Alignment.center,***
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: 300,
maxHeight: 60,
),
child: AppBar(
automaticallyImplyLeading: false,
bottom: TabBar(
tabs: [
Tab(
icon: Icon(Icons.directions_bike),
),
Tab(
icon: Icon(
Icons.directions_car,
),
),
],
),
),
),
),
ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 100,
maxWidth: 100,
),
child: Container(
color: Colors.blue,
),
)
],
),
),
),
);
}
For that please remove the mainAxisSize : MainAxisSize.min into the column widget.

Can't set ListView into LayoutBuilder Widget (Flutter)

I need to have some structure like this
I use LayoutBuilder to get the height of content (between App Bar and TabsBottomNavigation). Here i build Profile Info Container and want to build ListView with some List Tiles, but when I try to build it in Layout Builder I have errors in console.
If I create ListView out of LayoutBuilder it works!
Please help me to solve it.
My code below:
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Container(
height: viewportConstraints.maxHeight * .44,
color: Theme.of(context).primaryColor,
padding: EdgeInsets.only(bottom: 2),
child: Align(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildProfileImage(context),
SizedBox(height: 17),
Text(userName)
],
),
),
),
Expanded(
child: ListView(
children: <Widget>[
ListTile(
leading: Icon(Icons.print),
title: Text('asdad'),
)
],
),
)
],
),
),
);
},
);
}
Use below build method will work in your case. (I have checked and it's working, so I hope it will work in your case also and will fit in your requirement.)
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return Container(
child: Column(
children: <Widget>[
Container(
height: viewportConstraints.maxHeight * .44,
color: Theme.of(context).primaryColor,
padding: EdgeInsets.only(bottom: 2),
child: Align(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildProfileImage(context),
SizedBox(height: 17),
Text(userName),
],
),
),
),
SizedBox(height: 16),
Flexible(
child: ListView(
children: <Widget>[
Card(
child: ListTile(
leading: Icon(Icons.print),
title: Text('asdad'),
),
),
],
),
),
],
),
);
},
);
}
I think SingleChildScrollView is of no use in this case so I removed it but you can use it if you fill so.
You still need to do some UI improvement as per your wish as this is the basic structure as per your requirement.
Hope this will help you.
You are using the LayoutBuilder in a wrong way.
It's supposed to be used to change the layout with the size of the device and/or orientation.
What you are trying to do is best accomplished with MediaQuery:
MediaQuery.of(context).padding.top //APP bar height
MediaQuery.of(context).padding.bottom //Bottom bar height
MediaQuery.of(context).size.height //Screen height
Widget build(BuildContext context) {
return Column(
children:<Widget>[
Expanded(
child:LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Container(
height: viewportConstraints.maxHeight * .44,
color: Theme.of(context).primaryColor,
padding: EdgeInsets.only(bottom: 2),
child: Align(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildProfileImage(context),
SizedBox(height: 17),
Text(userName)
],
),
),
),
Expanded(
child: ListView(
children: <Widget>[
ListTile(
leading: Icon(Icons.print),
title: Text('asdad'),
)
],
),
)
],
),
),
);
},
),
),
]
);
}
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ListView(
shrinkWrap: true,
children: <Widget>[
new Container(
height: MediaQuery.of(context).size.height/3,
color: Theme.of(context).primaryColor,
padding: EdgeInsets.only(bottom: 2),
child: Align(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildProfileImage(context),
SizedBox(height: 17),
Text(userName)
],
),
),
),
new ListView(
shrinkWrap: true,
children: <Widget>[
ListTile(
leading: Icon(Icons.print),
title: Text('asdad'),
)
],
)
],
),
);
},
);
}
If you read the error log, it says non-zero flex incoming but constraints are unbounded. To understand that clearly, imagine Flutter is trying to draw pixels of something that not finite. That's the our problem.
Widgets like ListView or SingleChildScrollView are flex widgets and has no limits unlike Column or Row.
If you have children that sizes are not definite, then you have to define flex for your ListView. For that, you can use shrinkWrap or Flexible, Expanded widgets for both ListView itself or children.
And here is the my solution, simplified as much as possible:
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return ListView(
shrinkWrap: true, // That's it
children: <Widget>[
Container(
color: Theme.of(context).primaryColor,
height: viewportConstraints.maxHeight * .44,
padding: EdgeInsets.only(bottom: 2),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildProfileImage(context),
SizedBox(height: 17),
Text(userName)
],
),
),
ListTile(
leading: Icon(Icons.print),
title: Text('asdad'),
),
ListTile(
leading: Icon(Icons.print),
title: Text('asdad'),
),
ListTile(
leading: Icon(Icons.print),
title: Text('asdad'),
)
],
);
},
);
}
Meanwhile, you have too many children that does nothing. If you want different scrolling behavior inside the Profile Info and ListTiles parts, tell me because we will must create yet another ListView for achieve that.
Also if you share your buildProfileImage widget, we can optimize your code even further, because you may even not need the LayoutBuilder widget in this case.