Flutter ScrollPhysics Variations & Use Cases

Roaa Khaddam
4 min readJan 29, 2022

--

The ‘physics’ widget param is found in all scrollable widgets (SingleChildScrollView, CustomScrollView, NestedScrollView, ListView, GridView, TabBarView, ListWheelScrollView …etc) In this article, I will go over the variation of ScrollPhysics that this param can take and what that variation does.

ScrollPhysics Types Covered:

1. NeverScrollableScrollPhysics

2. AlwaysScrollableScrollPhysics

3. BouncingScrollPhysics

4. ClampingScrollPhysics

5. FixedExtentScrollPhysics

You can find code implementations of all of those variations here.

1. NeverScrollableScrollPhysics

As the name suggests, using this ScrollPhysics prevents scrolling inside your scrollable widget. You might think: Why would I need this?! Well, in some cases your will.

An example would be if you have a ListView (scrollable №1) inside a Column inside a SingleChildScrollView (scrollable №2)

return SingleChildScrollView(
padding: const EdgeInsets.symmetric(vertical: 20),
child: Column(
children: [
//...,
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true, // This is important ⬇️
itemCount: 20,
itemBuilder: (c, i) => ListItem(),
),
],
),
);

The problem here with having 2 scrollables is that you can’t scroll the ListView unless you tap and scroll inside it, and you can scroll the SingleChildScrollView only when you tap and scroll outside the ListView. Resulting in not being able to scroll the page when you scroll the area above of the ListView outside of view, thus being stuck. This easily solved by giving NeverScrollableScrollPhysics to the ListView

You can see this in action in this Gif:

Flutter With/Without NeverScrollableScrollPhysics Preview
With/Without NeverScrollableScrollPhysics Preview

IMPORTANT: the shrinkWrap: true in the ListView above is very important because here the ListView’s height is unbounded to it not having a parent with constrained height (Due to the SingleChildScrollView)

Click here for full source code of the NeverScrollableScrollPhysics implementation.

2. AlwaysScrollableScrollPhysics

This forces scrolling even when the content of the scrollable widget’s content doesn’t exceed the height of the screen, so even when scrolling is not needed.

You might need it when you want to use a RefreshIndicator widget, this widget will not show unless it’s content is scrollable, but if you have content that doesn’t exceed the height of the screen but you want to wrap it with a RefreshIndicator widget, you’ll definitely need to use the AlwaysScrollableScrollPhysics.

return RefreshIndicator(
onRefresh: refreshContent, // Future
child: ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
itemCount: 20,
itemBuilder: (c, i) => ListItem(),
),
);

Click here for full source code of the AlwaysScrollableScrollPhysics or the RefreshIndicator implementations

3. BouncingScrollPhysics

The scrolled content bounces back into place when you reach the end (top or bottom). This is the default behavior you see on iOS.

physics: const BouncingScrollPhysics(),
Flutter BouncingScrollPhysics Preview
BouncingScrollPhysics Preview

4. ClampingScrollPhysics

Prevents scrolling beyond the content, so basically prevents the behavior seen in BouncingScrollPhysics. This is the default behavior you see on Android

physics: const ClampingScrollPhysics(),
Flutter, ClampingScrollPhysics Preview
ClampingScrollPhysics Preview

5. FixedExtentScrollPhysics

This only works with a FixedExtentScrollController used with ListWheelScrollViews to give you snapping scroll behavior

class FixedExtentScrollPhysicsExample extends StatelessWidget {  final FixedExtentScrollController fixedExtentScrollController = FixedExtentScrollController();

@override
Widget build(BuildContext context) {
return ListWheelScrollView(
controller: fixedExtentScrollController,
physics: const FixedExtentScrollPhysics(),
itemExtent: MediaQuery.of(context).size.height,
overAndUnderCenterOpacity: 0,
children: [ /* children */ ],
);
}
}

Here’s a preview for a ListWheelScrollView with & without the FixedExtentScrollPhysics.

  1. On the left (without), you can scroll freely and stop the scrolling at any position
  2. On the right (with) the scroll doesn’t stop the scrolling and snaps to make the list item centered.
Flutter With/Without FixedExtentScrollPhysics Preview
With/Without FixedExtentScrollPhysics Preview

Click here for full source code of FixedExtentScrollPhysics implementation

And there you have it! I hope this was useful to you 🙌🏼. Feel free to leave your comments regarding any of the above variations and any use cases you might find useful yourselves 🤓

--

--

Roaa Khaddam

Software Engineer | 💙 Flutter / Dart Google Developer Expert