I am trying to implement this scroll animation (GIF below). But, after extensive searching online, I haven't found any specific information to this problem. I looked at the ScrollPhysics
class but I don't think that's the right path. My idea is to have transparent separators in between widgets and then to change the height of each separator to create the desired "illusion". I would appreciate any suggestions on how to implement this thing.
Update:
Here's a full example on DartPad that you can try yourself: https://dartpad.dev/26671eeec673a663b26c5dda68c934c2
Original:
Here's a simple example on how to approach this using NotificationListener
:
class Example extends StatefulWidget {
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
double spaceBetween = 10.0;
final _duration = Duration(milliseconds: 200);
_onStartScroll(ScrollMetrics metrics) {
// if you need to do something at the start
}
_onUpdateScroll(ScrollMetrics metrics) {
// do your magic here to change the value
if(spaceBetween == 30.0) return;
spaceBetween = 30.0;
setState((){});
}
_onEndScroll(ScrollMetrics metrics) {
// do your magic here to return the value to normal
spaceBetween = 10.0;
setState((){});
}
@override
Widget build(BuildContext context) {
return NotificationListener<ScrollNotification>(
onNotification: (scrollNotification) {
if (scrollNotification is ScrollStartNotification) {
_onStartScroll(scrollNotification.metrics);
} else if (scrollNotification is ScrollUpdateNotification) {
_onUpdateScroll(scrollNotification.metrics);
} else if (scrollNotification is ScrollEndNotification) {
_onEndScroll(scrollNotification.metrics);
}
return true; // see docs
},
child: ListView(
children: [
Container(height: 100, width: 100, color: Colors.red),
AnimatedContainer(duration: _duration, height: spaceBetween),
Container(height: 100, width: 100, color: Colors.blue),
AnimatedContainer(duration: _duration, height: spaceBetween),
Container(height: 100, width: 100, color: Colors.red),
AnimatedContainer(duration: _duration, height: spaceBetween),
Container(height: 100, width: 100, color: Colors.blue),
AnimatedContainer(duration: _duration, height: spaceBetween),
Container(height: 100, width: 100, color: Colors.red),
AnimatedContainer(duration: _duration, height: spaceBetween),
Container(height: 100, width: 100, color: Colors.blue),
AnimatedContainer(duration: _duration, height: spaceBetween),
Container(height: 100, width: 100, color: Colors.red),
AnimatedContainer(duration: _duration, height: spaceBetween),
Container(height: 100, width: 100, color: Colors.blue),
AnimatedContainer(duration: _duration, height: spaceBetween),
Container(height: 100, width: 100, color: Colors.red),
AnimatedContainer(duration: _duration, height: spaceBetween),
Container(height: 100, width: 100, color: Colors.blue),
AnimatedContainer(duration: _duration, height: spaceBetween),
],
),
);
}
}
I used AnimatedContainer here but you can use explicit animations if you want too.