I'm trying to get the scroll direction (Up/Down) of a NestedScrollView so one of my widgets can react accordingly.
I've already used the NotificationListener widget and tried to print the axisDirection that it returns but it only returns "down" when I scroll in both directions. apparently that's the way it supposed to behave but still, it doesn't look like there's any way in Flutter to know how to get the scroll direction. Is there any way to get the scroll direction whether be it as an AxisDirection or a bool ?.
@override
Widget build(BuildContext context) {
return Container(
color: Colors.black,
child: SafeArea(
child: Scaffold(
backgroundColor: Color.fromARGB(255, 22, 22, 22),
body: NotificationListener<ScrollStartNotification>(
onNotification: (ScrollNotification scrollInfo) {
print("scrollInfo up ===== ${scrollInfo.metrics.axisDirection}");
},
child: NotificationListener<ScrollStartNotification>(
onNotification: (ScrollNotification scrollInfo) {
if (scrollInfo.metrics.axisDirection == AxisDirection.down) {
print(
"scrollViewColtroller down == ${scrollViewColtroller.position.axisDirection}");
}
},
child: NestedScrollView(
controller: scrollViewColtroller,
headerSliverBuilder:
(BuildContext context, bool boxIsScrolled) {
return <Widget>[
SliverAppBar(
floating: true,
snap: true,
pinned: false,
elevation: 10,
)
];
},
body: Container(
padding: EdgeInsets.all(0.0),
child: Center(
child: Column(
children: <Widget>[
SizedBox(
height: 1,
),
_feedPosts(context)
],
),
),
),
),
),
),
),
),
);
}
This is what it prints.
scrollViewColtroller up ===== AxisDirection.down
scrollInfo up == AxisDirection.down
scrollViewColtroller up ===== AxisDirection.down
scrollInfo up == AxisDirection.down
You can get the Direction with the help of - scrollViewColtroller.position
First add - import 'package:flutter/rendering.dart';
Code:
@override
Widget build(BuildContext context) {
return Scaffold(
// backgroundColor: Color.fromARGB(255, 22, 22, 22),
body: NotificationListener<ScrollUpdateNotification>(
onNotification: (ScrollNotification scrollInfo) {
if (scrollViewColtroller.position.userScrollDirection ==
ScrollDirection.reverse) {
print('User is going down');
setState(() {
message = 'going down';
});
} else {
if (scrollViewColtroller.position.userScrollDirection ==
ScrollDirection.forward) {
print('User is going up');
setState(() {
message = 'going up';
});
}
}
},
child: NestedScrollView(
controller: scrollViewColtroller,
headerSliverBuilder: (BuildContext context, bool boxIsScrolled) {
return <Widget>[
SliverAppBar(
floating: true,
snap: true,
pinned: false,
elevation: 10,
)
];
},
body: Container(
padding: EdgeInsets.all(0.0),
child: Column(
children: <Widget>[
Container(
height: 150.0,
color: Colors.green,
child: Align(
alignment: Alignment.bottomCenter,
child: Text(
message,
style: TextStyle(color: Colors.white, fontSize: 25.0),
),
),
),
Expanded(
child: ListView(
children: List.generate(100, (i) {
return Text(i.toString());
}).toList(),
))
],
),
),
),
),
);
}
Output:
AxisDirection
isn't used to detect scrolling direction, it is used to return the Scrollable
structure, in your case the NestedScrollView
has scrollDirection = Axis.Vertical
by default, which makes its beginning at top and its AxisDirection = AxisDirection.down
. So when you tried to scroll up and down you received the same result because list structure doesn't change by scrolling events.
To achieve what you want you can compare the current position to the default one (0.0
), if the ScrollNotification.metrics.pixels
greater than previous position, then the list is scrolling up (or left in case of horizontal ones), or down if it is less.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final appTitle = 'Scroll Direction Detection';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: appTitle,
home: MyHomePage(title: appTitle),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
MyHomePage({Key key, this.title}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>{
double position = 0.0 ;
double sensitivityFactor = 20.0 ;
@override
Widget build(BuildContext context) {
return Container(
child: SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scrollInfo) {
if(scrollInfo.metrics.pixels - position >= sensitivityFactor){
print('Axis Scroll Direction : Up');
position = scrollInfo.metrics.pixels ;
}
if(position - scrollInfo.metrics.pixels >= sensitivityFactor){
print('Axis Scroll Direction : Down');
position = scrollInfo.metrics.pixels ;
}
},
child: ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(
title: Text('$index'),
);
},
),
),
),
),
);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With