Как показать индикатор загрузки при прокрутке до конца списка в флаттере - PullRequest
0 голосов
/ 12 марта 2020

Я загружаю данные с сервера в будущем и отображаю их в виде списка с помощью построителя списка и добавляю новый список, когда мы прокручиваем его до конца списка, но я не могу показать индикатор загрузки, пока новый список элементов загружаются. Я приложил свой код ниже. Я попробовал пакет loadmore , но не повезло.

Main.dart

class Herbs extends StatefulWidget {
  final String title;
  Herbs(this.title);

  @override
  _HerbsState createState() => new _HerbsState();
}

class _HerbsState extends State<Herbs> {
  ScrollController _scrollController = new ScrollController();
  var data;
  var cname;
  String gcm = '';
  List pages = [];

  @override
  void initState() {
    super.initState();
    fetchPost(gcm);
    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        print('Page reached end of page');
        setState(() {
          Text('Loading');
        });
        fetchPost(gcm);
      }
    });
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    cname = widget.title;
    var hgt = MediaQuery.of(context).size.width * 0.65;
    var wid = MediaQuery.of(context).size.height * 0.58;
    return new Scaffold(
      appBar: AppBar(
        title: Align(
          alignment: Alignment(-0.2, 0.3),
          child: Text(
            cname,
          ),
        ),
      ),
      body: Center(
        child: FutureBuilder<Herbslist>(
          future: fetchPost(gcm),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return Scrollbar(
                child: ListView.builder(
                  controller: _scrollController,
                  shrinkWrap: true,
                  itemCount: pages == null ? 0 : pages.length,
                  itemBuilder: (BuildContext context, int index) {
                    gcm = snapshot.data.herbslistContinue.gcmcontinue;
                    var img = pages[index].thumbnail.source;
                    return GestureDetector(
                        onTap: () {
                          Navigator.push(
                              context,
                              MaterialPageRoute(
                                builder: (context) => Detailpage(
                                  pages[index].title,
                                ),
                              ));
                        },
                        child: Card(
                            child: Column(
                          children: <Widget>[
                            CachedNetworkImage(
                              placeholder: (context, url) => Image.asset(
                                'images/image.png',
                                height: hgt,
                                width: wid,
                                fit: BoxFit.fill,
                              ),
                              imageUrl: img,
                              height: hgt,
                              width: wid,
                              fit: BoxFit.fill,
                            ),
                            ListTile(
                              title: Text(pages[index].title, style: TextStyle(fontWeight: FontWeight.bold),),
                            )
                          ],
                        )));
                  },
                ),
              );
            } else {
              return Center(
                child: CircularProgressIndicator(),
              );
            }
          },
        ),
      ),
    );
  }

  Future<Herbslist> fetchPost(gcm) async {
    String url =
        'https://eample.org/api.php?action=query&gcmtitle=Category:$cname&pilimit=max&prop=pageimages&pithumbsize=200&generator=categorymembers&format=json&gcmcontinue=$gcm';
    final response = await http.get(url);
    print(url);
    if (response.statusCode == 200) {
      data = Herbslist.fromJson(json.decode(response.body));
      pages.addAll(data.query.pages.values);
      return data;
    } else {
      throw (e) {
        print("Exception thrown: $e");
        Exception(e);
      };
    }
  }
}

Ответы [ 2 ]

0 голосов
/ 17 марта 2020

Вот способ, который работал для меня (случаи могут отличаться для других)

class _HerbsState extends State<Herbs> {
  bool _loading = false;

@override
  void initState() {
    super.initState();
    fetchPost(gcm);
    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        print('Page reached end of page');
        setState(() {});
        fetchPost(gcm);
      }
    });
  }

Widget build(BuildContext context){
return Scaffold(
         ListView.builder(
           controller: _scrollController,
           shrinkWrap: true,
           itemCount: pages == null ? 0 : pages.length+1,  //add +1 here
           itemBuilder: (BuildContext context, int index) {
           if(index == pages.length){
                _loading=true;  // declare the boolean and return loading indicator
                return Center(
                     child: Container(
                         child: SpinKitThreeBounce(
                                  color: Colors.green,
                                  size: 30,
                                 ),
                            ));
                          }
)
}
}
0 голосов
/ 12 марта 2020

Вы можете сделать это, используя виджет Stack и перекрывая CircularProgressIndicator с ListView. Проверьте приведенный ниже код для упрощенного примера:

class LoadingOnScroll60619794 extends StatefulWidget {
  @override
  _LoadingOnScroll60619794State createState() => _LoadingOnScroll60619794State();
}

class _LoadingOnScroll60619794State extends State<LoadingOnScroll60619794> {
  bool _loading = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.refresh),
            onPressed: runLoading
          ),
        ],
      ),
      body: Stack(
        children: <Widget>[
          ListView(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text('item 1'),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text('item 1'),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text('item 1'),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text('item 1'),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text('item 1'),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text('item 1'),
              ),
            ],
          ),
          _loading
            ? Center(
              child: CircularProgressIndicator(),
            )
            : SizedBox(width: 0, height: 0,)
        ],
      ),
    );
  }

  void runLoading(){
    setState(() {
      _loading = true;
    });
    Timer(Duration(milliseconds: 1500), (){
      setState(() {
        _loading = false;
      });
    });
  }
}

Если вы изменяете свой код, изменяя переменную _loading, когда вы выбираете данные, вы получите тот же эффект. Как в примере ниже:

Future<Herbslist> fetchPost(gcm) async {
  setState(() {
    _loading = true;
  });
  String url =
    'https://eample.org/api.php?action=query&gcmtitle=Category:$cname&pilimit=max&prop=pageimages&pithumbsize=200&generator=categorymembers&format=json&gcmcontinue=$gcm';
  final response = await http.get(url);
  print(url);
  if (response.statusCode == 200) {
    data = Herbslist.fromJson(json.decode(response.body));
    pages.addAll(data.query.pages.values);
    setState(() {
      _loading = false;
    });
    return data;
  } else {
    setState(() {
      _loading = false;
    });
    throw (e) {
      print("Exception thrown: $e");
      Exception(e);
    };
  }
}
...