For Limited Scroll
The solution is simple you just have to add itemCount to the builder so that the builder allows it to know the item count. Just like the above Code As stated in the this answer
For Infinite Scroll
To do Infinite Scroll use ListView.builder without specifying the itemCount parameter.
body: ListView.builder(
itemCount: _photos.length + (_hasMore ? 1 : 0),
itemBuilder: (context, index) {
if (index == item.length - _nextPageThreshold) {
// Here is your manuplated data code
} else {
getMoreData();
return Center(child: CircularProgressIndicator());
}
},
),
Full code example
class ItemListScreen extends StatefulWidget {
ItemListScreen({Key key}) : super(key: key);
@override
_PhotosListScreenState createState() => _PhotosListScreenState();
}
class _PhotosListScreenState extends State<ItemListScreen> {
bool _hasMore;
int _pageNumber;
bool _error;
bool _loading;
final int _defaultPhotosPerPageCount = 10;
List<Photo> _photos;
final int _nextPageThreshold = 5;
@override
void initState() {
super.initState();
_hasMore = true;
_pageNumber = 1;
_error = false;
_loading = true;
_photos = [];
fetchPhotos();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Photos App")),
body: getBody(),
);
}
Widget getBody() {
if (_photos.isEmpty) {
if (_loading) {
return Center(
child: Padding(
padding: const EdgeInsets.all(8),
child: CircularProgressIndicator(),
));
} else if (_error) {
return Center(
child: InkWell(
onTap: () {
setState(() {
_loading = true;
_error = false;
fetchPhotos();
});
},
child: Padding(
padding: const EdgeInsets.all(16),
child: Text("Error while loading photos, tap to try agin"),
),
));
}
} else {
return ListView.builder(
itemCount: _photos.length + (_hasMore ? 1 : 0),
itemBuilder: (context, index) {
if (index == _photos.length - _nextPageThreshold) {
fetchPhotos();
}
if (index == _photos.length) {
if (_error) {
return Center(
child: InkWell(
onTap: () {
setState(() {
_loading = true;
_error = false;
fetchPhotos();
});
},
child: Padding(
padding: const EdgeInsets.all(16),
child: Text("Error while loading photos, tap to try agin"),
),
));
} else {
return Center(
child: Padding(
padding: const EdgeInsets.all(8),
child: CircularProgressIndicator(),
));
}
}
final Photo photo = _photos[index];
return Card(
child: Column(
children: <Widget>[
Image.network(
photo.thumbnailUrl,
fit: BoxFit.fitWidth,
width: double.infinity,
height: 160,
),
Padding(
padding: const EdgeInsets.all(16),
child: Text(photo.title,
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16)),
),
],
),
);
});
}
return Container();
}
Future<void> fetchPhotos() async {
try {
final response = await http.get("https://jsonplaceholder.typicode.com/photos?_page=$_pageNumber");
List<Photo> fetchedPhotos = Photo.parseList(json.decode(response.body));
setState(() {
_hasMore = fetchedPhotos.length == _defaultPhotosPerPageCount;
_loading = false;
_pageNumber = _pageNumber + 1;
_photos.addAll(fetchedPhotos);
});
} catch (e) {
setState(() {
_loading = false;
_error = true;
});
}
}
}
class Photo {
final String title;
final String thumbnailUrl;
Photo(this.title, this.thumbnailUrl);
factory Photo.fromJson(Map<String, dynamic> json) {
return Photo(json["title"], json["thumbnailUrl"]);
}
static List<Photo> parseList(List<dynamic> list) {
return list.map((i) => Photo.fromJson(i)).toList();
}
}
to infinite scroll answer credit and for more info Infinite Scrolling ListView
itemCountparameter toListView.builder()constructor - pskink