我正在使用 future 从服务器加载数据,并使用列表视图生成器在列表视图中显示数据,并在滚动到列表末尾时添加新列表,但在新的项目列表时无法显示加载指示器正在加载。我在下面附上了我的代码。我已经尝试过该软件包loadmore但没有运气。
主.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);
};
}
}
}
以下是对我有用的方法(其他人的情况可能有所不同)
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,
),
));
}
}));
}
}
您可以通过使用
Stack
小部件并将 CircularProgressIndicator
与 ListView
重叠来完成此操作。检查下面的代码以获得简化示例:
class LoadingOnScroll60619794 extends StatefulWidget {
@override
_LoadingOnScroll60619794State createState() => _LoadingOnScroll60619794State();
}
class _LoadingOnScroll60619794State extends State<LoadingOnScroll60619794> {
bool _loading = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
icon: Icon(Icons.refresh),
onPressed: runLoading
),
],
),
body: Stack(
children: <Widget>[
ListView(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('item 1'),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('item 1'),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('item 1'),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('item 1'),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('item 1'),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('item 1'),
),
],
),
_loading
? Center(
child: CircularProgressIndicator(),
)
: SizedBox(width: 0, height: 0,)
],
),
);
}
void runLoading(){
setState(() {
_loading = true;
});
Timer(Duration(milliseconds: 1500), (){
setState(() {
_loading = false;
});
});
}
}
如果您修改代码以在每次获取数据时更改 _loading 变量,您将获得相同的效果。就像下面的例子:
Future<Herbslist> fetchPost(gcm) async {
setState(() {
_loading = true;
});
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);
setState(() {
_loading = false;
});
return data;
} else {
setState(() {
_loading = false;
});
throw (e) {
print("Exception thrown: $e");
Exception(e);
};
}
}