scroll_velocity_notifier 0.0.6
scroll_velocity_notifier: ^0.0.6 copied to clipboard
A lightweight Flutter utility that intercepts scroll notifications and calculates smooth, real-time scroll velocity using an exponential moving average. Useful for scroll-aware UI, animations, and ges [...]
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.
โจ 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 is 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'),
);
},
),
)
๐ 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:
```dart
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.
If you want next:
- a
CHANGELOG.md - an
example/app - pub.dev score optimization
- API tightening (ownership-safe controller handling)
Just tell me.