Reputation: 779
This issue has been haunting me for some time and even though I read countless web pages, I still cannot solve it. Maybe you're able to help out!
I got the following scenario:
A Flutter app has a PageView
with just 3 pages.
First page has a simple GridView
(vertical scrolling) and no problem there with nested scrolling.
Third page is a simple ListView
with lists of items, no problem here also with scrolling.
The second page has a NestedScrollView
, with two widgets for its headerSliverBuilder
: SliverAppBar
and SliverPersistentHeader
. Nothing fancy here.
The body of the NestedScrollView
contains a TabBarView
which contains 3 tabs, and it's possible to swipe between them using a horizontal swipe -- the same swipe direction as the PageView
which contains this page.
The body is where the scrolling problem occurs.
Swiping between the 3 tabs works like a charm. However, when the current tab is the first and you try to swipe further to the left (finger motion is from left-to-right), the first page (belonging to PageView
) doesn't show. Conversely, when the current tab is the 3rd and you try to swipe further to the right (finger motion is from right-to-left), nothing happens.
If you do the same finger motion on the header contained in the second page, the pages turn fine (either to the first or third pages).
Here's the code inside the second page, would love to know why swiping motion inside the TabBarView
isn't propagating to the container when tabs reach the edges:
Scaffold(
appBar: _generateAppBar(),
body: DefaultTabController(
length: 3,
child: NestedScrollView(
headerSliverBuilder: (_, __) => [
SliverAppBar(
backgroundColor: backgroundColor,
elevation: 0.0,
expandedHeight: 200.0,
floating: true,
pinned: false,
flexibleSpace: backgroundImageView,
),
SliverPersistentHeader(
floating: false,
delegate: _SliverAppBarDelegate(
TabBar(
labelColor: Theme.of(context).primaryColor,
unselectedLabelColor: Colors.black26,
indicatorWeight: 2.5,
tabs: const [
Text('Tab 1'),
Text('Tab 2'),
Text('Tab 3'),
],
),
),
pinned: true,
),
],
body: TabBarView(
children: [
Center(child: Text('Body 1')),
Center(child: Text('Body 2')),
Center(child: Text('Body 3')),
],
),
),
),
);
Auxiliary class:
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate(this._tabBar);
final TabBar _tabBar;
@override
double get minExtent => _tabBar.preferredSize.height;
@override
double get maxExtent => _tabBar.preferredSize.height;
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) =>
Container(child: _tabBar);
@override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) =>
false;
}
Any idea how to fix this? Thanks!
Upvotes: 0
Views: 2844
Reputation: 716
You should wrap the
NestedScrollView
like
DefaultTabController(
length: tabs.length,
child: NestedScrollView())
Upvotes: 1