Skip to content

Instantly share code, notes, and snippets.

@rydmike
Last active July 18, 2022 19:14
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rydmike/e199cb754fc08f4e1500efc96e322eee to your computer and use it in GitHub Desktop.
Save rydmike/e199cb754fc08f4e1500efc96e322eee to your computer and use it in GitHub Desktop.
EXAMPLE: Padding Slivers with SliverPadding and demo of why Padding does not work
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
return runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
systemNavigationBarColor: Colors.grey[100],
statusBarColor: Colors.indigo,
statusBarIconBrightness: Brightness.light,
systemNavigationBarIconBrightness: Brightness.dark,
),
);
return MaterialApp(
title: 'Flutter Grids',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.indigo,
scaffoldBackgroundColor: Colors.grey[100],
buttonTheme: ButtonThemeData(
colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.indigo),
textTheme: ButtonTextTheme.primary,
),
),
home: ExamplesPage(title: 'Flutter GridView Padding Examples'),
);
}
}
class ExamplesPage extends StatelessWidget {
ExamplesPage({Key? key, required this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
centerTitle: true,
elevation: 0,
),
body: SingleChildScrollView(
padding: EdgeInsets.only(top: 40),
child: Row(
children: <Widget>[
Expanded(
flex: 1,
child: Container(),
),
Container(
width: 410,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
SizedBox(height: 20),
Text('EXAMPLE 1 - Simple grid padding case',
style: TextStyle(fontWeight: FontWeight.bold)),
Text(
'Padding on GridView builder is simple, it has a standard '
'padding property, just use it.'),
ElevatedButton(
child: Text('Padding on Gridview builder'),
onPressed: () => GridViewBuilderPage.show(context,
title: 'Padding a GridView builder'),
),
SizedBox(height: 20),
Text('EXAMPLE 2 - Padding on SliverGrid',
style: TextStyle(fontWeight: FontWeight.bold)),
Text(
'Padding on SliverGrid is trickier, wrapping entire CustomScrollView '
'with padding FAILS, it will cover the shadows!'),
ElevatedButton(
child: Text('Padding Slivers and SliverGrid'),
onPressed: () => SliverGridFailPage.show(context,
title: 'Padding a CustomScrollView and SliverGrid'),
),
SizedBox(height: 20),
Text('EXAMPLE 3 - Padding SliverGrid with SliverPadding',
style: TextStyle(fontWeight: FontWeight.bold)),
Text('Padding on SliverGrid is trickier, use SliverPadding!'),
ElevatedButton(
child: Text('Padding Slivers and SliverGrid'),
onPressed: () => SliverGridPage.show(context,
title: 'Padding a CustomScrollView and SliverGrid'),
),
SizedBox(height: 20),
Text('EXAMPLE 4 - SliverGrid fancy pants',
style: TextStyle(fontWeight: FontWeight.bold)),
Text('Padding a SliverGrid works on extend behind '
'AppBar and fancy transparent gradient AppBar too'),
ElevatedButton(
child: Text('Padding fancy Slivers and SliverGrid'),
onPressed: () => SliverGridExtPage.show(context,
title: 'Padding a CustomScrollView and SliverGrid'),
),
],
),
),
Expanded(
flex: 1,
child: Container(),
),
],
),
),
);
}
}
// *****************************************************************************
class GridItem extends StatelessWidget {
const GridItem(
{Key? key,
required this.title,
required this.color,
this.height = 0,
this.bodyText = ''})
: super(key: key);
final String title;
final Color color;
final double height;
final String bodyText;
@override
Widget build(BuildContext context) {
return Container(
color: color,
padding: const EdgeInsets.all(20),
child: Column(
children: <Widget>[
Text(
title,
style: TextStyle(
color: Colors.white,
fontSize: 20,
),
),
if (height > 0) SizedBox(height: height),
if (height > 0 && bodyText != '')
Text(bodyText,
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.bold)),
],
),
);
}
}
// *****************************************************************************
// Example 1
class GridViewBuilderPage extends StatelessWidget {
const GridViewBuilderPage({Key? key, this.title = ''}) : super(key: key);
final String title;
static Future<void> show(BuildContext context, {String title = ''}) async {
await Navigator.of(context).push(MaterialPageRoute(
builder: (context) => GridViewBuilderPage(title: title)));
}
@override
Widget build(BuildContext context) {
var _gridItems = List<GridItem>.generate(400, (index) {
return GridItem(
title: 'Tile nr ${index + 1}',
color: Colors.primaries[index % Colors.primaries.length][800]!);
});
return Scaffold(
appBar: AppBar(
title: Text(title),
centerTitle: true,
elevation: 0,
),
body: Scrollbar(
child: GridView.builder(
padding: EdgeInsets.all(15),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 15,
crossAxisSpacing: 15,
childAspectRatio: 2,
),
itemCount: _gridItems.length,
itemBuilder: (context, index) => Card(
elevation: 12,
child: _gridItems[index],
),
),
),
);
}
}
// *****************************************************************************
// Example 2
class SliverGridFailPage extends StatelessWidget {
const SliverGridFailPage({Key? key, this.title = ''}) : super(key: key);
final String title;
static Future<void> show(BuildContext context, {String title = ''}) async {
await Navigator.of(context).push(MaterialPageRoute(
builder: (context) => SliverGridFailPage(title: title)));
}
@override
Widget build(BuildContext context) {
var _gridItems = List<GridItem>.generate(400, (index) {
return GridItem(
title: 'Tile nr ${index + 1}',
color: Colors.primaries[index % Colors.primaries.length][800]!);
});
return Scaffold(
appBar: AppBar(
title: Text(title),
centerTitle: true,
elevation: 0,
),
body: Scrollbar(
child: ScrollConfiguration(
behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),
child: Padding(
padding: const EdgeInsets.fromLTRB(15, 0, 15, 0),
child: CustomScrollView(
slivers: <Widget>[
SliverList(
delegate: SliverChildListDelegate([
SizedBox(height: 20),
Text(
'SliverGrid FAILED Padding',
style: Theme.of(context).textTheme.headline4,
),
Text('Texts and header in own SliverList so that we can '
'scroll them with the scrolling grid. If we WRAP the '
'CustomScrollView in a Padding, the result is ugly = FAIL! '
'The ELEVATION shadows will be covered by the padding!'),
SizedBox(height: 20),
]),
),
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 15,
crossAxisSpacing: 15,
childAspectRatio: 2,
),
delegate: SliverChildBuilderDelegate(
(ctx, index) {
return Card(
elevation: 6,
child: _gridItems[index],
);
},
childCount: _gridItems.length,
),
),
],
),
),
),
),
);
}
}
// *****************************************************************************
// Example 3
class SliverGridPage extends StatelessWidget {
const SliverGridPage({Key? key, this.title = ''}) : super(key: key);
final String title;
static Future<void> show(BuildContext context, {String title = ''}) async {
await Navigator.of(context).push(
MaterialPageRoute(builder: (context) => SliverGridPage(title: title)));
}
@override
Widget build(BuildContext context) {
var _gridItems = List<GridItem>.generate(400, (index) {
return GridItem(
title: 'Tile nr ${index + 1}',
color: Colors.primaries[index % Colors.primaries.length][800]!);
});
return Scaffold(
appBar: AppBar(
title: Text(title),
centerTitle: true,
elevation: 0,
),
body: Scrollbar(
child: ScrollConfiguration(
behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),
child: CustomScrollView(
slivers: <Widget>[
SliverPadding(
padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
sliver: SliverList(
delegate: SliverChildListDelegate([
SizedBox(height: 20),
Text(
'SliverGrid OK Padding',
style: Theme.of(context).textTheme.headline4,
),
Text('Texts and header in own SliverList so that we can '
'scroll them with the scrolling grid. To get the '
'Padding effect, we must wrap each Sliver in a '
'SliverPadding!'),
SizedBox(height: 20),
]),
),
),
SliverPadding(
padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 15,
crossAxisSpacing: 15,
childAspectRatio: 2,
),
delegate: SliverChildBuilderDelegate(
(ctx, index) {
return Card(
elevation: 6,
child: _gridItems[index],
);
},
childCount: _gridItems.length,
),
),
)
],
),
),
),
);
}
}
// *****************************************************************************
// Example 4
class SliverGridExtPage extends StatelessWidget {
const SliverGridExtPage({Key? key, this.title = ''}) : super(key: key);
final String title;
static Future<void> show(BuildContext context, {String title = ''}) async {
await Navigator.of(context).push(MaterialPageRoute(
builder: (context) => SliverGridExtPage(title: title)));
}
@override
Widget build(BuildContext context) {
var _gridItems = List<GridItem>.generate(400, (index) {
return GridItem(
title: 'Tile nr ${index + 1}',
color: Colors.primaries[index % Colors.primaries.length][800]!);
});
return Scaffold(
extendBodyBehindAppBar: true,
extendBody: true,
appBar: AppBar(
title: Text(title),
centerTitle: true,
elevation: 0,
backgroundColor: Colors.transparent,
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.topRight,
colors: [
Colors.indigo,
Colors.indigo.withOpacity(0.6),
],
),
),
child: null,
),
),
body: Scrollbar(
child: ScrollConfiguration(
behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),
child: CustomScrollView(
slivers: <Widget>[
SliverPadding(
padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
sliver: SliverList(
delegate: SliverChildListDelegate([
SizedBox(height: 20 + kToolbarHeight),
Text(
'SliverGrid OK Padding',
style: Theme.of(context).textTheme.headline4,
),
Text('Texts and header in own SliverList so that we can '
'scroll them with the scrolling grid. Here with scroll '
'behind a fancy gradient transparent AppBar!'),
Text('SliverPadding also works with package '
'StaggeredGrid and its SliverStaggeredGrid but that cannot be '
'shown in DartPad, but here is an another example using it: '),
SelectableText(
'https://gist.github.com/rydmike/5997737351268ad08e35e9f406e73f39'),
SizedBox(height: 20),
]),
),
),
SliverPadding(
padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 15,
crossAxisSpacing: 15,
childAspectRatio: 2,
),
delegate: SliverChildBuilderDelegate(
(ctx, index) {
return Card(
elevation: 6,
child: _gridItems[index],
);
},
childCount: _gridItems.length,
),
),
)
],
),
),
),
);
}
}
@rydmike
Copy link
Author

rydmike commented Feb 21, 2020

You can run this exmple on DartPad here

@rayliverified
Copy link

Nice, I'm seeing you everywhere now 👍

@rydmike
Copy link
Author

rydmike commented Dec 17, 2020

Thx and lol, because how on earth did you even find this old thing! 😃
Although this one contains some nice pointers, I should perhaps add it somewhere on my GitHub Pages site https://rydmike.com/gridview to make this and few other ones like it easier find...

@rydmike
Copy link
Author

rydmike commented Dec 19, 2020

19.12.2020 Updated: Removed the web shadows issues, since it is no longer an issue, at least not to the extent it was when I wrote this demo. It was thus a bit confusing to have in here. Also increased the elevation of the demo card to show the difference better now that the elevation is not as exaggerated as it was before we need to use a bit more elevation to show the difference.

@rayliverified
Copy link

Right, the web shadows were a big issue. Thank you for helping improve the web fidelity with your demos and issues. Creating reproducible samples takes quite a bit of time!

@rydmike
Copy link
Author

rydmike commented Jul 27, 2021

Updated to null safe version and to use ScrollConfiguration to avoid double scrollbars on desktop and web.

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