The drop-down refresh
Very simple, use RefreshIndicator component directly, onRefresh is the method to retrieve data
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.all(2.0),
child: RefreshIndicator(
onRefresh: _refresh,
backgroundColor: Colors.blue,
child: ListView.builder(
itemCount: _dataList.length,
itemBuilder: (context, index) {
returnListItem(_dataList[index]); },),),),); } Future<Null> _refresh() async {
_dataList.clear();
await _loadFirstListData();
return;
}
Copy the code
Pull up to load more
So let’s look at the effect
- Let’s start with the first ten numbers
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<int> items = List.generate(10, (i) => i);
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("Infinite ListView"),
),
body: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(title: new Text("Number $index")); },),); }}Copy the code
- Now we’re going to write a method that loads more data to simulate
http
request
Future<List<int>> fakeRequest(int from, int to) async {
return Future.delayed(Duration(seconds: 2), () {
return List.generate(to - from, (i) => i + from);
});
}
Copy the code
- Now we want the user to take
ListView
Slide to the end of the triggerfakeRequest
To load more data, the simplest way to do this is to useScrollController
To finish,ScrollController
Will listen for scroll events whenListView
At the end of the scroll he makes a request. One other thing to note here is that in order to avoid repeated requests to the server, we need to make a flagisPerformingRequest
Only if it isfalse
Is allowed to make requests to the background.
class _MyHomePageState extends State<MyHomePage> {
List<int> items = List.generate(10, (i) => i);
ScrollController _scrollController = new ScrollController();
bool isPerformingRequest = false;
@override
void initState() {
super.initState();
_scrollController.addListener(() {
if(_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { _getMoreData(); }}); }@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
_getMoreData() async {
if(! isPerformingRequest) { setState(() => isPerformingRequest =true);
List<int> newEntries = await fakeRequest(items.length, items.length + 10);
setState(() {
items.addAll(newEntries);
isPerformingRequest = false; }); }}@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("Infinite ListView"),
),
body: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(title: new Text("Number $index")); }, controller: _scrollController, ), ); }}Copy the code
If you run the program now you will see that our list is ready to load dynamically, but it is far from our goal, we need to add some flag action to let the user know that the request has started.
- And then we’re going to use
CircularProgressIndicator
To complete the load flag
Widget _buildProgressIndicator() {
return new Padding(
padding: const EdgeInsets.all(8.0),
child: new Center(
child: new Opacity(
opacity: isPerformingRequest ? 1.0 : 0.0,
child: new CircularProgressIndicator(),
),
),
);
}
Copy the code
- Now let’s put this load flag in our
ListView
To the middle, pay attention here to giveitemCount
Make room for our_buildProgressIndicator
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("Infinite ListView"),
),
body: ListView.builder(
itemCount: items.length + 1,
itemBuilder: (context, index) {
if (index == items.length) {
return _buildProgressIndicator();
} else {
return ListTile(title: new Text("Number $index"));
}
},
controller: _scrollController,
),
);
}
Copy the code
- We’re almost done loading more data from here, but to make it more beautiful we’re going to have to deal with actions when we don’t get more data, so here we’re going to add an animation when we don’t get more data
ListView
Move down to overwrite the flag that is loading more data
_getMoreData() async {
if(! isPerformingRequest) { setState(() => isPerformingRequest =true);
List<int> newEntries = await fakeRequest(items.length, items.length); //returns empty list
if (newEntries.isEmpty) {
double edge = 50.0;
double offsetFromBottom = _scrollController.position.maxScrollExtent - _scrollController.position.pixels;
if (offsetFromBottom < edge) {
_scrollController.animateTo(
_scrollController.offset - (edge -offsetFromBottom),
duration: new Duration(milliseconds: 500),
curve: Curves.easeOut);
}
}
setState(() {
items.addAll(newEntries);
isPerformingRequest = false; }); }}Copy the code