Skip to content

Instantly share code, notes, and snippets.

@IkhwanSI13
Last active October 4, 2024 13:05
Show Gist options
  • Save IkhwanSI13/eb09a588096db4c88f96ad9f2faf91d1 to your computer and use it in GitHub Desktop.
Save IkhwanSI13/eb09a588096db4c88f96ad9f2faf91d1 to your computer and use it in GitHub Desktop.
load more data in NestedScrollView with NotificationListener
import 'package:cartenz_djp/style/colors.dart';
import 'package:cartenz_djp/widget/override/customTabs.dart' as Tabs;
import 'package:flutter/material.dart';
class ExampleWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() => ExampleState();
}
class ExampleState extends State<ExampleWidget> {
onLoadMore() {
//Load More, do something
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: ColorWhite,
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Builder(builder: (BuildContext context) {
return NestedScrollView(
//controller: scrollController,
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
bottom: getTabHeader(),
)
];
}, body: Builder(builder: (BuildContext context) {
return Stack(children: <Widget>[
getTabBody(),
]);
}));
}),
)
],
),
);
}
Widget getTabHeader() {
return Tabs.TabBar(tabs: [
Tabs.Tab(child: Text("Tab 1")),
Tabs.Tab(child: Text("Tab 2")),
Tabs.Tab(child: Text("Tab 3")),
]);
}
Widget getTabBody() {
return Column(
children: <Widget>[
Expanded(
child: Tabs.TabBarView(children: [
Container(
child:
//Solved with this
NotificationListener<ScrollNotification>(
child: MediaQuery.removePadding(
context: context,
removeTop: true,
child: ListView.builder(
shrinkWrap: true,
itemCount: 3,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Container();
})),
onNotification: (ScrollNotification scrollInfo) {
if (scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent) {
//load more here
onLoadMore();
}
return false;
},
);
Container(child: Container()),
Container(child: Container())
]))
],
);
}
}
@xialisuper
Copy link

shrinkWrap: true ????

Can you make the listView infinity?

@IkhwanSI13
Copy link
Author

shrinkWrap: true ????

Can you make the listView infinity?

yes, just try it.

@debasmitasarkar
Copy link

This does not trigger NestedScrollView. SliverAppbar does not get collapsed

@Martibis
Copy link

Martibis commented Feb 29, 2020

This does not trigger NestedScrollView. SliverAppbar does not get collapsed

In case someone stumbles upon this, you can wrap your inner ListView with a NotificationListener() and check if the Notification is an OverScrollNotification. This is how I got around the issue. As opposed to the solution described above (so no SingleChildScrollView and no Scrollcontroller inside your ListView)

@IkhwanSI13
Copy link
Author

This does not trigger NestedScrollView. SliverAppbar does not get collapsed

yeah, with the new flutter version make the SliverAppBar do not get collapsed.

@IkhwanSI13
Copy link
Author

This does not trigger NestedScrollView. SliverAppbar does not get collapsed

In case someone stumbles upon this, you can wrap your inner ListView with a NotificationListener() and check if the Notification is an OverScrollNotification. This is how I got around the issue. As opposed to the solution described above (so no SingleChildScrollView and no Scrollcontroller inside your ListView)

I think, I tried this too, but not work. Maybe it runs correctly now.

btw, thanks for the answer

@IkhwanSI13
Copy link
Author

This does not trigger NestedScrollView. SliverAppbar does not get collapsed

In case someone stumbles upon this, you can wrap your inner ListView with a NotificationListener() and check if the Notification is an OverScrollNotification. This is how I got around the issue. As opposed to the solution described above (so no SingleChildScrollView and no Scrollcontroller inside your ListView)

I tried it, and it's work. thanks, dude

@fahadadnaan
Copy link

fahadadnaan commented Mar 29, 2020

@IkhwanSI13 Please can you share your code i have the same issue.

   return Scaffold(
     appBar: AppBar(
       iconTheme: IconThemeData(
         color: Color(0xFF6991C7),
       ),
       title: Text(
         "Search",
         style: TextStyle(
             fontWeight: FontWeight.w700,
             fontSize: 18.0,
             color: Colors.black54,
             fontFamily: "Gotik"),
       ),
       centerTitle: true,
       backgroundColor: Colors.white,
       elevation: 0.0,
     ),
     body: SingleChildScrollView(
       primary: false,
       child: Container(
         color: Colors.white,
         padding: EdgeInsets.only(top: 15.0, bottom: 30.0),
         child:  Column(
           crossAxisAlignment: CrossAxisAlignment.start,
           children: <Widget>[
             _textHello,
             BlocListener<FilterBloc, FilterState>(
               listener: (context, state) {
                 if (state is ErrorFilter) {
                   Scaffold.of(context).showSnackBar(
                     SnackBar(
                       content: Text(state.message),
                     ),
                   );
                 }
               },
               child: BlocBuilder<FilterBloc, FilterState>(
                 // ignore: missing_return
                 builder: (context, state) {
                   if (state is InitialFilter) {
                     return buildInitialInput();
                   } else if (state is LoadingFilter) {
                     return buildLoading();
                   } else if (state is LoadedFilter) {
                     if (state.products.isEmpty) {
                       return Column(
                         crossAxisAlignment: CrossAxisAlignment.center,
                         children: <Widget>[
                           ProductInputField(),
                           SizedBox(height: 30.0),
                           Center(child: Text('No content'))
                         ],
                       );
                     }
                     return Column(
                       children: <Widget>[
                         ProductInputField(),
                         SizedBox(height: 30.0),
                         NotificationListener<ScrollNotification>(
                           onNotification: (notification) => _onScrollNotification(notification, state),
                           child: GridView.builder(
                             physics: ScrollPhysics(),
                             itemCount: state.products.length,
                             primary: false,
                             shrinkWrap: true,
                             gridDelegate:
                             SliverGridDelegateWithFixedCrossAxisCount(
                               crossAxisSpacing: 10.0,
                               mainAxisSpacing: 10.0,
                               childAspectRatio: 0.605,
                               crossAxisCount: 2,
                             ),
                             itemBuilder: (context, pos) {
                               return ProductWidget(product: state.products[pos]);
                             },
                           ),
                         ),
                       ],
                     );
                   } else if (state is ErrorFilter) {
                     return buildInitialInput();
                   }
                 },
               ),
             ),
           ],
         )
       ),
     ),
   );
 }

 bool _onScrollNotification(ScrollNotification notif, LoadedFilter state) {
   if (notif is ScrollEndNotification && notif.metrics.pixels == notif.metrics.maxScrollExtent) {
     context.bloc<FilterBloc>().add(LoadMoreFilter(products: state.products, productName: 'a', stateName: ''));
   }
   return false;
 }

@IkhwanSI13
Copy link
Author

@IkhwanSI13 Please can you share your code i have the same issue.

   return Scaffold(
     appBar: AppBar(
       iconTheme: IconThemeData(
         color: Color(0xFF6991C7),
       ),
       title: Text(
         "Search",
         style: TextStyle(
             fontWeight: FontWeight.w700,
             fontSize: 18.0,
             color: Colors.black54,
             fontFamily: "Gotik"),
       ),
       centerTitle: true,
       backgroundColor: Colors.white,
       elevation: 0.0,
     ),
     body: SingleChildScrollView(
       primary: false,
       child: Container(
         color: Colors.white,
         padding: EdgeInsets.only(top: 15.0, bottom: 30.0),
         child:  Column(
           crossAxisAlignment: CrossAxisAlignment.start,
           children: <Widget>[
             _textHello,
             BlocListener<FilterBloc, FilterState>(
               listener: (context, state) {
                 if (state is ErrorFilter) {
                   Scaffold.of(context).showSnackBar(
                     SnackBar(
                       content: Text(state.message),
                     ),
                   );
                 }
               },
               child: BlocBuilder<FilterBloc, FilterState>(
                 // ignore: missing_return
                 builder: (context, state) {
                   if (state is InitialFilter) {
                     return buildInitialInput();
                   } else if (state is LoadingFilter) {
                     return buildLoading();
                   } else if (state is LoadedFilter) {
                     if (state.products.isEmpty) {
                       return Column(
                         crossAxisAlignment: CrossAxisAlignment.center,
                         children: <Widget>[
                           ProductInputField(),
                           SizedBox(height: 30.0),
                           Center(child: Text('No content'))
                         ],
                       );
                     }
                     return Column(
                       children: <Widget>[
                         ProductInputField(),
                         SizedBox(height: 30.0),
                         NotificationListener<ScrollNotification>(
                           onNotification: (notification) => _onScrollNotification(notification, state),
                           child: GridView.builder(
                             physics: ScrollPhysics(),
                             itemCount: state.products.length,
                             primary: false,
                             shrinkWrap: true,
                             gridDelegate:
                             SliverGridDelegateWithFixedCrossAxisCount(
                               crossAxisSpacing: 10.0,
                               mainAxisSpacing: 10.0,
                               childAspectRatio: 0.605,
                               crossAxisCount: 2,
                             ),
                             itemBuilder: (context, pos) {
                               return ProductWidget(product: state.products[pos]);
                             },
                           ),
                         ),
                       ],
                     );
                   } else if (state is ErrorFilter) {
                     return buildInitialInput();
                   }
                 },
               ),
             ),
           ],
         )
       ),
     ),
   );
 }

 bool _onScrollNotification(ScrollNotification notif, LoadedFilter state) {
   if (notif is ScrollEndNotification && notif.metrics.pixels == notif.metrics.maxScrollExtent) {
     context.bloc<FilterBloc>().add(LoadMoreFilter(products: state.products, productName: 'a', stateName: ''));
   }
   return false;
 }

just check my code above. I updated it

@fahadadnaan
Copy link

@IkhwanSI13 Thanks for replying, Notifications Listener not working with multi ListView like my case, So i resolved this problem by add listener function instead of Notifications Listener.

@prateek601
Copy link

Thanks for the code.It is working well 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment