-
-
Notifications
You must be signed in to change notification settings - Fork 513
Open
Description
https://github.com/user-attachments/assets/789583f0-155b-4e93-8829-31e6c1556a0b
Hi, I have found some unexpected jump. You can reproduce by follow code.
Main reason:
The footer sliver is too high and if user scroll the view to bottom all the time some unexpected jump will happen!
Btw, it's only happened when crossAxisCount >= 2.
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class LifecycleMonitor extends StatefulWidget {
final Widget child;
final String tag;
final int index;
const LifecycleMonitor({
super.key,
required this.child,
this.tag = 'Container',
this.index = 0,
});
@override
State<LifecycleMonitor> createState() => _LifecycleMonitorState();
}
class _LifecycleMonitorState extends State<LifecycleMonitor> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
print('π ${widget.tag} - initState index:${widget.index}');
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
print('π ${widget.tag} - didChangeDependencies index:${widget.index}');
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
print('π ${widget.tag} - dispose index:${widget.index}');
super.dispose();
}
@override
void didUpdateWidget(LifecycleMonitor oldWidget) {
super.didUpdateWidget(oldWidget);
print('π¦ ${widget.tag} - didUpdateWidget index:${widget.index}');
}
@override
Widget build(BuildContext context) {
print('ποΈ ${widget.tag} - build index:${widget.index}');
return widget.child;
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
print('π ${widget.tag} - App Lifecycle: $state');
}
}
class MyHomePage extends StatelessWidget {
final GlobalKey scrollViewKey = GlobalKey();
final ScrollController finalScrollController = ScrollController();
final Axis scrollDirection = Axis.vertical;
final double? cacheExtent = 1000.0;
final int? crossAxisCount = 2;
final double? mainAxisSpacing = 10.0;
final double? crossAxisSpacing = 10.0;
final int _finalItemCount = 20;
ScrollPhysics getScrollPhysics() {
return BouncingScrollPhysics();
}
Widget _buildChildWidget(BuildContext context, int index) {
print('π¨ _buildChildWidget $index');
return LifecycleMonitor(
tag: 'MySpecialContainer',
index: index,
child: Container(
color: Colors.blueAccent,
height: 100,
margin: EdgeInsets.all(5),
child: Center(
child: Text('Item $index', style: TextStyle(color: Colors.white)),
),
),
);
}
void _finishLayoutCallBack(int index) {
print('π _finishLayoutCallBack $index');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Custom Scroll View Example'),
),
body: CustomScrollView(
key: scrollViewKey,
physics: getScrollPhysics(),
controller: finalScrollController,
scrollDirection: scrollDirection,
cacheExtent: cacheExtent,
slivers: [
SliverList(
delegate: CustomSliverChildBuilderDelegate(
(context, index) => Center(
child: Text(
'Header',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
),
_finishLayoutCallBack,
childCount: 1,
),
),
SliverMasonryGrid(
gridDelegate: SliverSimpleGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount ?? 1, // Number of columns
),
delegate: CustomSliverChildBuilderDelegate(
_buildChildWidget,
_finishLayoutCallBack,
childCount: _finalItemCount,
),
mainAxisSpacing: mainAxisSpacing ?? 0,
crossAxisSpacing: crossAxisSpacing ?? 0,
),
SliverList(
delegate: CustomSliverChildBuilderDelegate(
(context, index) => _buildFooterItem(index),
_finishLayoutCallBack,
childCount: 3,
),
),
],
),
);
}
Widget _buildFooterItem(int index) {
return Container(
color: Colors.red,
height: 500,
margin: EdgeInsets.all(10),
child: Center(
child: Text(
'Footer Item $index',
style: TextStyle(color: Colors.white, fontSize: 24),
),
),
);
}
}
class CustomSliverChildBuilderDelegate extends SliverChildBuilderDelegate {
CustomSliverChildBuilderDelegate(
Widget Function(BuildContext, int) builder,
this.finishLayoutCallBack, {
int? childCount,
}) : super(builder, childCount: childCount);
final void Function(int) finishLayoutCallBack;
@override
void didFinishLayout(int firstIndex, int lastIndex) {
super.didFinishLayout(firstIndex, lastIndex);
finishLayoutCallBack(lastIndex);
}
}
Mistic92
Metadata
Metadata
Assignees
Labels
No labels