tl;dr
You can remove the overscroll glow effect in Flutter using:
- A custom
ScrollBehavior
being wrapped with aScrollConfiguration
- Using
BouncingScrollPhysics
instance being set as thephysics
property of your scrollable widget GlowingOverscrollIndicator
widget with theshowLeading
andshowTrailing
properties set tofalse
(discouraged as there is bug preventing it from working properly right now)
It’s important to keep in mind that disabling this effect could make the app look less native.
Flutter provides several widgets that help developers add scrolling functionality to their apps. However, by default, some widgets such as ListView
and CustomScrollView
display an overscroll glow effect which is a visual indication that the user has reached the end of a scrollable widget.
While this overscroll glow can be great for the user to feel comfortable because of the familiar look, it can also be distracting or irritating in others. It also might not fit so well with the rest of the UI.
Default behavior
First, let’s consider the default behavior of a ListView
widget in Flutter on Android. When the user scrolls to the top or bottom of the list, a glow effect is visible, as the iconic image below is showing.
What’s the cause?
Flutter automatically adds a GlowingOverscrollIndicator
widget around any child widget of a scrollable widget on certain platforms by default, as demonstrated in the following code snippet taken from the ScrollBehavior
abstract
class
.
1 /// Applies a [GlowingOverscrollIndicator] to the child widget on
2 /// [TargetPlatform.android] and [TargetPlatform.fuchsia].
3 Widget buildOverscrollIndicator(BuildContext context, Widget child, ScrollableDetails details) {
4 // When modifying this function, consider modifying the implementation in
5 // the Material and Cupertino subclasses as well.
6 switch (getPlatform(context)) {
7 case TargetPlatform.iOS:
8 case TargetPlatform.linux:
9 case TargetPlatform.macOS:
10 case TargetPlatform.windows:
11 return child;
12 case TargetPlatform.android:
13 switch (androidOverscrollIndicator) {
14 case AndroidOverscrollIndicator.stretch:
15 return StretchingOverscrollIndicator(
16 axisDirection: details.direction,
17 child: child,
18 );
19 case AndroidOverscrollIndicator.glow:
20 continue glow;
21 }
22 glow:
23 case TargetPlatform.fuchsia:
24 return GlowingOverscrollIndicator(
25 axisDirection: details.direction,
26 color: _kDefaultGlowColor,
27 child: child,
28 );
29 }
30 }
The ScrollBehavior
class, where this code is taken from, defines the basic scroll behavior for all scrollable widgets in an application.
The buildOverscrollIndicator
is used to build the overscroll indicator widget that appears when an element in a scrollable view is overscrolled.
When called, this method makes a distinction:
- If the platform is any of iOS, MacOS, Linux or Windows, the method returns the child widget without any overscroll indicator.
- Otherwise, if the platform is Android or Fuchsia, the method returns a
GlowingOverscrollIndicator
widget wrapped around the child widget. TheGlowingOverscrollIndicator
widget adds a glowing effect to edges of the child widget while scrolling.
Solutions
Like with many aspects of Flutter, there are multiple solutions to approach this problem. Let’s examine all of them one by one.
Using GlowingOverscrollIndicator
Let’s first look at how to use the exact same GlowingOverscrollIndicator
widget to remove the overscroll effect from a ListView
widget:
1
2class ExampleListView extends StatelessWidget {
3 @override
4 Widget build(BuildContext context) {
5 return GlowingOverscrollIndicator(
6 showLeading: false,
7 showTrailing: false,
8 axisDirection: AxisDirection.down,
9 color: Colors.transparent,
10 child: ListView.builder(
11 itemCount: 50,
12 itemBuilder: (BuildContext context, int index) {
13 return ListTile(
14 title: Text('Item $index'),
15 );
16 },
17 ),
18 );
19 }
20}
We create a GlowingOverscrollIndicator
widget and set both the showLeading
and the showTrailing
property to false
. This will prevent the overscroll glow from appearing at the top and bottom of the list. We also specify the axisDirection
as AxisDirection.down
, which is the default for a ListView.
We then set the child property of the GlowingOverscrollIndicator
to a ListView.builder
widget. This creates a scrollable list of ListTile
widgets. We could replace this with any scrollable widget if we liked.
showLeading
and showTrailing
property. Until this bug is fixed, this solution should not be used.Using a custom ScrollBehavior
and ScollConfiguration
A different approach is creating our own ScrollBehavior.
First we create the custom NoGlowScrollBehavior
class that defines the changes:
1class NoGlowScrollBehavior extends ScrollBehavior {
2 @override
3 Widget buildViewportChrome(
4 BuildContext context,
5 Widget child,
6 AxisDirection axisDirection
7 ) {
8 return child;
9 }
10}
After that, we’re wrapping our ListView.builder
widget inside a ScrollConfiguration
widget. We pass a custom NoGlowScrollBehavior
object as the behavior parameter of the ScrollConfiguration
widget:
1ScrollConfiguration(
2 behavior: NoGlowScrollBehavior(),
3 child: ListView.builder(
4 itemCount: 50,
5 itemBuilder: (BuildContext context, int index) {
6 return ListTile(title: Text('Item $index'));
7 },
8 ),
9);
With a custom ScrollBehavior
, we have more control over the scrolling physics and behavior, such as the duration of the animation, the scroll velocity, and the overscroll effect. Furthermore, it can also be reused across different widgets and screens within your app.
The NoGlowScrollBehavior
class overrides the buildViewportChrome
method of the ScrollBehavior
class. By returning the child widget passed as parameter, we’re effectively removing the scroll glow effect in the viewport.
If we have a special ScrollBehavior
we want to keep with the exception of the glow not showing, we can also use this:
1myExistingScrollBehavior().copyWith(overscroll: false)
In comparison, using GlowingOverscrollIndicator
and overriding showLeading
and showTrailing
is a quick and easy solution for getting rid of the scroll glow in your app as we don’t have to write a new class.
However, if we want more control and flexibility over our app’s scrolling behavior, then using a custom ScrollBehavior
is the way to go.
Using BouncingScrollPhysics
Another way to remove the overscroll glow is to use BouncingScrollPhysics
, which is a predefined ScrollPhysics implementation.
Here’s an example of how to use the BouncingScrollPhysics
widget to remove the glow effect:
1class ExampleCustomScrollView extends StatelessWidget {
2 @override
3 Widget build(BuildContext context) {
4 return ListView.builder(
5 physics: BouncingScrollPhysics(),
6 itemCount: 50,
7 itemBuilder: (BuildContext context, int index) {
8 return ListTile(title: Text('Item $index'));
9 },
10 );
11 }
12}
This will not only remove the scroll glow effect but also replace it with a bouncing effect as we know it from iOS when the user overscrolls the list.
Compared to the other presented solution, this can be achieved very quickly as no configuration is required and no class needs to be written.
On the other hand, we are not only losing the scroll glow, but we also have a predefined scroll behavior, which is a stretching effect on iOS. We can not separate these two issues.
Conclusion
In Flutter, there are several ways to remove the scroll glow effect that appears when you reach the end of a scrollable widget.
- One approach is to create a custom
ScrollBehavior
that sets the overscroll indicator color to transparent or disables it altogether - Another option is to modify the scroll physics by using the
BouncingScrollPhysics
to remove the glow effect - Finally, you can also use the
GlowingOverscrollIndicator
widget, which allows you to customize the appearance of the overscroll indicator
While all three approaches can effectively remove the scroll glow, choosing which one to use depends on your specific requirements and preferences.
For instance, using GlowingOverscrollIndicator
provides a bit control over the visual appearance of the overscroll indicator, while a custom ScrollBehavior
might be more appropriate if you need to apply the same modifications to multiple widgets.
Meanwhile, using BouncingScrollPhysics
might be the simplest solution if you only need to disable the scroll glow effect without any further customization.
At least until the bug regarding GlowingOverscrollIndicator
is fixed, I would recommend using a custom ScrollBehavior
as it is the most reliable solution right now and wins in terms of reusability.
Comment this 🤌