'TabBarView within Scrollable Page

I am having real trouble getting a layout to work within Flutter.

The layout I am trying to create:

  • A ListView that contains a:
    • A Container.
    • A TabBar.
    • A TabBarView, where each TabBarView contains a Column.
  • And I want the whole page to be scrollable.

Here is the schematic for the layout:

Example Code

Here is a minimum example code (with exact widget definitions removed):

return DefaultTabController(
      length: 2,
      child: ListView(
        children: [
          // TOP CONTAINER //
          Container(height: 30),

          // TAB BAR //

          const TabBar(tabs: [
            Tab(child: Text("Tab 1")),
            Tab(child: Text("Tab 2")),
          ]),

          // TAB BAR VIEWS //
          SizedBox(
            height: MediaQuery.of(context).size.height,
            child: TabBarView(
              children: [
                Container(height: 5000),
                Container(height: 5000),
              ],
            ),
          )
        ],
      ),
    );

The Problem:

When the height of the window gets smaller, I get an overflow error at the bottom:

What I have Done:

  • I first tried converting the inner Column into a ListView, which fixed the overflow, but resulted in two separate scrollable areas (the individual tab views and the whole page), which is not what I want - I want a single scrollable area. Setting the physics property of this ListView to NeverScrollablePhysics() doesnt fix this and results in some weird behaviour.
  • I tried using a NestedScrollView with Silvers (from How to create a bounded scrollable TabBarView). But this results in the following exception when navigating through the tabs: The provided ScrollController is currently attached to more than one ScrollPosition., and produces some dodgy scroll mechanics.
  • I tried using a CustomScrollView but that didnt work.

Similar Questions that Didnt provide a working solution:

I am very confused as to why it is not working as I feel this is a very simple thing. Essentially, it is the same layout used in the Instragram app (among others) when viewing your personal profile (see: https://unblast.com/wp-content/uploads/2020/01/Instagram-UI-Profile-1.jpg).



Solution 1:[1]

From the comments you can wrap your page in a singlechildscrollview, disable scroll physics for the listview as the parent is already scrollable.

return SIngleChildScrollView(child: DefaultTabController(
      length: 2,
      child: ListView(
physics:NeverScrollablePhysics(),
        children: [
          // TOP CONTAINER //
          Container(height: 30),

          // TAB BAR //

          const TabBar(tabs: [
            Tab(child: Text("Tab 1")),
            Tab(child: Text("Tab 2")),
          ]),

          // TAB BAR VIEWS //
          SizedBox(
            height: MediaQuery.of(context).size.height,
            child: TabBarView(
              children: [
                Container(height: 5000),
                Container(height: 5000),
              ],
            ),
          )
        ],
      ),
    ));

** Option2 **

you can use a customScrollView or a nestedScrollView

DefaultTabController(
      length: 2,
      child:
CustomScrollView(
              slivers: [

SlivertoboxAdapter(child:   // TOP CONTAINER //
          Container(height: 30),

SlivertoboxAdapter(child:   // TAB BAR //

          const TabBar(tabs: [
            Tab(child: Text("Tab 1")),
            Tab(child: Text("Tab 2")),
          ]),

//... Sliverfillremaining/slivettoboxadapter for your tabbarview

SlivertoboxAdapter(child:TabBarView(
              children: [
                Container(height: 5000),
                Container(height: 5000),
              ],
            ),




Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 griffins