'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 eachTabBarView
contains aColumn
.
- A
- 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 aListView
, 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 thephysics
property of thisListView
toNeverScrollablePhysics()
doesnt fix this and results in some weird behaviour. - I tried using a
NestedScrollView
withSilvers
(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:
- Flutter scrollable TabBarView in Column without predefined size
- How to create a bounded scrollable TabBarView
- how to implement a sliverAppBar with a tabBar
- Getting 'Horizontal viewport was given unbounded height.' with TabBarView in flutter
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 |