How to Automatically Scroll down when expanding ExpansionTile
You can create your own ScrollController and pass it to ListView, then when ExpansionTile expands, use onExpansionChanged to animate the controller and scroll a bit down
class ListViewExample extends StatefulWidget {
ListViewExample({Key key}) : super(key: key);
@override
_ListViewExampleState createState() => _ListViewExampleState();
}
class _ListViewExampleState extends State<ListViewExample> {
final ScrollController scroll = ScrollController();
@override
void dispose() {
scroll.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListView(
controller: scroll,
children: [
ListTile(
subtitle: Image.asset('assets/images/lunch-logo.jpg'),
title: ElevatedButton(
child: Text('Back'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HomeRoute()),
);
},
),
),
ListTile(
//leading: Image.asset('assets/images/lunch-logo.jpg'),
subtitle: Text('Enjoy our Lunch Options!',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue,
fontWeight: FontWeight.w600,
) ,
textAlign: TextAlign.center ,
),
),
ExpansionTile(
leading: Text(
'Starters',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue,
fontWeight: FontWeight.w600,
),
),
onExpansionChanged: (value) {
if (value)
scroll.animateTo(120, //this is a hardcoded value, would need some tweaking
duration: const Duration(milliseconds: 300),
curve: Curves.linear);
},
children: [
... //Your widgets
],
)
],
);
}
}
onExpansionChanged returns true when its expanding and false when collapsing, you can use those values and check the scroll offset to know if you need to animate the scroll to move downward
John
Updated on December 01, 2022Comments
-
John over 1 year
I am making my first Flutter App; enjoying it thus far. One annoying thing that I can not quite put my finger on, is that I have some ExpandedTiles, like so:
However, when the tile is expanded, the screen stays in the same position; like so:
What I would like, is if the app is scrolled down aa little bit when the ExpandedView is expanded.
I found this previous question, How to scroll an ExpansionTile / Listview when a tile is expanded? but that is a little different in that it just creates a list of the same items every time. I want the same functionality, but for 3 or 4 unique lists.
Widget build(BuildContext context) { final title = 'Lunch Menu'; return MaterialApp( title: title, home: Scaffold( appBar: AppBar( title: Text(title), ), body: ListView( children: <Widget>[ ListTile( subtitle: Image.asset('assets/images/lunch-logo.jpg'), title: ElevatedButton( child: Text('Back'), onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => HomeRoute()), ); }, ), ), ListTile( //leading: Image.asset('assets/images/lunch-logo.jpg'), subtitle: Text('Enjoy our Lunch Options!', style: TextStyle( fontSize: 18.0, color: Colors.blue, fontWeight: FontWeight.w600, ) , textAlign: TextAlign.center , ), ), ExpansionTile( leading: Text( 'Starters', style: TextStyle( fontSize: 18.0, color: Colors.blue, fontWeight: FontWeight.w600, ), ), children:<Widget>[ ListTile( leading: Image.asset('assets/images/food/image1.png'), title: Text('Title1'), isThreeLine: true, subtitle: Text('Description 1') , ),ListTile( leading: Image.asset('assets/images/food/image2.png'), title: Text('Title2'), isThreeLine: true, subtitle: Text('Description2') , ),
Would appreciate if someone can give me a pointer on how to implement the scroll controller correctly.
-
John over 3 yearsThank you, this is pretty good. One thing that isn't quite right, is when it expands, it scrolls to the desired position; but then 'frisbees' back to the initial spot. Should I try playing with that 120? I made it bigger and smaller, but same effect.
-
EdwynZN over 3 yearsMaybe adding a future delayed to wait the expanded tile to finish the animation before scrolling