Flutter 在Flatter中实现无限卷轴GridView的最佳实践?
我想创建一个GridView,显示将按偏移量从服务器获取的项目。我在GridView中只加载10个项目,当用户滚动到10个后,我将加载更多的10个项目。在Flatter中实现无限滚动GridView的最佳实践是什么?Flutter 在Flatter中实现无限卷轴GridView的最佳实践?,flutter,Flutter,我想创建一个GridView,显示将按偏移量从服务器获取的项目。我在GridView中只加载10个项目,当用户滚动到10个后,我将加载更多的10个项目。在Flatter中实现无限滚动GridView的最佳实践是什么?类AllOrdersPage扩展StatefulWidget{ class AllOrdersPage extends StatefulWidget { @override _AllOrdersPageState createState() => _AllOrdersP
类AllOrdersPage扩展StatefulWidget{
class AllOrdersPage extends StatefulWidget {
@override
_AllOrdersPageState createState() => _AllOrdersPageState();
}
class _AllOrdersPageState extends State<AllOrdersPage> {
List<OrderDatum> ordersList;
ScrollController _scrollController = ScrollController();
int skip = 0;
bool shouldLoadMore = true;
Future<OrdersResponse> future;
@override
void initState() {
super.initState();
ordersList = [];
future = getAllOrders(skip); //load data for first time
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) { //Check whether user scrolled to last position
if (shouldLoadMore) {
setState(() {
skip += ordersList.length;
future = getAllOrders(skip); //load more data
});
}
}
});
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return FutureBuilder<OrdersResponse>(
future: future,
builder: (context, snapshot) {
if (snapshot.hasError)
return ErrorText('${snapshot.error.toString()}');
if (snapshot.hasData) {
skip = snapshot.data.skip;
if (snapshot.data.limit + snapshot.data.skip >=
snapshot.data.total) {
shouldLoadMore = false;
}
snapshot.data.data.forEach((element) {
if (!ordersList.contains(element)) ordersList.add(element);
});
if (skip == 0 && ordersList.isEmpty) {
return ErrorText('No orders.');
}
return Scrollbar(
controller: _scrollController,
isAlwaysShown: true,
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 8,
childAspectRatio: 2.5,
mainAxisSpacing: 8),
controller: _scrollController,
padding: const EdgeInsets.all(8),
itemBuilder: (BuildContext context, int index) {
if (index == ordersList.length) {
return shouldLoadMore
? Center(child: CircularProgressIndicator())
: Container();
}
return Container(
width: MediaQuery.of(context).size.width,
child: OrderCard(ordersList[index]));
},
itemCount: ordersList.length + 1,
),
);
}
return Loader();
});
}
}
@凌驾
_AllOrdersPageState createState()=>\u AllOrdersPageState();
}
类_AllOrdersPageState扩展状态{
列出订单列表;
ScrollController_ScrollController=ScrollController();
int skip=0;
bool shouldLoadMore=true;
未来;
@凌驾
void initState(){
super.initState();
订单列表=[];
future=getAllOrders(跳过);//首次加载数据
_scrollController.addListener((){
如果(_scrollController.position.pixels==
_scrollController.position.maxScrollExtent){//检查用户是否滚动到最后一个位置
如果(应该加载更多){
设置状态(){
跳过+=订单列表长度;
future=getAllOrders(跳过);//加载更多数据
});
}
}
});
}
@凌驾
无效处置(){
_scrollController.dispose();
super.dispose();
}
@凌驾
小部件构建(构建上下文){
回归未来建设者(
未来:未来,,
生成器:(上下文,快照){
if(snapshot.hasError)
返回ErrorText(“${snapshot.error.toString()}”);
if(snapshot.hasData){
skip=snapshot.data.skip;
如果(snapshot.data.limit+snapshot.data.skip>=
snapshot.data.total){
shouldLoadMore=false;
}
snapshot.data.data.forEach((元素){
如果(!ordersList.contains(element))ordersList.add(element);
});
if(skip==0&&ordersList.isEmpty){
返回ErrorText(“无订单”);
}
返回滚动条(
控制器:\ u滚动控制器,
伊莎韦肖恩:没错,
子项:GridView.builder(
gridDelegate:SliverGridDelegateWithFixedCrossAxisCount(
交叉轴计数:2,
横轴间距:8,
儿童方面:2.5,
主轴间距:8),
控制器:\ u滚动控制器,
填充:常量边集。全部(8),
itemBuilder:(构建上下文,int索引){
if(index==ordersList.length){
返回时应加载更多
?中心(子项:循环压缩机指示器())
:容器();
}
返回容器(
宽度:MediaQuery.of(context).size.width,
子项:订单卡(订单列表[索引]);
},
itemCount:ordersList.length+1,
),
);
}
返回加载器();
});
}
}
谢谢类AllOrdersPage扩展StatefulWidget{
@凌驾
_AllOrdersPageState createState()=>\u AllOrdersPageState();
}
类_AllOrdersPageState扩展状态{
列出订单列表;
ScrollController_ScrollController=ScrollController();
int skip=0;
bool shouldLoadMore=true;
未来;
@凌驾
void initState(){
super.initState();
订单列表=[];
future=getAllOrders(跳过);//首次加载数据
_scrollController.addListener((){
如果(_scrollController.position.pixels==
_scrollController.position.maxScrollExtent){//检查用户是否滚动到最后一个位置
如果(应该加载更多){
设置状态(){
跳过+=订单列表长度;
future=getAllOrders(跳过);//加载更多数据
});
}
}
});
}
@凌驾
无效处置(){
_scrollController.dispose();
super.dispose();
}
@凌驾
小部件构建(构建上下文){
回归未来建设者(
未来:未来,,
生成器:(上下文,快照){
if(snapshot.hasError)
返回ErrorText(“${snapshot.error.toString()}”);
if(snapshot.hasData){
skip=snapshot.data.skip;
如果(snapshot.data.limit+snapshot.data.skip>=
snapshot.data.total){
shouldLoadMore=false;
}
snapshot.data.data.forEach((元素){
如果(!ordersList.contains(element))ordersList.add(element);
});
if(skip==0&&ordersList.isEmpty){
返回ErrorText(“无订单”);
}
返回滚动条(
控制器:\ u滚动控制器,
伊莎韦肖恩:没错,
子项:GridView.builder(
gridDelegate:SliverGridDelegateWithFixedCrossAxisCount(
交叉轴计数:2,
横轴间距:8,
儿童方面:2.5,
主轴间距:8),
控制器:\ u滚动控制器,
填充:常量边集。全部(8),
itemBuilder:(构建上下文,int索引){
if(index==ordersList.length){
返回时应加载更多
?中心(子项:循环压缩机指示器())
:容器();
}
返回容器(
宽度:MediaQuery.of(context).size.width,
子项:订单卡(订单列表[索引]);
},
itemCount:ordersList.length+1,
),
);
}
返回加载器();
});
}
}
谢谢您需要添加
滚动控制器
,以便在列表视图
和网格视图
的底部进行滚动检测。如你所需
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class HomeScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return HomeState();
}
}
class HomeState extends State<HomeScreen> {
List dataList = new List<int>();
bool isLoading = false;
int pageCount = 1;
ScrollController _scrollController;
@override
void initState() {
super.initState();
////LOADING FIRST DATA
addItemIntoLisT(1);
_scrollController = new ScrollController(initialScrollOffset: 5.0)
..addListener(_scrollListener);
}
Widget build(BuildContext context) {
return MaterialApp(
title: 'Gridview',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.red,
accentColor: Color(0xFFFEF9EB),
),
home: Scaffold(
appBar: new AppBar(),
body: GridView.count(
controller: _scrollController,
scrollDirection: Axis.vertical,
crossAxisCount: 2,
mainAxisSpacing: 10.0,
physics: const AlwaysScrollableScrollPhysics(),
children: dataList.map((value) {
return Container(
alignment: Alignment.center,
height: MediaQuery.of(context).size.height * 0.2,
margin: EdgeInsets.only(left: 10.0, right: 10.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
),
child: Text("Item ${value}"),
);
}).toList(),
)));
}
//// ADDING THE SCROLL LISTINER
_scrollListener() {
if (_scrollController.offset >=
_scrollController.position.maxScrollExtent &&
!_scrollController.position.outOfRange) {
setState(() {
print("comes to bottom $isLoading");
isLoading = true;
if (isLoading) {
print("RUNNING LOAD MORE");
pageCount = pageCount + 1;
addItemIntoLisT(pageCount);
}
});
}
}
////ADDING DATA INTO ARRAYLIST
void addItemIntoLisT(var pageCount) {
for (int i = (pageCount * 10) - 10; i < pageCount * 10; i++) {
dataList.add(i);
isLoading = false;
}
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
}