scroll_velocity_notifier 0.0.14
scroll_velocity_notifier: ^0.0.14 copied to clipboard
A lightweight Flutter utility that calculates smooth, real-time scroll velocity from scroll notifications, useful for scroll-aware UI and gesture-driven effects.
scroll_velocity_notifier #
scroll_velocity_notifier is a lightweight Flutter utility that intercepts scroll notifications and computes smooth, real-time scroll velocity (pixels per second).
It is designed for scroll-aware UI, gesture-driven effects, and advanced animations, without imposing layout constraints or architectural opinions.
From the creator of http_mock_adapter, a widely used Flutter testing utility.
β¨ Features #
- π Calculates scroll velocity in pixels per second
- π Uses Exponential Moving Average (EMA) for smooth values
- π Optional overscroll velocity support
- π§© Implemented as a ProxyWidget (zero layout impact)
- π Works with any
ScrollView - π§ No global state, no forced state management
π¦ Installation #
Add the dependency to your pubspec.yaml:
dependencies:
scroll_velocity_notifier: ^0.0.1
Then run:
flutter pub get
πΈ Demo - gif removes frames so it looks junky on the gif #

π§ How It Works #
The widget listens to ScrollNotifications emitted by scrollable widgets and computes velocity using:
- Scroll position delta (
pixels) - Time delta (microseconds)
- EMA smoothing for stability
The widget does not alter layout or scrolling behavior. It acts purely as a transparent observer in the widget tree.
π Basic Usage #
Wrap any scrollable widget with ScrollVelocityNotifier:
ScrollVelocityNotifier(
onNotification: (notification, velocity) {
debugPrint('Velocity: $velocity px/s');
return false; // allow notification to bubble up
},
child: ListView.builder(
itemCount: 50,
itemBuilder: (context, index) {
return ListTile(
title: Text('Item $index'),
);
},
),
)
Further reading #
π Velocity Semantics #
- Positive velocity β scrolling down
- Negative velocity β scrolling up
- Zero velocity β stationary or ignored overscroll
- Smoothed output β ideal for UI reactions and animations
π Overscroll Support #
By default, velocity is reported as 0 during overscroll.
To include overscroll velocity (e.g. when using BouncingScrollPhysics):
ScrollVelocityNotifier(
includeOversScroll: true,
onNotification: (notification, velocity) {
debugPrint('Overscroll velocity: $velocity');
return false;
},
child: ListView(
physics: const BouncingScrollPhysics(),
children: const [
SizedBox(height: 2000),
],
),
)
π― Use Case Examples #
Hide / Show AppBar Based on Scroll Speed #
double appBarOffset = 0;
ScrollVelocityNotifier(
onNotification: (notification, velocity) {
if (velocity > 800) {
appBarOffset = -100;
} else if (velocity < -800) {
appBarOffset = 0;
}
return false;
},
child: CustomScrollView(
slivers: [
SliverAppBar(
floating: true,
expandedHeight: 100,
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(title: Text('Item $index')),
childCount: 50,
),
),
],
),
)
Trigger Animations Based on Scroll Velocity #
ScrollVelocityNotifier(
onNotification: (notification, velocity) {
if (velocity.abs() > 1200) {
debugPrint('Fast scroll detected');
}
return false;
},
child: ListView(
children: List.generate(
30,
(i) => ListTile(title: Text('Row $i')),
),
),
)
π StreamController Integration #
ScrollVelocityNotifier can optionally emit scroll velocity updates into a
user-provided StreamController.
This allows scroll velocity data to be consumed outside the widget tree, for example by:
- BLoC / Cubit
- analytics systems
- animation coordinators
- logging or debugging tools
Basic Usage #
final controller =
StreamController<ScrollStreamNotification>.broadcast();
@override
void dispose() {
controller.close();
super.dispose();
}
ScrollVelocityNotifier(
controller: controller,
child: ListView.builder(
itemCount: 50,
itemBuilder: (context, index) {
return ListTile(title: Text('Item $index'));
},
),
);
π§ Architectural Notes #
- Implemented using
ProxyWidget+ProxyElement - No rebuilds are triggered
- No inherited state
- No frame callbacks
- Safe for high-frequency scroll updates
This makes it suitable for large dashboards and complex scroll hierarchies.
π§ͺ Testing #
The velocity stream can be tested by driving scroll notifications and asserting expected velocity output:
expect(
velocity.abs(),
greaterThan(0),
);
π οΈ When to Use This Package #
β Scroll-aware UI β Velocity-driven animations β Gesture-based visibility logic β Overscroll-sensitive effects β Performance-safe scroll observation
π License #
MIT License
See LICENSE file for details.
π Contributions #
Issues and pull requests are welcome. If you find a bug or have a feature idea, feel free to open an issue.