添加无限滚动到 GridView.builder 以 flutter FutureBuilder
Add infinite scroll to GridView.builder to flutter FutureBuilder
我很难在 flutter 中专注于无限滚动。
我试图先加载 10 个食谱,然后在 ScrollController 的帮助下显示新的食谱。
当没有更多食谱时,我想显示一条消息,表明没有更多帖子。
这是我的项目代码。
import 'package:flutter/material.dart';
import 'package:test/model/recipe.dart';
import 'package:test/pages/recipe_details.dart';
import 'package:test/widgets/recipe_card.dart';
import 'package:http/http.dart' as http;
class SingleCategory extends StatefulWidget {
final Recipe recipe;
final int recipeCourseid;
final String recipeCourseName;
SingleCategory({
this.recipe,
@required this.recipeCourseid,
@required this.recipeCourseName,
});
@override
_SingleCategoryState createState() => _SingleCategoryState();
}
class _SingleCategoryState extends State<SingleCategory> {
ScrollController _scrollController = ScrollController();
int pageNumber = 1;
var myRecipe;
Future<List<Recipe>> getRecipeList({int pageNumber}) async {
// pageNum = 1;
var response = await http.get(
'https://test.com/wp-json/wp/v2/wprm_recipe?wprm_course=${widget.recipeCourseid}&per_page=10&$pageNumber');
var body = response.body;
final recipes = recipeFromJson(body)
return recipes;
}
@override
void initState() {
super.initState();
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
pageNumber++;
print(pageNumber);
getRecipeList();
}
});
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.rtl,
child: Scaffold(
appBar: AppBar(
title: Text(widget.recipeCourseName),
centerTitle: true,
elevation: 5,
),
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 12.0),
child: FutureBuilder(
future: getRecipeList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return GridView.builder(
controller: _scrollController,
itemCount: snapshot.data.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 12.0,
mainAxisSpacing: 12.0,
),
itemBuilder: (BuildContext context, int index) {
myRecipe = snapshot.data[index].recipe;
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RecipeDetails(
recipe: snapshot.data[index],
),
),
);
},
child: RecipeCard(myRecipe: myRecipe),
);
},
);
} else if (snapshot.hasError) {
return Center(
child: Text('There was an error, Please try again'),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
),
),
);
}
}
如果你能指出正确的方向,我将不胜感激。
尝试在您的 GridView 中添加
physics: const AlwaysScrollableScrollPhysics(),
一切看起来都不错,但你必须做一点小改动。
您的代码:
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
pageNumber++;
print(pageNumber);
getRecipeList();
}
});
应该是:
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
pageNumber++;
setState(() {}); // if add this, Reload your futurebuilder and load more data
// getRecipeList(); // It's not necessary because, FutureBuilder call automatically getRecipeList when you call setState
}
});
在 class
中声明一个新变量
List<Recipe> recipesList;
并且在 getRecipeList() 方法内部更改如下
Future<List<Recipe>> getRecipeList({int pageNumber}) async {
// pageNum = 1;
If(page number ==1)
recipesList.clear;
var response = await http.get(
'https://test.com/wp-json/wp/v2/wprm_recipe?wprm_course=${widget.recipeCourseid}&per_page=10&$pageNumber');
var body = response.body;
final recipes = recipeFromJson(body)
recipesList.addAll(recipes);
return recipesList;
}
并在 scrollListener 中尝试传递 pageNumber。由于您在 getRecipesList 方法内外都为 pageNumber 声明了相同的名称。
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
pageNumber++;
print(pageNumber);
getRecipeList(pageNumber:pageNumber).then((){
setState((){});
});
}
});
我很难在 flutter 中专注于无限滚动。 我试图先加载 10 个食谱,然后在 ScrollController 的帮助下显示新的食谱。 当没有更多食谱时,我想显示一条消息,表明没有更多帖子。
这是我的项目代码。
import 'package:flutter/material.dart';
import 'package:test/model/recipe.dart';
import 'package:test/pages/recipe_details.dart';
import 'package:test/widgets/recipe_card.dart';
import 'package:http/http.dart' as http;
class SingleCategory extends StatefulWidget {
final Recipe recipe;
final int recipeCourseid;
final String recipeCourseName;
SingleCategory({
this.recipe,
@required this.recipeCourseid,
@required this.recipeCourseName,
});
@override
_SingleCategoryState createState() => _SingleCategoryState();
}
class _SingleCategoryState extends State<SingleCategory> {
ScrollController _scrollController = ScrollController();
int pageNumber = 1;
var myRecipe;
Future<List<Recipe>> getRecipeList({int pageNumber}) async {
// pageNum = 1;
var response = await http.get(
'https://test.com/wp-json/wp/v2/wprm_recipe?wprm_course=${widget.recipeCourseid}&per_page=10&$pageNumber');
var body = response.body;
final recipes = recipeFromJson(body)
return recipes;
}
@override
void initState() {
super.initState();
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
pageNumber++;
print(pageNumber);
getRecipeList();
}
});
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.rtl,
child: Scaffold(
appBar: AppBar(
title: Text(widget.recipeCourseName),
centerTitle: true,
elevation: 5,
),
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 12.0),
child: FutureBuilder(
future: getRecipeList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return GridView.builder(
controller: _scrollController,
itemCount: snapshot.data.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 12.0,
mainAxisSpacing: 12.0,
),
itemBuilder: (BuildContext context, int index) {
myRecipe = snapshot.data[index].recipe;
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RecipeDetails(
recipe: snapshot.data[index],
),
),
);
},
child: RecipeCard(myRecipe: myRecipe),
);
},
);
} else if (snapshot.hasError) {
return Center(
child: Text('There was an error, Please try again'),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
),
),
);
}
}
如果你能指出正确的方向,我将不胜感激。
尝试在您的 GridView 中添加
physics: const AlwaysScrollableScrollPhysics(),
一切看起来都不错,但你必须做一点小改动。
您的代码:
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
pageNumber++;
print(pageNumber);
getRecipeList();
}
});
应该是:
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
pageNumber++;
setState(() {}); // if add this, Reload your futurebuilder and load more data
// getRecipeList(); // It's not necessary because, FutureBuilder call automatically getRecipeList when you call setState
}
});
在 class
中声明一个新变量 List<Recipe> recipesList;
并且在 getRecipeList() 方法内部更改如下
Future<List<Recipe>> getRecipeList({int pageNumber}) async {
// pageNum = 1;
If(page number ==1)
recipesList.clear;
var response = await http.get(
'https://test.com/wp-json/wp/v2/wprm_recipe?wprm_course=${widget.recipeCourseid}&per_page=10&$pageNumber');
var body = response.body;
final recipes = recipeFromJson(body)
recipesList.addAll(recipes);
return recipesList;
}
并在 scrollListener 中尝试传递 pageNumber。由于您在 getRecipesList 方法内外都为 pageNumber 声明了相同的名称。
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
pageNumber++;
print(pageNumber);
getRecipeList(pageNumber:pageNumber).then((){
setState((){});
});
}
});