Flutter Listview builder show data in two rows depending upon `index` is odd or event - flutter

I am fairly new in Flutter, I am fetching data from api and displaying it in a listview. I have following demo code.
/*Other codes*/
return ListView.builder(
//Other Codes
physics: const AlwaysScrollableScrollPhysics(),
itemCount: item.length,
padding: new EdgeInsets.only(top: 5.0),
itemBuilder: (context, index) {
});
My requirement is to show data in Two Rows, such that if the item in index is even show it in first row and if its odd, show it in another row? More like in the Image below.
Update: There could be many items and can be scrolled horizontally to reveal more items.
Can we achieve this without manipulating the data received from API? From API the data comes in date-wise sorted in descending order.
Thanks

GridView.builder is probably what you are looking for.
Just give it scrollDirection: Axis.horizontal to make it horizontal.
Then give it gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2) to make sure you have only 2 rows.
Then use SizedBox to restrict the height of the GridView to 90 + 90.
Finally, use the childAspectRatio property of the SliverGridDelegateWithFixedCrossAxisCount to specify that you want your aspect ratio to be 90 / 256.
Color randomColor() => Color.fromARGB(255, Random().nextInt(255), Random().nextInt(100), Random().nextInt(200));
class MyApp extends StatelessWidget {
List<String> array = ["0", "1", "2", "3"];
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Example')),
body: SizedBox(
height: 90 + 90,
child: GridView.builder(
itemCount: 4,
scrollDirection: Axis.horizontal,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 90 / 256,
crossAxisCount: 2,
),
itemBuilder: (context, index) {
return Container(
color: randomColor(), child: Text(array[index])
);
}
),
),
),
);
}
}

Related

Flutter: How to show a widget after every 3 rows in a gridview.count

I am trying to implement a banner ad widget like so
AdBanner()
in a GridView.count widget. I want the ad widget to show after every 3 rows within the grid (i.e, below every 6th item). I'm not able to get the logic. Can anyone here, please help me out? Thanks. Here is the code for my gridview
Expanded(
child: GridView.count(
shrinkWrap: true,
controller: _scrollController,
crossAxisCount: 2,
childAspectRatio: 0.68,
physics: const ClampingScrollPhysics(),
scrollDirection: Axis.vertical,
children: items.map((Product item) {
return Container(
color: Colors.black,
margin: const EdgeInsets.only(top: 10),
child: ProductCard(data: item));
}).toList(),
),
I have added an image below to further explain what I mean. Though this is a listview, but if I can get it in listview, I will implement the grid. In the image, we can see a banner ad showing up after every 6th item in the list
You can try a different approach with GridView.builder()
int ad_count = items.length ~/ 6; // divide by number of entries between every ad
int showed_ads = 0; // counter variable
GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemCount: items.length + ad_count,
itemBuilder: (BuildContext ctx, index) {
if((index+1)%ad_count == 0) // modulo defines the count between every ad
{
showed_ads += 1;
return AdBanner(); // your AdBanner class here
}
return Container(
color: Colors.black,
margin: const EdgeInsets.only(top: 10),
child: ProductCard(data: item[index-showed_ads]));
}),

I want the SingleChildScrollView to stay fixed

I used SingleChildScrollView in the table I created friends. I want SingleChildScrollView to stay on the screen all the time, how can I do this (i.e. I don't want it to be shown only when I come with the mouse)
my code
enter link description here
I want the scrollbar to stay fixed
wrap your List with ScrollBar.
set isAlwaysShown = true
Scrollbar(
isAlwaysShown: true,
child: GridView.builder(
itemCount: 10,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return Center(
child: Text('item $index'),
);
},
),
);

Flutter. How to collapse GridView.builder when it empty (do not have any elements)

I have a GridView.builder with shrinkWrap to true. It fills dynamically, but the problem that at start it empty but takes place, like it has elements (sort of reserving place) depends on the size of maxCrossAxisExtent.
Is it possible change this? Empty space not very good..
I looked docs and google but didnt find any answer.
This is the code
class _PhotosState extends State<Photos> {
List<File> photos = [];
final ImagePicker _picker = ImagePicker();
Widget getGrid() {
return Container(
child: GridView.builder(
padding: EdgeInsets.all(0),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
//childAspectRatio: 3 / 2,
// crossAxisSpacing: 10,
// mainAxisSpacing: 10,
//mainAxisExtent: 200,
),
itemCount: photos.length,
itemBuilder: (BuildContext ctx, index) {
return Container(
color: Colors.blueGrey,
);
},
),
);
}
The empty GridView with empty space
One element added to GridView
try
Widget getGrid() {
return photos.length<1?SizedBox():
Container(
child: GridView.builder(

Staggered Gridview creates column of photos instead of grid

I trying to create a Staggered Gridview widget, but it's creates Column of photos instead of grid.
I want to create a grid of photos with 3 photos in a row.
I tried to change crossAxisCount and StaggeredTile.fit.
Here is my code for my widget:
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:flutter_svg/flutter_svg.dart';
class MyMediaWidget extends StatelessWidget {
final List<String> images = [
'assets/png/photo1.png',
'assets/png/photo2.png',
'assets/png/photo3.png',
'assets/png/photo4.png',
'assets/png/photo5.png',
'assets/png/photo6.png',
'assets/png/photo7.png',
'assets/png/photo8.png',
'assets/png/photo9.png',
];
#override
Widget build(BuildContext context) {
return StaggeredGridView.countBuilder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: ScrollPhysics(),
crossAxisCount: 3,
itemCount: images.length,
itemBuilder: (BuildContext context, int index) => Stack(
children: [
ClipRRect(
child: Image.asset(
images[index],
),
borderRadius: BorderRadius.circular(10),
),
Positioned(
top: 5,
right: 5,
child: InkWell(
onTap: () {},
child: SvgPicture.asset('assets/svg/close.svg', color: Color(0xFFCF6679),),
),
),
],
),
staggeredTileBuilder: (int index) => StaggeredTile.fit(3),
mainAxisSpacing: 10,
crossAxisSpacing: 10,
);
}
}
And here is how it looks now:
Change StaggeredTile.fit(3), to StaggeredTile.count(1,1),
(the first parameter is how much you want an item to stretch horizontally / x-axis and the second parameter is how much you want it to stretch vertically / y-axis).
It basically subdivides your cross-axis count into further more columns. So if you had 6 for cross-axis a .count(2,1) will put your 3 items on the first line each occupying 2 imaginary columns out of your 6.
Right now your code does the same thing as StaggeredTile.count(3,1) would do.

Why is GridView.builder creating the same random image?

How is it that "http://lorempixel.com/300/300/" returns the same image for all the grid tiles in the following example?
Widget build(BuildContext context) {
return GridView.builder(
itemCount: 100,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 2,
mainAxisSpacing: 2,
),
itemBuilder: (BuildContext context, int index) {
return Container(
color: Colors.grey,
child: Center(child: Image.network("http://lorempixel.com/300/300/")),
);
},
);
}
It seems that the result of the first request to "http://lorempixel.com/300/300" is used for all images. Why?
It's due to the structure of Image widget and its Image.network constructor which caches all Images loaded through it. They mention that in the Image widget documentation :
All network images are cached regardless of HTTP headers.