Daibaku
Daibaku

Reputation: 12566

Flutter how to get last PageView scroll direction

I'm trying to get which direction(left or right) user swiped by using PageView. I was able to get direction like so.

Code:

 PageController _controller;

  @override
  void initState() {
    _controller = new PageController()..addListener(_listener);
    super.initState();
  }

  _listener() {
    if (_controller.position.userScrollDirection == ScrollDirection.reverse) {
      print('swiped to right');
    } else {
      print('swiped to left');
    }
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(),
      body: PageView.builder(
          itemCount: 10,
          controller: _controller,
          itemBuilder: (context, index) {
            return new Center(child: Text('item ${++index}'));
          }),
    );
  }

However since it's not getting end of scrolling, print method return this many times. Is there way I can get this after current page switched to next page completely?

flutter: swiped to right
flutter: swiped to right
flutter: swiped to right
flutter: swiped to right
flutter: swiped to right
flutter: swiped to right
flutter: swiped to right
flutter: swiped to right
flutter: swiped to right
flutter: swiped to right
flutter: swiped to right

Upvotes: 12

Views: 17193

Answers (4)

Merritt
Merritt

Reputation: 564

None of the solutions here worked for me, figuring this out was a huge headache.

I ended up using a gesture detector and disabling the PageView gestures entirely.

The NeverScrollableScrollPhysics() is how you disable the PageView's built-in gestures.

class MyPageView extends StatefulWidget {
  @override
  _MyPageViewState createState() => _MyPageViewState();
}

class _MyPageViewState extends State<MyPageView> {
  PageController _pageController;
  Duration pageTurnDuration = Duration(milliseconds: 500);
  Curve pageTurnCurve = Curves.ease;

  @override
  void initState() {
    super.initState();
    // The PageController allows us to instruct the PageView to change pages.
    _pageController = PageController();
  }

  void _goForward() {
    _pageController.nextPage(duration: pageTurnDuration, curve: pageTurnCurve);
  }

  void _goBack() {
    _pageController.previousPage(
        duration: pageTurnDuration, curve: pageTurnCurve);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        // Using the DragEndDetails allows us to only fire once per swipe.
        onHorizontalDragEnd: (dragEndDetails) {
          if (dragEndDetails.primaryVelocity < 0) {
            // Page forwards
            print('Move page forwards');
            _goForward();
          } else if (dragEndDetails.primaryVelocity > 0) {
            // Page backwards
            print('Move page backwards');
            _goBack();
          }
        },
        child: PageView.builder(
            itemCount: 10,
            controller: _pageController,
            // NeverScrollableScrollPhysics disables PageView built-in gestures.
            physics: NeverScrollableScrollPhysics(),
            itemBuilder: (context, index) {
              return new Center(child: Text('item ${++index}'));
            }),
      ),
    );
  }
}

Upvotes: 5

Patrick Waweru
Patrick Waweru

Reputation: 204

Your code is okay just add a setState like this

PageController _controller;

  @override
  void initState() {
    _controller = new PageController()..addListener(_listener);
    super.initState();
  }

  _listener() {
    setState(() {
      if (_controller.position.userScrollDirection == ScrollDirection.reverse) {
        print('swiped to right');
      } else {
        print('swiped to left');
      }
    });

  }

Upvotes: 3

ThinkDigital
ThinkDigital

Reputation: 3539

A better solution is as follows, using the PageView widget's built in function.

 PageView(
 onPageChanged: (int page) { 
 // this page variable is the new page and will change before the pageController fully reaches the full, rounded int value
   var swipingRight = page > pageController.page;
   print(swipingRight);
  },

Upvotes: 18

boformer
boformer

Reputation: 30103

Compare the current _controller.page.round() with the value from the previous listener invocation (store the previous value in the State).

  • If the current value is greater than the previous value, the user swiped to the right.
  • If the current value is lower than the previous value, the user swiped to the left.

Upvotes: 6

Related Questions