I want 2 tab pages with a ListView each to share a single RefreshIndicator. However, a RefreshIndicator must have Scrollable as a child (which a TabBarView isn't) so instead I tried making 2 RefreshIndicators per tab as shown in the code below.
But this brings a different problem, I also wanted a floating AppBar which meant I had to use a NestedScrollView. So as a result I end up triggering both RefreshIndicators' onRefresh method whenever I scroll down. Whereas I only need one to refresh.
import 'package:flutter/material.dart';
main() {
runApp(
MaterialApp(
home: DefaultTabController(
length: 2,
child: Scaffold(
body: NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
SliverAppBar(
floating: true,
snap: true,
bottom: TabBar(
tabs: [
Tab(text: 'Page1'),
Tab(text: 'Page2'),
],
),
),
];
},
body: TabBarView(
children: [
Page(1),
Page(2),
],
),
),
),
),
),
);
}
class Page extends StatefulWidget {
final pageNumber;
Page(this.pageNumber);
createState() => PageState();
}
class PageState extends State<Page> with AutomaticKeepAliveClientMixin {
get wantKeepAlive => true;
build(context){
super.build(context);
return RefreshIndicator(
onRefresh: () => Future(() async {
print('Refreshing page no. ${widget.pageNumber}'); // This prints twice once both tabs have been opened
await Future.delayed(Duration(seconds: 5));
}),
child: ListView.builder(
itemBuilder: ((context, index){
return ListTile(
title: Text('Item $index')
);
}),
)
);
}
}
The AutomaticKeepAliveClientMixin is there to prevent the pages rebuilding every time I switch tabs as this would be an expensive process in my actual app.
A solution that uses a single RefreshIndicator for both tabs would be most ideal, but any help is appreciated.
The Flutter documentation defines NestedScrollView as “A scrolling view inside of which can be nested other scrolling views, with their scroll positions being intrinsically linked.” This means that with NestedScrollView , you get two scrolling areas. One is the header part and the other is its body part.
RefreshIndicator class Null safety. A widget that supports the Material "swipe to refresh" idiom.
This is a simple way to do it. RefreshIndicator( onRefresh: () { setState((){ // Update your data here }); }, child: ... ) Give me some examples for complete code or links to set 'setState' in a flutter.
This code is working for me, it's mostly built on top of @Nuts answer, but it needed some tweaking and my edit was rejected
DefaultTabController(
length: tabs.length,
child: RefreshIndicator(
notificationPredicate: (notification) {
// with NestedScrollView local(depth == 2) OverscrollNotification are not sent
return notification.depth == 2;
},
onRefresh: () => Future.value(null),
child: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
SliverAppBar(...)
];
},
body: TabBarView(
children: tabs,
),
),
),
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With