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 simulatehttprequest
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 takeListViewSlide to the end of the triggerfakeRequestTo load more data, the simplest way to do this is to useScrollControllerTo finish,ScrollControllerWill listen for scroll events whenListViewAt 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 flagisPerformingRequestOnly if it isfalseIs 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 useCircularProgressIndicatorTo 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 ourListViewTo the middle, pay attention here to giveitemCountMake 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 dataListViewMove 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