Search code examples
flutterdartmobilepageviewssinglechildscrollview

SingleChildScrollView inside PageView


I got four different Tabs at my Bottom Navigation and one of those tabs (the last one) is a SingleChildScrollView. I want that I can click on the Icons on the Bottom Navigation AND also can scroll trough the App. That works fine, only the last tab makes a lot of trouble: My Problem is that when I scroll down to the SingleChildScrollView (the last tab), I can't scroll out of it to the tab above it anymore. That's what my PageView looks like (it's the Body):

      body: PageView(
        scrollDirection: Axis.vertical,
        onPageChanged: (page) {
          setState(
            () {
              _selectedIndex = page;
            },
          );
        },
        controller: _controller,
        children: [
          Home(),
          Games(),
          Shop(),
          AboutUs(),
        ],
      ),
    );
  }

And that's what my Tab (AboutUs()) looks like:

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      scrollDirection: Axis.vertical,
      physics: BouncingScrollPhysics(),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
           // In there are many many children (Containers, etc. :))
        ],
      ),
    );
  }

Sorry for my bad explaination I hope someone can help! Thanks already! :)


Solution

  • One possible way is to wrap your SingleChildScrollView with a NotificationListener like so:

    class AboutUs extends StatelessWidget {
    
      final PageController pageController;
      const AboutUs({Key? key, required this.pageController}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return NotificationListener<ScrollUpdateNotification>(
          onNotification: (notification) {
            if (pageController.page == 3) {
              if (notification.metrics.pixels < -50) {
                pageController.previousPage(duration: const Duration(milliseconds: 200), curve: Curves.ease);
              }
            }
            return false;
          },
          child: SingleChildScrollView(
            scrollDirection: Axis.vertical,
            physics: const BouncingScrollPhysics(),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                // In there are many many children (Containers, etc. :))
              ],
            ),
          )
        );
      }
    }
    

    Note that you will need to pass down your PageController to the AboutUs Widget so you can go back up to the previous page.