Flutter expand/collapse a container with dynamic height - flutter

I'm trying to expand and collapse a container dynamically based on the data received. Currently I'm doing it like this:
AnimatedContainer(
duration: const Duration(milliseconds: 550),
margin: EdgeInsets.symmetric(horizontal: 16),
constraints: !isExpanded
? BoxConstraints(
maxHeight: MyUtils.height(221),
minHeight: MyUtils.height(221))
: BoxConstraints(
minHeight: MyUtils.height(321),
maxHeight: MyUtils.height(1000)),
decoration: BoxDecoration(
color: containerColor,
borderRadius: const BorderRadius.all(Radius.circular(8))),
child: Column(children: [
Container(
margin: EdgeInsets.fromLTRB(8, 10, 8, 20),
height: MyUtils.height(36),
width: double.infinity,
decoration: BoxDecoration(
color: containerColor3,
borderRadius: BorderRadius.all(Radius.circular(6))),
),
InkWell(
onTap: () => expand(),
child: Text(
'Show',
style: TextStyle(color: Colors.white),
),
)
]),
),
The function expand() is as simple as changing the bool of isExpanded. I managed to collapse/expand the Container, but the problem is that the Container expanded until maxHeight, I want to make the expanded height dynamic based on the items inside. So I tried to set only minHeight and hoping that maxHeight will follow the items, but I got an error because maxHeight is not set.
Is there any way I can achieve this?

By default, Column tries to be as much as possible. You can control this behavior by specifying mainAxisSize param.
Column(
mainAxisSize: MainAxisSize.min, // ADD THIS LINE TO YOUR COLUMN
children: [...]
)
I recommend that you read this article https://docs.flutter.dev/development/ui/layout/constraints

Try to Do this Hope this will be helpful:
Table(children: [
TableRow(children: [
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
alignment: Alignment.center,
child: Text('Widget'),
),
Container(
alignment: Alignment.center,
child: Text('Widget'),
),
],
),
]),
]),

AlignedGridView.count(
crossAxisCount: 4,
mainAxisSpacing: 4,
crossAxisSpacing: 4,
itemBuilder: (context, index) {
return Tile(
index: index,
extent: (index % 7 + 1) * 30,
);
},
);
use this package flutter_staggered_grid_view

Related

How can stretch height of one of child widget according to another widget in a row?

I wanted to get same dynamic height of right widget to left widget in Row Widget.Below I was attaching screenshot of my expected design. Could you help how can do that.
We can see right side date widget is expanding , So I wanted to get the height of left side widget(blue and purple) same as right side widget.
If left side image widget is not possible to expand the height then is any there any possible to create custom widget, Any solution is welcome.
Thanks in advance.
Row(
children: [
Align(
alignment: Alignment.topCenter,
child: Container(
constraints: BoxConstraints(
minHeight: 40.0,
maxHeight: 50.0,
/*maxWidth: 10,
minWidth: 10,*/
),
padding: EdgeInsets.only(top: 0.0),
//height: 98,
width: 20,
child: ShaderMask(
shaderCallback: (bounds) {
return LinearGradient(
colors: [Color(0xff12229F), Color(0xff615FDF)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
).createShader(bounds);
},
child: ImageIcon(
AssetImage('assets/images/reservations/small_timeline.png'),
color: Colors.white,
size: 40,
),
),
),
),
Expanded(
child: Column(
children: [
pickup(data),
dropoff(data),
],
),
),
],
),
After Using IntrinsicHeight
I was unable to remove default padding around the icons
IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.only(top: 0,bottom: 0),
child: Row(
children: [
Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 4),
child: Icon(
Icons.fiber_manual_record,
size: 18,
color: Color(0xff11219E),),
),
Flexible(
child: Container(
decoration: BoxDecoration(
gradient:
LinearGradient(colors: [Color(0xff11219E), Color(0xff6F6AEB)]),
),
width: 4,
),
),
Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Icon(
Icons.fiber_manual_record,
size: 18,
color: Color(0xff6F6AEB),),
),
],
),
Expanded(
child: Column(
children: [
pickup(data),
dropoff(data),
],
),
),
],
),
),
),
It seems to me that Expanded could be used to expand your widget to full availabe height.
Keep in mind that the Row width will distribution will also expand, since no flex parameter is provided.
You already have an Expanded on the right widget so just add the other one and provide a flex value for both of them.
Some thing like 10 for left and 90 for right should work for you :)

Flutter SingleChildScrollView Not Working

I want the scroll page to work when the keyboard is opened, but it does not work when the keyboard is opened, the user needs to see what he is typing, I am making a login page, when the keyboard opens, the scrollview will work, I used the same code in my other project, but it works there, it just does not work in my project, what could be the reason for this?
Edit: What I want to do is, when the keyboard pops up, I should be able to scroll the screen
My Code:
Scaffold(
resizeToAvoidBottomInset: true,
body: Stack(
children: [
SafeArea(
child: SingleChildScrollView(
controller: scrollController,
child: Container(
padding: MediaQuery.of(context).size.width > webScreenSize
? EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width / 3)
: const EdgeInsets.symmetric(
horizontal: 15,
),
height: deviceHeight,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(top: 35.0),
child: SvgPicture.asset(
"assets/bahce.svg",
color: primaryColor,
height: 64.0,
),
),
Container(
height: deviceHeight * 0.65,
width: double.infinity,
margin: EdgeInsets.symmetric(horizontal: 20),
child: LayoutBuilder(
builder: (ctx, contsraints) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: contsraints.maxHeight * 0.01,
),
Container(
.......
),
SizedBox(
height: contsraints.maxHeight * 0.05,
),
Container(
height: contsraints.maxHeight * 0.12,
...................
),
Container(
width: double.infinity,
height: contsraints.maxHeight * 0.12,
......button
),
SizedBox(
height: contsraints.maxHeight * 0.15,
),
RichText(
text: TextSpan(
......,
children: [
TextSpan(
..onTap = navigateToSignup,
),
],
),
),
],
);
},
),
),
],
),
),
),
),
],
),
);
Remove other widgers directly use sigle child scroll view as a child of body
Remove the Stack widget after your Scaffold Widget. It is an un-used widget in your code.
Scaffold
SafeArea
SingleChildScrollView
Other widgets
If SingleChildScrollView works, let me know.

Flutter design with timeline

I'm trying to make this drawing but I'm struggling.
I don't understand how to make the white block of information dynamic. That is to say that it automatically adapts to the size in height of the elements it contains.
I am for the moment obliged to give a defined height (here 200), I would like the size to be automatic. Moreover if I do not give a defined size my gray line on the left side disappears.
The design :
ListTile(
title : Column(
children: [
Container(
width: double.infinity,
child: Row(
children: [
Container(
width: 50,
alignment: Alignment.center,
child: Container(
width: 20,
height: 20,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40),
border: Border.all(
width: 5,
color: Colors.blue,
style: BorderStyle.solid
)
),
),
),
Text('9:00 am - 9:15 am')
],
)
),
Container(
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
width : 50,
alignment: Alignment.center,
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
color: Colors.grey,
width: 3,
height : 200 // if I remove the size it desappear
),
],
),
),
),
Expanded(
child: Container(
margin: EdgeInsets.symmetric(vertical :10),
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
color: Colors.white,
child: Column(
children: [
Text('Titre'),
Text('Info 1'),
Text('Info 2')
],
),
),
)
],
),
),
)
],
),
),
You can try this package for timelines https://pub.dev/packages/timeline_tile.
This package also automatically Sizes your widget height and width.
And for Automatically Sizing your widgets next time, You could use Expanded widget at most places in your code.
Note: An Expanded widget must be a descendant of a Row, Column, or Flex, So Use it carefully.
I think it's much easier with this package, timelines.
TimelineTileBuilder.connected(
connectionDirection: ConnectionDirection.before,
itemCount: processes.length,
contentsBuilder: (_, index) {
//your Container/Card Content
},
indicatorBuilder: (_, index) {
if (processes[index].isCompleted) {
return DotIndicator(
color: Color(0xff66c97f),
child: Icon(
Icons.check,
color: Colors.white,
size: 12.0,
),
);
} else {
return OutlinedDotIndicator(
borderWidth: 2.5,
);
}
},
connectorBuilder: (_, index, ___) => SolidLineConnector(
color: processes[index].isCompleted ? Color(0xff66c97f) : null,
),
),
),

Text align in a box decoration

I have this box decoration used for showing the reviews but I don't know what I should use to align the text properly. This is how it looks right now:
I want the username ("La fottaria to have some space left) I used Align( Alignment(8,3)) but it doesn't change the position.
return ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
return Container(
width: 200,
margin: EdgeInsets.only(
top: 8, bottom: 8, right: 12),
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 2,
spreadRadius: 1)
], borderRadius: BorderRadius.circular(4)),
child: Column(
children: [
Row(
children: [
CircleAvatar(
backgroundImage: NetworkImage(
snapshot.data.documents[index]
.data["avatarUrl"]),
),
Align(
alignment: Alignment(8, 3),
child: Text(snapshot
.data
.documents[index]
.data["name"]),
)
],
),
_buildRatingStars(snapshot.data
.documents[index].data["rating"]),
Text(snapshot
.data.documents[index].data["text"])
],
),
);
}
);
Inside the Row widget, you can use a SizedBox with width property.
It will give some space.
Row(
children: [
CircleAvatar(
backgroundImage:
NetworkImage(snapshot.data.documents[index].data["avatarUrl"]),
),
//insert here
SizedBox(
width: 20.0,
),
Align(
alignment: Alignment(8, 3),
child: Text(snapshot.data.documents[index].data["name"]),
)
],
)
You can remove the Align widget if you want.
Instead of align widget, I suggest you to use Container widget like this:
Container(
margin: const EdgeInsets.only(left: 15),
child: Text(snapshot
.data
.documents[index]
.data["name"]),
)
Use Align
Example:
DecoratedBox(
decoration: BoxDecoration(
border: Border.all(
color: Colors.blue,
width: 1,
),
borderRadius: BorderRadius.circular(4),
),
child: Align(
alignment: Alignment.center, // align type
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 15),
child: Text(
title,
style: TextStyle(fontSize: 17, color: Colors.blue),
),
),
),
)
You can use some inbuilt property of rows i.e Main Axis Alignment and Cross Axis Alignment to align its children.For eg:
Row(
mainAxisAligment:MainAxisAlignment.spaceEvenly,
crossAxisAligment:CrossAxisAligment.center,
children: [
CircleAvatar(
backgroundImage:
NetworkImage(snapshot.data.documents[index].data["avatarUrl"]),
),
SizedBox(
width: 20.0,
),
Text(snapshot.data.documents[index].data["name"]),
],
)
You can wrap the text widget inside padding widget also to align according to your needs.

Flutter - How create Container with width match parent?

I use this simple widget in my Flutter app:
FlatButton(
child: Column(
children: <Widget>[
Image.asset(assets, height: 40, width: 40),
Text('Title'),
//my color line
Container(
height: 5,
width: ?,
color: Colors.blue[800],
)
],
)
)
I need color line (in buttom), with width match parent. but I don’t know how to do it.
Container(
height: 5,
width: double.infinity,
color: Colors.blue[800],
)
Use IntrinsicWidth
FlatButton(
child: IntrinsicWidth(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Image.asset(assets, height: 40, width: 40),
Text('Title'),
//my color line
Container(
height: 5,
width: ?,
color: Colors.blue[800],
)
],
))
)
Some cheatsheet
Two ways of doing this
ConstrainedBox:
It Creates a widget that imposes additional constraints on its child, which internally uses SingleChildRenderObjectWidget to add constraints over the child widget.
ConstrainedBox(
constraints:
const BoxConstraints(minWidth: double.infinity, maxHeight: 10),
child: Container(
color: Colors.blue,
),
),
SizedBox:
SizedBox simply creates a box with a given width/height and doesn't allow the child to go beyond given dimensions. It also used SingleChildRenderObjectWidget to decide the child render area
SizedBox(
width: double.infinity,
height: 5,
// height: double.infinity,
child: Container(
color: Colors.blue,
),
),
Container in a Column with no child will always expand. if you do add a child it will wrap it.
Also if you don't constrain your Column in the button it will also grow to full available height.
My suggestion to you is instead of putting an empty Container in your button's Column, rather wrap the button with a Container and give it a bottom border. This will give you your colored line on the bottom.
Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(width: 5, color: Colors.blue[800]),
),
),
child: FlatButton(
onPressed: () {},
child: Column(
mainAxisSize: MainAxisSize.min, // prevent Column to expand full height
children: <Widget>[
Icon(Icons.cake, size: 40),
Text('title'),
],
),
),
),