Closed clragon closed 5 months ago
Hey @clragon,
Have you tried using this as a Sliver? Inside of a CustomScrollView
with other sibling Sliver widgets.
Hi @EdsonBueno,
I dont remember whether I specifically tested that. Is there an issue with it?
I am using this fork in my app, though I am using the PagedMasonryGridView
which wraps PagedSliverMasonryGrid
.
I havent seen any issues yet though.
I also use this fork in my app, works with Custom Scroll View
@clragon i found a bug using PagedSliverMasonryGrid: When having long items, after reaching the bottom of the list, the scrolls jumps to the start, (this doens't happend 70% of the time)
Flutter doctor: Flutter (Channel beta, 3.10.0-1.4.pre, on Microsoft Windows [Version 10.0.25309.1000], locale en-US) • Flutter version 3.10.0-1.4.pre on channel beta at C:\src\flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision a14a4eac61 (4 days ago), 2023-04-26 12:54:31 +0700 • Engine revision f7ac42e8a2 • Dart version 3.0.0 (build 3.0.0-417.3.beta) • DevTools version 2.23.1
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
• Android SDK at C:\Users\G3orG3\AppData\Local\Android\Sdk
• Platform android-33, build-tools 31.0.0
• ANDROID_HOME = C:\Users\G3orG3\AppData\Local\Android\Sdk
• Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java
• Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-9586694)
• All Android licenses accepted.
[√] Chrome - develop for the web • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe
[√] Android Studio (version 2022.2) • Android Studio at C:\Program Files\Android\Android Studio • Flutter plugin can be installed from: https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-9586694)
[√] VS Code (version 1.77.3) • VS Code at C:\Users\G3orG3\AppData\Local\Programs\Microsoft VS Code • Flutter extension version 3.62.0
[√] Connected device (2 available) • Chrome (web) • chrome • web-javascript • Google Chrome 112.0.5615.138 • Edge (web) • edge • web-javascript • Microsoft Edge 112.0.1722.64
[√] Network resources • All expected network resources are available.
• No issues found!
Code to test:
class _MyHomePageState extends State<MyHomePage> {
//create paging controller
final PagingController<int, String> _pagingController =
PagingController(firstPageKey: 0);
@override
void initState() {
//setup paging controller
_pagingController.addPageRequestListener((pageKey) {
//fetch data from server
//here we are using random data
final random = Random();
final nextPageKey = pageKey + random.nextInt(3) + 1;
final items = List.generate(3, (index) => '');
if ((_pagingController.itemList?.length ?? 0) >= 3) {
_pagingController.appendLastPage(items);
return;
}
Future.delayed(const Duration(seconds: 1), () {
_pagingController.appendPage(items, nextPageKey);
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(slivers: [
SliverPadding(
padding: const EdgeInsets.all(10),
sliver: SliverList(
delegate: SliverChildListDelegate([
const Text(
"TESTTT",
),
])),
),
PagedMasonrySliverGrid.extent(
maxCrossAxisExtent: 500,
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<String>(
itemBuilder: (c, item, index) {
return Container(
margin: const EdgeInsets.all(20),
width: double.infinity,
color: Colors.primaries[index % Colors.primaries.length],
child: //create a list with random items count
ListView.builder(
shrinkWrap: true,
primary: false,
itemCount: Random().nextInt(40) + 40,
itemBuilder: (context, index2) {
return ListTile(
title: Text('Parent $index: Child $index2'),
);
},
),
);
},
),
)
]),
);
}
}
when will this be implemented ? @EdsonBueno
@prologikus thank you for your report. I have also noticed this same issue. I am not sure if this issue is related to the staggered grid package or if it is an issue of my implementation. I will take some time to investigate this, as well as rebase my branch.
@EdsonBueno I have fixed the issue. It was related to the appendix builder changing the widget tree and resetting the state.
Could you take a look at this PR?
@prologikus can you help us validate this?
I still use this commit inside my production code and it works. But, the problem is still present.
When there are 2 columns, and the last item is big, the scroll resets here is the full code to test and reproduce:
import 'package:flutter/material.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
//create paging controller
final PagingController<int, String> _pagingController =
PagingController(firstPageKey: 0);
@override
void initState() {
//setup paging controller
_pagingController.addPageRequestListener((pageKey) {
final nextPageKey = pageKey + 1;
final items = List.generate(3, (index) => '');
if (nextPageKey > 1) {
_pagingController.appendLastPage(items);
return;
}
_pagingController.appendPage(items, nextPageKey);
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
PagedMasonrySliverGrid.extent(
maxCrossAxisExtent: 500,
pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<String>(
itemBuilder: (c, item, index) {
return Container(
width: double.infinity,
color: Colors.primaries[index % Colors.primaries.length],
child: //create a list with random items count
ListView.builder(
shrinkWrap: true,
primary: false,
itemCount: index > 4 ? 80 : 30,
itemBuilder: (context, index2) {
return ListTile(
title: Text('Parent $index: Child $index2'),
);
},
),
);
},
),
)
],
),
);
}
}
Thank you for the example.
When we modify the code to exclude pagination all together:
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(),
);
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> items = List.generate(6, (index) => '');
@override
Widget build(BuildContext context) => Scaffold(
body: CustomScrollView(
slivers: [
SliverMasonryGrid.extent(
childCount: items.length,
maxCrossAxisExtent: 500,
itemBuilder: (context, index) => Container(
width: double.infinity,
color: Colors.primaries[index % Colors.primaries.length],
child: ListView.builder(
shrinkWrap: true,
primary: false,
itemCount: index > 4 ? 80 : 30,
itemBuilder: (context, index2) => ListTile(
title: Text('Parent $index: Child $index2'),
),
),
),
),
],
),
);
}
the same issue still occurs. This is therefore an upstream issue and we should notify the developers of flutter_staggered_grid_view
about this behaviour.
@EdsonBueno From my testing, the PR code should work fine, besides the upstream bug. I think we could merge it.
@EdsonBueno everything works here (y)
@clragon
PagedMasonryGridView.count(crossAxisCount: 2,
mainAxisSpacing: 10.w, crossAxisSpacing: 10.w,
showNoMoreItemsIndicatorAsGridChild: false,
showNewPageProgressIndicatorAsGridChild: false,
showNewPageErrorIndicatorAsGridChild: false,
pagingController: controller.pagingController,
padding: EdgeInsets.symmetric(vertical: 5.w),
...
)
mainAxisSpacing: 10.w, crossAxisSpacing: 10.w, not work, there is no space between child; I read the source of PagedMasonryGridView, I think you forget to pass mainAxisSpacing and crossAxisSpacing to PagedMasonrySliverGrid
@override
Widget buildChildLayout(BuildContext context) =>
PagedMasonrySliverGrid<PageKeyType, ItemType>(
builderDelegate: builderDelegate,
pagingController: pagingController,
gridDelegateBuilder: gridDelegateBuilder,
addAutomaticKeepAlives: addAutomaticKeepAlives,
addRepaintBoundaries: addRepaintBoundaries,
addSemanticIndexes: addSemanticIndexes,
showNewPageProgressIndicatorAsGridChild:
showNewPageProgressIndicatorAsGridChild,
showNewPageErrorIndicatorAsGridChild:
showNewPageErrorIndicatorAsGridChild,
showNoMoreItemsIndicatorAsGridChild:
showNoMoreItemsIndicatorAsGridChild,
shrinkWrapFirstPageIndicators: _shrinkWrapFirstPageIndicators,
mainAxisSpacing: mainAxisSpacing, //I add this, problem solved
crossAxisSpacing: crossAxisSpacing, //I add this, problem solved
);
Thank you for your report. However, please file an issue next time. This helps us keep track of things better.
I still haven't managed to use the option to center the items in the PagedMasonryGridView. Can someone help out?
return PagedMasonryGridView<int, T>(
gridDelegateBuilder: (childCount) {
return SliverSimpleGridDelegateWithFixedCrossAxisCount(
crossAxisCount: count,
);
},
showNoMoreItemsIndicatorAsGridChild: false, <------------------------ this line
padding: EdgeInsets.symmetric(
horizontal: width > AppConfig.maxCardWidth
? ((width - AppConfig.maxCardWidth) / count)
: count * 2,
vertical: count * 2,
),
crossAxisSpacing: count * 2,
mainAxisSpacing: count * 2,
reverse: widget.reverse == true,
physics: widget.scrollPhysics ?? const AlwaysScrollableScrollPhysics(),
scrollController: widget.scrollController ??
ScrollController(
initialScrollOffset: widget.moduleController.scrollOffset,
),
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
pagingController: widget.moduleController.pagingController,
builderDelegate: PagedChildBuilderDelegate<T>(
firstPageProgressIndicatorBuilder: (context) => widget.firstLoadingPage,
firstPageErrorIndicatorBuilder: (context) => AppWidgetLoadingErrorPage(
error: widget.moduleController.pagingController.error,
details: _errorDetails ?? 'Contate um administrador do sistema.',
onTryAgain: () => widget.moduleController.pagingController.refresh(),
),
newPageErrorIndicatorBuilder: (context) => AppWidgetLoadingErrorItem(
error: widget.moduleController.pagingController.error,
onTryAgain: () =>
widget.moduleController.pagingController.retryLastFailedRequest(),
),
newPageProgressIndicatorBuilder: (context) =>
const AppWidgetLoadingItemGrid(),
noItemsFoundIndicatorBuilder: (context) => widget.emptyItemsPage,
noMoreItemsIndicatorBuilder: (context) =>
widget.noMoreItemsIndicator ?? const SizedBox(height: 128),
itemBuilder: (context, item, index) =>
widget.itemWidget(item, index) as Widget,
),
);
I added
PagedSliverMasonryGrid
and rewrotePagedMasonryGrid
to use it internally.To facilitate this change, I moved
_AppendedSliverGrid
into its own file.SliverMasonryGrid
is very similar toSliverGrid
but not the same, so reusing this felt right. I imagine if we implement other wrappers around the new custom staggered grid view types, this will also come in handy.All tests pass as usual and I did not add new ones as
PagedMasonrySliverGrid
is tested throughPagedMasonryGridView
and I have seen thatPagedSliverGrid
does not have tests at the moment either.I have reverted
PagedMasonryGridView
to aBoxScrollView
so that it is consistent with other paged sliver wrappers and can be used withpull_to_refresh
.