I am loading the data from the server using future and displaying the data in list view by using listview builder and adding the new list when we scroll to the end of the list but I am unable to show loading indicator while the new list of items are being loaded. I have attached my code below. I have tried the package loadmore but no luck.
Main.dart
class Herbs extends StatefulWidget {
final String title;
Herbs(this.title);
@override
_HerbsState createState() => new _HerbsState();
}
class _HerbsState extends State<Herbs> {
ScrollController _scrollController = new ScrollController();
var data;
var cname;
String gcm = '';
List pages = [];
@override
void initState() {
super.initState();
fetchPost(gcm);
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
print('Page reached end of page');
setState(() {
Text('Loading');
});
fetchPost(gcm);
}
});
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
cname = widget.title;
var hgt = MediaQuery.of(context).size.width * 0.65;
var wid = MediaQuery.of(context).size.height * 0.58;
return new Scaffold(
appBar: AppBar(
title: Align(
alignment: Alignment(-0.2, 0.3),
child: Text(
cname,
),
),
),
body: Center(
child: FutureBuilder<Herbslist>(
future: fetchPost(gcm),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Scrollbar(
child: ListView.builder(
controller: _scrollController,
shrinkWrap: true,
itemCount: pages == null ? 0 : pages.length,
itemBuilder: (BuildContext context, int index) {
gcm = snapshot.data.herbslistContinue.gcmcontinue;
var img = pages[index].thumbnail.source;
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Detailpage(
pages[index].title,
),
));
},
child: Card(
child: Column(
children: <Widget>[
CachedNetworkImage(
placeholder: (context, url) => Image.asset(
'images/image.png',
height: hgt,
width: wid,
fit: BoxFit.fill,
),
imageUrl: img,
height: hgt,
width: wid,
fit: BoxFit.fill,
),
ListTile(
title: Text(pages[index].title, style: TextStyle(fontWeight: FontWeight.bold),),
)
],
)));
},
),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
),
);
}
Future<Herbslist> fetchPost(gcm) async {
String url =
'https://eample.org/api.php?action=query&gcmtitle=Category:$cname&pilimit=max&prop=pageimages&pithumbsize=200&generator=categorymembers&format=json&gcmcontinue=$gcm';
final response = await http.get(url);
print(url);
if (response.statusCode == 200) {
data = Herbslist.fromJson(json.decode(response.body));
pages.addAll(data.query.pages.values);
return data;
} else {
throw (e) {
print("Exception thrown: $e");
Exception(e);
};
}
}
}
Following is the way which worked for me(Cases maybe different for others)
class _HerbsState extends State<Herbs> {
bool _loading = false;
@override
void initState() {
super.initState();
fetchPost(gcm);
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
print('Page reached end of page');
setState(() {});
fetchPost(gcm);
}
});
}
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
controller: _scrollController,
shrinkWrap: true,
itemCount: pages == null ? 0 : pages.length + 1, //add +1 here
itemBuilder: (BuildContext context, int index) {
if (index == pages.length) {
_loading =
true; // declare the boolean and return loading indicator
return Center(
child: Container(
child: SpinKitThreeBounce(
color: Colors.green,
size: 30,
),
));
}
}));
}
}