0

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).

cekpowell
  • 17
  • 4
  • Wrap the SingleChildScrollView with ``Expanded`` – pasha Apr 06 '22 at 15:31
  • @pasha i am not using a SingleChildScrollView - where should I place it? – cekpowell Apr 06 '22 at 15:36
  • 1
    Expanded-> SingleChildScrollView -> ListView( make shrinkWrap: true and physics: NeverScrollableScrollPhysics() for ListView) – pasha Apr 06 '22 at 15:43
  • No that hasnt done it - I get an error when using the Expanded widget and the SingleChildScrollView gives me two scrollable areas still. – cekpowell Apr 06 '22 at 15:53
  • @pasha would you be able to produce a code example for it? – cekpowell Apr 06 '22 at 16:31
  • https://stackoverflow.com/questions/71769800/implement-tabbar-under-appbar/71769862?noredirect=1#comment126833382_71769862 i just answered this here it is very similar – flutterloop Apr 06 '22 at 16:47

1 Answers1

0

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),
              ],
            ),




griffins
  • 5,390
  • 3
  • 23
  • 46
  • sorry Im on mobile ,I'll fomart the answer once on a desktop – griffins Apr 06 '22 at 16:49
  • Yeah using `NestedScrollView` kind of works but it produces an exception (`The provided ScrollController is currently attached to more than one ScrollPosition`). – cekpowell Apr 06 '22 at 17:00
  • also @griffins - this works but it produces two scroll areas - the scroll area for the `NestedScrollView` or `CustomScrollView` and the scroll area for the `ListView` that I have in `TabView`. – cekpowell Apr 06 '22 at 18:05
  • let the parent widget be the only scrollable widget set physcis on other scrollable components and remove the scroll controller from them i.e `physics:NeverScrollablePhysics(),` – griffins Apr 07 '22 at 03:47