Last active
August 31, 2022 14:57
-
-
Save macoshita/7c2d3b376c1140fc8a9cc8f763bf1400 to your computer and use it in GitHub Desktop.
The last step of https://medium.com/flutter/slivers-demystified-6ff68ab0296f
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'dart:math' as math; | |
void main() => runApp(MyApp()); | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
home: Scaffold( | |
appBar: AppBar(title: const Text('Collapsing List Demo')), | |
body: CollapsingList(), | |
), | |
); | |
} | |
} | |
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate { | |
_SliverAppBarDelegate({ | |
required this.minHeight, | |
required this.maxHeight, | |
required this.child, | |
}); | |
final double minHeight; | |
final double maxHeight; | |
final Widget child; | |
@override | |
double get minExtent => minHeight; | |
@override | |
double get maxExtent => math.max(maxHeight, minHeight); | |
@override | |
Widget build( | |
BuildContext context, double shrinkOffset, bool overlapsContent) { | |
return SizedBox.expand(child: child); | |
} | |
@override | |
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) { | |
return maxHeight != oldDelegate.maxHeight || | |
minHeight != oldDelegate.minHeight || | |
child != oldDelegate.child; | |
} | |
} | |
class CollapsingList extends StatelessWidget { | |
List<Widget> makeHeader(String headerText) { | |
final targetKey = GlobalKey(); | |
return [ | |
SliverToBoxAdapter(key: targetKey), | |
SliverPersistentHeader( | |
pinned: true, | |
delegate: _SliverAppBarDelegate( | |
minHeight: 60.0, | |
maxHeight: 200.0, | |
child: GestureDetector( | |
onTap: () { | |
Scrollable.ensureVisible(targetKey.currentContext!, | |
duration: const Duration(milliseconds: 300)); | |
}, | |
child: Container( | |
color: Colors.lightBlue, | |
child: Center(child: Text(headerText)), | |
), | |
), | |
), | |
), | |
]; | |
} | |
@override | |
Widget build(BuildContext context) { | |
return CustomScrollView( | |
slivers: <Widget>[ | |
...makeHeader('Header Section 1'), | |
SliverGrid.count( | |
crossAxisCount: 3, | |
children: [ | |
Container(color: Colors.red, height: 150.0), | |
Container(color: Colors.purple, height: 150.0), | |
Container(color: Colors.green, height: 150.0), | |
Container(color: Colors.orange, height: 150.0), | |
Container(color: Colors.yellow, height: 150.0), | |
Container(color: Colors.pink, height: 150.0), | |
Container(color: Colors.cyan, height: 150.0), | |
Container(color: Colors.indigo, height: 150.0), | |
Container(color: Colors.blue, height: 150.0), | |
], | |
), | |
...makeHeader('Header Section 2'), | |
SliverFixedExtentList( | |
itemExtent: 150.0, | |
delegate: SliverChildListDelegate( | |
[ | |
Container(color: Colors.red), | |
Container(color: Colors.purple), | |
Container(color: Colors.green), | |
Container(color: Colors.orange), | |
Container(color: Colors.yellow), | |
], | |
), | |
), | |
...makeHeader('Header Section 3'), | |
SliverGrid( | |
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( | |
maxCrossAxisExtent: 200.0, | |
mainAxisSpacing: 10.0, | |
crossAxisSpacing: 10.0, | |
childAspectRatio: 4.0, | |
), | |
delegate: SliverChildBuilderDelegate( | |
(BuildContext context, int index) { | |
return Container( | |
alignment: Alignment.center, | |
color: Colors.teal[100 * (index % 9)], | |
child: Text('grid item $index'), | |
); | |
}, | |
childCount: 20, | |
), | |
), | |
...makeHeader('Header Section 4'), | |
// Yes, this could also be a SliverFixedExtentList. Writing | |
// this way just for an example of SliverList construction. | |
SliverList( | |
delegate: SliverChildListDelegate( | |
[ | |
Container(color: Colors.pink, height: 150.0), | |
Container(color: Colors.cyan, height: 150.0), | |
Container(color: Colors.indigo, height: 150.0), | |
Container(color: Colors.blue, height: 150.0), | |
], | |
), | |
), | |
], | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment