Reputation: 31
Goal
My goal is to present a carousel with long pages. So I use a PageView with scrollviews. The PageView scrolls horizontally. The scrollviews (children) scroll vertically.
Expected Results
Swipe horizontally and scroll vertically smoothly.
Actual Results
If I swipe horizontally to the next page, I can't scroll it vertically right away. I need to wait for 1 second. It seems the user must wait the animation completion to be able to interact with the new current page.
What have I tried so far :
Here's the minimum code you would need to reproduce the problem
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: carousel(),
);
}
Widget carousel() {
return PageView(
children: <Widget>[
page(Colors.pinkAccent),
page(Colors.blueAccent),
page(Colors.orangeAccent)
],
);
}
Widget page(Color color) {
return Container(
decoration: BoxDecoration(
color: color,
),
child: SingleChildScrollView(
child: Column(
children: pageContent()),
));
}
List<Widget> pageContent() {
return <Widget>[
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
Row(children: <Widget>[Text("Hop", textScaleFactor: 5,)]),
];
}
}
Upvotes: 2
Views: 4276
Reputation: 31
I succeeded to find a solution to make my PageView really smooth horizontally and vertically.
I disable PageView.pageSnapping to make the carousel very smooth. However I lost the magnetic effect, so I use a NotificationListener to catch the ScrollEndNotification event. When the scrolling ends, I calculate the most visible page to the user and call PageController.animateToPage() to finish the job.
The code looks like this:
Widget getCarousel() {
return NotificationListener<ScrollNotification>(
onNotification: (scrollNotification) {
if (scrollNotification is ScrollEndNotification) {
print("ScrollEndNotification");
Future.delayed(const Duration(milliseconds: 0), () {
int newPage = pageController.page.round();
print("end at $newPage");
pageController.animateToPage(newPage, duration: Duration(milliseconds: 400), curve: Curves.fastOutSlowIn);
});
}
return true;
},
child: PageView.builder(
scrollDirection: Axis.horizontal,
pageSnapping: false,
controller: pageController,
itemBuilder: (BuildContext context, int index) {
return myPages[index];
},
)
);
}
Upvotes: 1
Reputation: 392
After a little digging, I believe the issue lies in the DragStartBehavior of PageView. Intending to be smooth, the default behavior of PageView ends up feeling sluggish, the page snap almost feels like it had one too many drinks.
This means that while you want to vertical scroll, the PageView is still slurring through a change.
Adjust the DragStartBehavior when you call PageView and it will feel much more reactive - it will feel a little more snappy, which I believe may resolve your issue.
Widget carousel() {
return PageView(
children: <Widget>[
dragStartBehavior: DragStartBehavior.down,
page(Colors.pinkAccent),
page(Colors.blueAccent),
page(Colors.orangeAccent)
],
);
}
p.s Thank you Yunnosch for the reprimand and laugh :) Feel free to edit this out also since I cant exactly comment yet!
Upvotes: 0