What I'm trying to do is have a GridView with a variable/dynamic CrossAxisCount.
I have a FutureBuilder retrieving data from an API and sometimes I need to show one item per line and sometimes I need to show two items per line, depending on some item properties.
Being more specific the condition is:
if (previousItem != null && items[index].idCategory != previousItem.idCategory && items[index].isOdd)
.
The list of items would have around 700 items, please remember that crossAxisCount is final in most of the constructors.
I found the following code on Stackoverflow but it is not compatible with the latest version of flutter_staggered_grid_view.
I have other things on the app using version 0.6.2 of that package so I cannot use version ^0.4.0.
class Staggered extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: StaggeredGridView.count(
crossAxisCount: 2,
mainAxisSpacing: 5,
crossAxisSpacing: 5,
children: List.generate(14, (index){
return Container(
child: Center(
child: Text("${index+1}"),
),
color: Colors.blue,
);
}),
staggeredTiles: buildTiles(),
),
),
);
}
List<StaggeredTile> buildTiles(){
return List.generate(14, (index){
if((index+1)%7 == 0){
return StaggeredTile.count(2, 1);
}else{
return StaggeredTile.count(1, 1);
}
});
}
}
update: the following is exactly what I'm trying to achieve using the latest version of that package.
return StaggeredGridView.countBuilder(
crossAxisCount: 2,
mainAxisSpacing: 4,
crossAxisSpacing: 4,
itemCount: cards.length,
itemBuilder: (context, index) {
return Container(
width: 187,
height: 210,
color: Colors.red,
child: Text('$index - ${cards[index].id} - ${cards[index].idStoreCategory}',
style: const TextStyle(color: Colors.white, fontSize: 20)),
);
},
staggeredTileBuilder: (index) {
final nextItem = index < cards.length - 1 ? cards[index + 1] : null;
if (nextItem != null && cards[index].idStoreCategory != nextItem.idStoreCategory && index.isEven) {
return StaggeredTile.count(2, 1);
} else {
return StaggeredTile.count(1, 1);
}
},
);```
So, you want a custom GridView
widget which shows crossAxisCount
dynamically based on your API response. Sometimes, single or N items in a row. So, here I wrote a sample code for you. I hope it helps you. Feel free to ask.
import "package:flutter/material.dart";
import "package:get/get.dart";
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return GetMaterialApp(
home: const Sample(),
theme: ThemeData(),
);
}
}
class Sample extends StatefulWidget {
const Sample({super.key});
@override
State<Sample> createState() => _SampleState();
}
class _SampleState extends State<Sample> {
int currentIndex = 0;
final List<List<dynamic>> items = <List<dynamic>>[
<dynamic>["Hello"],
<dynamic>["Hello", "World"],
<dynamic>["Hello", "World", "Yay!"],
<dynamic>["Hello"],
<dynamic>["Hello", "World"],
<dynamic>["Hello", "World", "Yay!"],
];
@override
Widget build(BuildContext context) {
if (currentIndex != 0) {
currentIndex = 0;
} else {}
return Scaffold(
body: SafeArea(
child: GridView.builder(
shrinkWrap: true,
itemCount: items.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: items[currentIndex].length,
childAspectRatio: 16 / 9,
),
itemBuilder: (BuildContext context, int builderIndex) {
currentIndex = builderIndex;
return Row(
children: List<Widget>.generate(
items[currentIndex].length,
(int listItemIndex) {
return SizedBox(
width: Get.width / items[currentIndex].length,
child: Text(items[currentIndex][listItemIndex]),
);
},
),
);
},
),
),
);
}
}