在我的程序中,我尝试使用一个AnimatedBuilder小部件沿着无限滚动分页:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class Home extends StatefulWidget {
Home({Key? key}) : super(key: key);
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
final ScrollController _scrollController = ScrollController();
// The item list where the data is stored.
List<String> items = [];
// Flags used to check the loading status.
bool loading = false, allLoaded = false;
// Function that loads data in the item list.
mockFetch() async {
// No more data to load.
if (allLoaded) {
return;
}
// Set the loading flag to true to prevent this function to be called several times.
setState(() {
loading = true;
});
// Simulates the delay that might occurs during an API call.
await Future.delayed(Duration(milliseconds: 500));
// If the item list is higher or equal to 60, an empty array is returned to simulate
// the end of the data stream. If not, 20 more items are generated.
List<String> newData = items.length >= 60 ? [] : List.generate(20, (index) => "List Item ${index + items.length}");
// Add the new data to the item list.
if (newData.isNotEmpty) {
items.addAll(newData);
}
// Reset the flags.
setState(() {
loading = false;
// Returns false if the array is empty.
allLoaded = newData.isEmpty;
});
}
@override
void initState() {
super.initState();
// Call the mockFetch() function when the state of MyHomePage is initialized for the first time.
mockFetch();
// Set a listener.
_scrollController.addListener(() {
if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent && !loading) {
mockFetch();
}
});
}
@override
void dispose() {
super.dispose();
_scrollController.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepOrange,
title: Text("Home Page"),
),
body: LayoutBuilder(builder: (context, constraints) {
if (items.isNotEmpty) {
return Stack(
// Dispay the data.
children: [
ListView.separated(
// Assign the scroll controller to the ListView.
controller: _scrollController,
itemBuilder: (context, index) {
// Display the newly loaded items.
if (index < items.length) {
return ListTile(
title: Text(items[index]),
);
}
// An extra item has been added to the index of the list meaning that
// all the items have been loaded.
else {
// Inform the user that there is no more data to load.
return Container(
width: constraints.maxWidth,
height: 50,
child: Center(
child: Text("Nothing more to load"),
),
);
}
},
// Add a separator between each item.
separatorBuilder: (context, index) {
return Divider(height: 1);
},
// Add an extra item to the length of the list when all of the items are loaded.
itemCount: items.length + (allLoaded ? 1 : 0)),
if (loading)...[
// Display a progress indicator at the bottom of the list whenever some data is loading.
Positioned(
left: 0,
bottom: 0,
child: Container(
width: constraints.maxWidth,
height: 80,
child: Center(
child: CircularProgressIndicator(),
),
)
)
]
],
);
}
else {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
}
}
),
bottomNavigationBar: AnimatedBuilder(
animation: _scrollController,
builder: (context, child) {
return AnimatedContainer(
duration: Duration(milliseconds: 300),
height: _scrollController.position.userScrollDirection == ScrollDirection.reverse ? 0: 100,
child: child,
);
},
child: BottomNavigationBar(
backgroundColor: Colors.amber[200],
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.child_friendly),
label: 'Child',
),
],
),
),
); // Scaffold
}
但我得到以下错误:
在构建AnimatedBuilder(animation:ScrollController#713ce(无客户端),脏,状态:_AnimatedState#02479):ScrollController未附加到任何滚动视图。'package:flutter/src/widgets/scroll_controller.dart ':Assert失败:第107行位置12:'_位置。不为空'
我读到过if(_scrollController.hasClients)
通常可以解决这个问题,但我不知道如何在我的程序中使用它。
有人能帮帮我吗
2条答案
按热度按时间wqnecbli1#
问题是您试图访问
_scrollController.position
,而_scrollController
没有附加到任何滚动视图。所以在访问_scrollController.position
之前,检查它是否是hasClients
,这应该意味着它被附加到滚动视图。就像这样:现在错误应该消失了。
ha5z0ras2#
问题是initState在呈现第一个帧(build())之前被调用。尝试将所有scrollcontroller的东西 Package 在postFrameCallback中:
在呈现第一个帧并将scrollcontroller附加到scrollview之后,将调用一次该函数