Skip to content

Instantly share code, notes, and snippets.

@MarcinusX
Created April 16, 2018 19:47
Show Gist options
  • Select an option

  • Save MarcinusX/a6644d501dcf9b8953e8998be5cfc80c to your computer and use it in GitHub Desktop.

Select an option

Save MarcinusX/a6644d501dcf9b8953e8998be5cfc80c to your computer and use it in GitHub Desktop.

Revisions

  1. MarcinusX created this gist Apr 16, 2018.
    105 changes: 105 additions & 0 deletions infinite_listview.dart
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,105 @@
    import 'dart:async';

    import 'package:flutter/material.dart';

    void main() => runApp(new MyApp());

    class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new MaterialApp(
    theme: new ThemeData(primarySwatch: Colors.blue),
    home: new MyHomePage(),
    );
    }
    }

    class MyHomePage extends StatefulWidget {
    @override
    _MyHomePageState createState() => _MyHomePageState();
    }

    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); //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;
    });
    }
    }

    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(),
    ),
    ),
    );
    }

    @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,
    ),
    );
    }
    }

    /// from - inclusive, to - exclusive
    Future<List<int>> fakeRequest(int from, int to) async {
    return Future.delayed(Duration(seconds: 2), () {
    return List.generate(to - from, (i) => i + from);
    });
    }