Mastering Scroll Event Tracking in Flutter: A Practical Guide

Scrolling is a ubiquitous interaction in mobile apps, and being able to track scroll events accurately can lead to better user experiences and informed design decisions. In this blog post, we’re diving into the world of efficient scroll event tracking in Flutter. Even if you’re not a Flutter wizard, worry not — I’ve got you covered with a step-by-step breakdown of the code and concepts.

Getting Started

To start, let’s take a look at the core components of the code we’ll be discussing. The main parts consist of main.dart and a handy mixin named tracking_scroll.dart.

main.dart

import 'package:flutter/material.dart';
import 'package:scroll_example/tracking_scroll.dart';

void main() {

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Demo',
      home: ScrollExample(),
    );
  }
}
class ScrollExample extends StatefulWidget  {
  const ScrollExample({super.key});

  @override
  State<ScrollExample> createState() => _ScrollExampleState();
}

class _ScrollExampleState extends State<ScrollExample> with TrackingScroll {
late ScrollController _scrollController;
  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController();
    initiateTracking(
      _scrollController,
      Axis.vertical,
      (percent, typeOfScroll) {
        debugPrint('Scrolling $typeOfScroll at $percent%');
      },
    );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: const Text('Scroll Tracking'),
      ),
      body: ListView.builder(
        itemCount: 100,
        controller: _scrollController,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text('Item $index'),
          );
        },
      ),
    );
  }
}

Here’s a quick rundown:

  • We have the ScrollExample widget, which is our playground for scroll event tracking.

  • Inside the _ScrollExampleState state class, we're embracing the power of the TrackingSrcoll mixin to efficiently track scroll events.

  • initState() sets up the necessary components for scroll tracking, including a scroll controller, scroll direction, and the callback function.

scroll_tracker.dart

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

typedef ScrollTrackerCallback = void Function(
    int scrollPercent, String typeOfScroll);

mixin TrackingScroll {
  ScrollController? _scrollController;
  Axis? _scrollDirection;
  ScrollTrackerCallback? _onScrolled;

  void initiateTracking(
    ScrollController scrollController,
    Axis scrollDirection,
    ScrollTrackerCallback? onScrolled,
  ) {
    _scrollController = scrollController;
    _scrollDirection = scrollDirection;
    _onScrolled = onScrolled;

    _scrollController?.position.isScrollingNotifier
        .addListener(_scrollChangeListener);
  }

  void _scrollChangeListener() {
    if (_scrollController == null) return;
    final scrollController = _scrollController!;
    if (!scrollController.position.isScrollingNotifier.value) {
      final percent = scrollController.position.pixels *
          100 ~/
          scrollController.position.maxScrollExtent;
      var typeOfScroll = '';
      if (_scrollDirection == Axis.horizontal) {
        if (scrollController.position.userScrollDirection ==
            ScrollDirection.reverse) {
          typeOfScroll = 'sroll left';
        } else if (scrollController.position.userScrollDirection ==
            ScrollDirection.forward) {
          typeOfScroll = 'sroll right';
        }
      } else {
        if (scrollController.position.userScrollDirection ==
            ScrollDirection.reverse) {
          typeOfScroll = 'sroll up';
        } else if (scrollController.position.userScrollDirection ==
            ScrollDirection.forward) {
          typeOfScroll = 'sroll down';
        }
      }
      _onScrolled?.call(percent, typeOfScroll);
    }
  }
}

In this snippet:

  • We have a cool ScrollTrackerCallback type that we'll use for our scroll event callback.

  • And here’s where the magic happens — the TrackingSroll mixin encapsulates the scroll tracking logic we're about to explore.

The Scroll Tracking Magic

Let’s pull back the curtains and reveal how this scroll tracking magic works under the hood.

  • Inside the TrackingSroll mixin, there are a few hidden gems: _scrollController, _scrollDirection, and _onScrolled. These store our scroll controller, scroll direction, and the callback function, respectively.

  • The initiateTracking method initiates the scroll tracking process. It takes in a ScrollController, an Axis (to define scroll direction), and a callback function. This callback function is your secret weapon to be triggered whenever a scroll event is detected.

  • Here comes the star of the show — _scrollChangeListener. It gets attached as a listener to the scroll controller's isScrollingNotifier. This function is called every time there's a scroll event.

  • When the _scrollChangeListener detects that scrolling has stopped (yep, only when it stops), it calculates the scroll percentage based on the current scroll position.

  • Depending on whether you’re scrolling vertically or horizontally, it figures out if you’ve been scrolling up, down, left, or right.

  • Armed with the scroll percentage and direction, the callback function you provided gets its moment to shine.

The Grand Finale

Tracking scroll events efficiently in Flutter is like having a crystal ball into your users’ interaction with your app. By tapping into the power of the TrackingScroll mixin, you can bring your app to life with engaging and responsive scrolling behaviors.

Remember, the ScrollTrackerCallback is your canvas – you can customize it to suit your app's unique needs. Whether you're building a simple list or a complex UI with intricate scrolling behaviors, this approach has got your back.

And here’s a neat little secret: You’re not limited to either StatelessWidget or StatefulWidget – this mixin can be your trusty sidekick in both realms.

So, there you have it! A deep dive into scroll event tracking in Flutter that’s designed to empower developers of all levels. Go ahead, experiment, and take your Flutter app’s scrolling to the next level.

0
Subscribe to my newsletter

Read articles from NonStop io Technologies directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

NonStop io Technologies
NonStop io Technologies

Product Development as an Expertise Since 2015 Founded in August 2015, we are a USA-based Bespoke Engineering Studio providing Product Development as an Expertise. With 80+ satisfied clients worldwide, we serve startups and enterprises across San Francisco, Seattle, New York, London, Pune, Bangalore, Tokyo and other prominent technology hubs.