Listview 在颤振中滚动到列表末尾时如何显示加载指示器
我使用future从服务器加载数据,使用listview builder在列表视图中显示数据,并在滚动到列表末尾时添加新列表,但在加载新项目列表时,我无法显示加载指示器。我在下面附上了我的代码。我试过这个包裹,但运气不好 主飞镖Listview 在颤振中滚动到列表末尾时如何显示加载指示器,listview,flutter,lazy-loading,Listview,Flutter,Lazy Loading,我使用future从服务器加载数据,使用listview builder在列表视图中显示数据,并在滚动到列表末尾时添加新列表,但在加载新项目列表时,我无法显示加载指示器。我在下面附上了我的代码。我试过这个包裹,但运气不好 主飞镖 class Herbs extends StatefulWidget { final String title; Herbs(this.title); @override _HerbsState createState() => new _Her
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);
};
}
}
}
类扩展StatefulWidget{
最后的字符串标题;
草药(本标题);
@凌驾
_HerbsState createState()=>new_Herbstate();
}
类_herbstate扩展状态{
ScrollController_ScrollController=新的ScrollController();
var数据;
var-cname;
字符串gcm='';
列表页=[];
@凌驾
void initState(){
super.initState();
fetchPost(gcm);
_scrollController.addListener((){
如果(_scrollController.position.pixels==
_scrollController.position.maxScrollExtent){
打印(“页面到达页面末尾”);
设置状态(){
文本(“加载”);
});
fetchPost(gcm);
}
});
}
@凌驾
无效处置(){
_scrollController.dispose();
super.dispose();
}
@凌驾
小部件构建(构建上下文){
cname=widget.title;
var hgt=MediaQuery.of(context).size.width*0.65;
var wid=MediaQuery.of(context).size.height*0.58;
归还新脚手架(
appBar:appBar(
标题:对齐(
对齐:对齐(-0.2,0.3),
子:文本(
cname,
),
),
),
正文:中(
孩子:未来建设者(
未来:fetchPost(gcm),
生成器:(上下文,快照){
if(snapshot.hasData){
返回滚动条(
子项:ListView.builder(
控制器:\ u滚动控制器,
收缩膜:对,
itemCount:pages==null?0:pages.length,
itemBuilder:(构建上下文,int索引){
gcm=snapshot.data.herbslitcontinue.gcmcontinue;
var img=pages[index].thumbnail.source;
返回手势检测器(
onTap:(){
导航器。推(
上下文
材料路线(
生成器:(上下文)=>Detailpage(
页[索引]。标题,
),
));
},
孩子:卡片(
子:列(
儿童:[
CachedNetworkImage(
占位符:(上下文,url)=>Image.asset(
“images/image.png”,
高度:hgt,
宽度:wid,
fit:BoxFit.fill,
),
imageUrl:img,
高度:hgt,
宽度:wid,
fit:BoxFit.fill,
),
列表砖(
标题:文本(页面[索引]。标题,样式:TextStyle(fontWeight:fontWeight.bold),
)
],
)));
},
),
);
}否则{
返回中心(
子对象:CircularProgressIndicator(),
);
}
},
),
),
);
}
未来回迁(gcm)异步{
字符串url=
'https://eample.org/api.php?action=query&gcmtitle=Category:$cname&pilimit=max&prop=pageimages&pitumbsize=200&generator=categorymembers&format=json&gcmcontinue=$gcm';
最终响应=等待http.get(url);
打印(url);
如果(response.statusCode==200){
data=Herbslist.fromJson(json.decode(response.body));
pages.addAll(data.query.pages.values);
返回数据;
}否则{
投掷(e){
打印(“抛出异常:$e”);
例外情况(e);
};
}
}
}
您可以通过使用堆栈
小部件并将循环压缩器指示器
与列表视图
重叠来完成此操作。查看下面的代码以获取简化示例:
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;
});
});
}
}
class LoadingOnScroll60619794扩展StatefulWidget{
@凌驾
_LoadingOnScroll60619794State createState()=>_LoadingOnScroll60619794State();
}
类_LoadingOnScroll60619794State扩展状态{
bool\u加载=假;
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
行动:[
图标按钮(
图标:图标(Icons.refresh),
onPressed:运行加载
),
],
),
主体:堆栈(
儿童:[
列表视图(
儿童:[
填充物(
填充:常数边集全部(8.0),
子项:文本(“项目1”),
),
填充物(
填充:常数边集全部(8.0),
子项:文本(“项目1”),
),
填充物(
填充:常数边集全部(8.0),
子项:文本(“项目1”),
),
填充物(
填充:常数边集全部(8.0),
子项:文本(“项目1”),
),
填充物(
填充:常数边集全部(8.0),
子项:文本(“项目1”),
),
填充物(
填充:常数边集全部(8.0),
子项:文本(“项目1”),
),
],
),
_装载
?中心(
子对象:CircularProgressIndicator(),
)
:SizedBox(宽度:0,
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);
};
}
}
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(
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,
),
));
}
)
}
}