Reputation: 3414
I am using an animatedContainer to reveal a listView.builder() when a button is pressed. It's a simple sublist to show, but the problem is the height of the ListView builder is not known by me to pass to animatedContainer height Constraint. Do there any way to get the height of the listview builder dynamically or any other method to achieve this?
What I need?
height:
property, so
it will wrap around the child automaticallySomething like this: https://getbootstrap.com/docs/4.0/components/collapse/
AnimatedContainer(
duration: Duration(milliseconds: 200),
curve: Curves.easeIn,
height: _expanded ? 150 : 0, // This height I cannot set here explicitly. I need to set dynamically like, get child's height
child: ListView.builder(
key: listViewKey,
shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: const NeverScrollableScrollPhysics(),
itemCount: loadedSubCategories.length,
itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
value: loadedSubCategories[i],
child: SubCategoryItem(loadedSubCategories[i].categoryId,
loadedSubCategories[i].subCategoryId)),
),
),
While I am using a normal Container(), I wont set the height:
property so that it will get the child's height automatically but I need the height because I would like to expanded the subcategories in a animated way.
Each element of SubCategories having different heights and the number of Subcategories is also Unknown. so calculating the height with subcategories.length
is also not possible.
Any advice is really appreciated, Thank you
Upvotes: 1
Views: 5562
Reputation: 174
Instead of using AnimatedContainer
you can use AnimatedCrossFade
Like this
AnimatedCrossFade(
duration: Duration(milliseconds: 200),
curve: Curves.easeIn,
crossFadeState: _expanded ? CrossFadeState.showFirst : CrossFadeState.showSecond,
firstChild: ListView.builder(
key: listViewKey,
shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: const NeverScrollableScrollPhysics(),
itemCount: loadedSubCategories.length,
itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
value: loadedSubCategories[i],
child: SubCategoryItem(loadedSubCategories[i].categoryId,
loadedSubCategories[i].subCategoryId)),
),
secondChild: Container(),
),
This works for me.
Upvotes: 1
Reputation: 510
you can achieve what you're looking for with AnimatedSize widget .
it automatically creates a widget that animates itself to match it's child size and you don't need to provide any height or width to it. you just need to wrap your widget with it
AnimatedSize(
curve: Curves.fastOutSlowIn,
duration: Duration(milliseconds: 300),
vsync: this,
child: Container()
)
you can have look at for more information.
Upvotes: 18
Reputation: 1290
Using the Curves.fastLinearToSlowEaseIn and SizeBox.shrink to achieve your requirement
@override
Widget build(BuildContext context) {
return SafeArea(
bottom: true,
top: false,
child: Scaffold(
appBar: AppBar(
title: Text('Container'),
),
body: Column(
children: [
Center(
child: FlatButton(
onPressed: () {
setState(() {
_expanded = true;
});
},
child: Text('expand')),
),
AnimatedContainer(
duration: Duration(seconds: 2),
curve: Curves.fastLinearToSlowEaseIn,
height: _expanded ? 150 : 0,
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: Colors.white
),
child: _expanded ? ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: const NeverScrollableScrollPhysics(),
itemCount: 3,
itemBuilder: (ctx, i) {
return ListTile(
title: Text(i.toString()),
);
}) : SizedBox.shrink(),
),
],
)
),
);
}
Upvotes: 0