I want to use a PageView with vertical axis and move between the pages using the mouse-scroll, but when I use the mouse-scroll the page don't scroll... The page only scroll when I click and swipe to up/down.

There is any way to do that?

I want to keep the property pageSnapping: true

The problem:

When I try to mouse-scroll the page, it don't change, it just back to initial offset. But when I click and swipe works...

Problem exemple

class Body extends StatefulWidget {

  @override
  _BodyState createState() => _BodyState();
}

class _BodyState extends State<Body> {
  PageController _controller = PageController(keepPage: true);

  @override
  void initState() {
    super.initState();
 }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        height: Sizing.size.height,
        width: Sizing.size.width,
        child: Stack(
          children: <Widget>[
            PageView(
              scrollDirection: Axis.vertical,
              controller: _controller,
              children: <Widget>[
                Container(color: Colors.red),
                Container(color: Colors.blue),
                Container(color: Colors.orange),
              ],
            ),
          ],
        ),
      ),
    );
  }
}


Solution 1: user13374179

To make stuff scrollable in general you can wrap the widget (>>right click on the widget you want to make scrollable>>refactor>>wrap with widget) in a SingleChildScrollView().


Solution 2: Luca Oropallo

To use the mouse scroll you must disable the movement of the PageView by setting physics: NeverScrollableScrollPhysics(). Then you have to manually intercept the mouse scroll through a Listener. If you also want to recover the PageView classic movement through swipe you must use a GestureDetector. Here is an example code:

class _HomepageState extends State<Homepage> {
  final PageController pageController = PageController();
  // this is like a lock that prevent update the PageView multiple times while is 
  // scrolling
  bool pageIsScrolling = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
          child: GestureDetector(
        // to detect swipe
        onPanUpdate: (details) {
          _onScroll(details.delta.dy * -1);
        },
        child: Listener(
          // to detect scroll
          onPointerSignal: (pointerSignal) {
            if (pointerSignal is PointerScrollEvent) {
              _onScroll(pointerSignal.scrollDelta.dy);
            }
          },
          child: PageView(
            scrollDirection: Axis.vertical,
            controller: pageController,
            physics: NeverScrollableScrollPhysics(),
            pageSnapping: true,
            children: [
               Container(color: Colors.red),
               Container(color: Colors.blue),
               Container(color: Colors.orange),
            ],
          ),
        ),
      )),
    );
  }

  void _onScroll(double offset) {
    if (pageIsScrolling == false) {
      pageIsScrolling = true;
      if (offset > 0) {
        pageController
            .nextPage(
                duration: Duration(milliseconds: 300),
                curve: Curves.easeInOut)
            .then((value) => pageIsScrolling = false);

        print('scroll down');
      } else {
        pageController
            .previousPage(
                duration: Duration(milliseconds: 300),
                curve: Curves.easeInOut)
            .then((value) => pageIsScrolling = false);
        print('scroll up');
      }
    }
  }
}


Solution 3: EngineSense

Thanks to Luca!

I just modified the entire thing to do the same, what was the question asked for.

  Listener(
                onPointerMove: (pointerMove) {
                  if (pointerMove is PointerMoveEvent) {
                    _onScroll(pointerMove.delta.dy * -1);
                    print(pointerMove.delta.dy);
                  }
                },
                onPointerSignal: (pointerSignal) {
                  if (pointerSignal is PointerScrollEvent) {
                    _onScroll(pointerSignal.scrollDelta.dy);
                    print(pointerSignal.scrollDelta.dy);
                  }
                },
                child: SingleChildScrollView(
                  child: Container(
                    constraints: BoxConstraints(
                        minHeight: SizeConfig.screenHeight * .9),
                    width: SizeConfig.screenWidth,
                    height: SizeConfig.screenWidth / 2,
                    decoration: BoxDecoration(
                        image: DecorationImage(
                            alignment: Alignment.centerRight,
                            image: AssetImage(
                                'assets/images/background_circles.png'))),
                    child: PageView(
                      controller: _pageController,
                      physics: NeverScrollableScrollPhysics(),
                      pageSnapping: true,
                      scrollDirection: Axis.vertical,
                      children: [