How to remove scroll glow

How to remove scroll glow
No time to read?
tl;dr

You can remove the overscroll glow effect in Flutter using:

  • A custom ScrollBehavior being wrapped with a ScrollConfiguration
  • Using BouncingScrollPhysics instance being set as the physics property of your scrollable widget
  • GlowingOverscrollIndicator widget with the showLeading and showTrailing properties set to false (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.

Tip
One important thing to note is that the overscroll glow effect is provided by the underlying platform, whether it be iOS or Android. Disabling this effect could result in a less native look and feel for your app. It is up to you to weigh the pros and cons of removing this effect in your particular use case.

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.

Iconic screenshot of the unwanted scroll glow
Does this look familiar? 🤔

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. The GlowingOverscrollIndicator 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.

Warning
The big issue with this is that there is a bug inside of Flutter that leads to ignoring the 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 🤌

You are replying to 's commentRemove reference