Skip to content

Instantly share code, notes, and snippets.

@slightfoot
Last active August 29, 2020 01:17
Show Gist options
  • Save slightfoot/e386f10cb80c5770d24f5c94828087e5 to your computer and use it in GitHub Desktop.
Save slightfoot/e386f10cb80c5770d24f5c94828087e5 to your computer and use it in GitHub Desktop.
Staggered GridView with Example - by Simon Lightfoot - 19/08/2020
import 'package:flutter/material.dart';
import 'staggered_grid.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
home: HomeScreen(),
),
);
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Material(
child: Transform.scale(
scale: 0.7,
child: Container(
foregroundDecoration: BoxDecoration(
border: Border.all(color: Colors.red, width: 2.0),
),
child: StaggeredGridView(
//clipBehavior: Clip.none,
crossAxisCount: 2,
childAspectRatio: 0.65,
itemCount: 20,
spacing: 24.0,
itemBuilder: (BuildContext context, int index) {
return ListItem(index: index);
},
),
),
),
);
}
}
class ListItem extends StatelessWidget {
const ListItem({
Key key,
@required this.index,
}) : super(key: key);
final int index;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Card(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
shadowColor: Colors.black38,
elevation: 16.0,
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
children: [
Expanded(
child: Placeholder(
color: Colors.primaries[(index * 3) % Colors.primaries.length],
),
),
Expanded(
child: Column(
children: [
const SizedBox(height: 8.0),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Text(
'This Is Cool Item $index',
textAlign: TextAlign.center,
style: theme.textTheme.headline6,
overflow: TextOverflow.ellipsis,
maxLines: 2,
),
),
const SizedBox(height: 4.0),
Text(
'Subtitle',
textAlign: TextAlign.center,
style: theme.textTheme.subtitle1.copyWith(
color: Colors.grey,
),
maxLines: 1,
),
Spacer(),
RatingBar(rating: 3.5),
],
),
),
],
),
),
);
}
}
class RatingBar extends StatelessWidget {
const RatingBar({
Key key,
@required this.rating,
this.color = Colors.amber,
this.size = 18.0,
}) : super(key: key);
final double rating;
final Color color;
final double size;
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: List.generate(5, (int index) {
return Icon(
() {
if (index < rating.floor()) {
return Icons.star;
} else if (index + 0.5 <= rating) {
return Icons.star_half;
} else {
return Icons.star_border;
}
}(),
color: color,
size: size,
);
}),
);
}
}
// MIT License
//
// Copyright (c) 2020 Simon Lightfoot
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import 'package:flutter/material.dart';
class StaggeredGridView extends StatelessWidget {
const StaggeredGridView({
Key key,
@required this.crossAxisCount,
@required this.childAspectRatio,
@required this.itemCount,
@required this.itemBuilder,
this.spacing = 0.0,
this.clipBehavior = Clip.hardEdge,
}) : super(key: key);
final double spacing;
final int crossAxisCount;
final int itemCount;
final IndexedWidgetBuilder itemBuilder;
final double childAspectRatio;
final Clip clipBehavior;
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
assert(constraints.hasBoundedWidth && constraints.hasBoundedHeight);
final width = constraints.maxWidth;
final childHeight = ((width / crossAxisCount) * childAspectRatio);
final height = constraints.maxHeight + childHeight + spacing;
final content = OverflowBox(
alignment: Alignment.bottomLeft,
minWidth: width,
maxWidth: width,
minHeight: height,
maxHeight: height,
child: GridView.builder(
padding: EdgeInsets.fromLTRB(
spacing,
spacing + childHeight + spacing,
spacing,
itemCount.isEven ? childHeight + spacing * 2 : spacing,
),
cacheExtent: height * 1.5,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
childAspectRatio: childAspectRatio,
mainAxisSpacing: spacing,
crossAxisSpacing: spacing,
),
itemCount: itemCount,
itemBuilder: (BuildContext context, int index) {
return Transform.translate(
offset: Offset(0.0, index.isOdd ? childHeight + (spacing * 0.5) : 0.0),
child: itemBuilder(context, index),
);
},
),
);
if (clipBehavior == Clip.none) {
return content;
} else {
return ClipRect(
clipBehavior: clipBehavior,
child: content,
);
}
},
);
}
}
@JMario1
Copy link

JMario1 commented Aug 28, 2020

Great work

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