0

CircularProgressIndicator如果正在加载对另一部分广告的请求,我希望在列表末尾。我想它需要在onNotification方法下完成,因为我在那里提出请求并且可能在此方法完成时禁用它?

代码类似于https://codinginfinite.com/flutter-future-builder-pagination/

你能告诉我我该怎么做吗?

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:..../ui/pages/home/page/AdvertisementCard.dart';
import 'package:.../ui/pages/home/page/model/AdvertisementList.dart';

import '../../SizedBox.dart';
import 'AdvertisementProdRepository.dart';
import 'BottomAppBar.dart';
import 'FAB.dart';
import 'model/AdvertisementList.dart';

class HomePage extends StatefulWidget {
  final String jwt;

  const HomePage(this.jwt);

  @override
  _HomePage createState() => _HomePage();

  factory HomePage.fromBase64(String jwt) => HomePage(jwt);
}

class _HomePage extends State<HomePage> {
  late final String jwt;
  late Future<AdvertisementList> _listOfItems;
  final searchTextController = TextEditingController();

  @override
  void initState() {
    super.initState();
    jwt = widget.jwt;
    _listOfItems = AdvertisementProdRepository.fetchAdvertisements(1);
  }

  @override
  Widget build(BuildContext context) => Scaffold(
        body: Scaffold(
          backgroundColor: const Color(0xFEF9F9FC),
          floatingActionButtonLocation:
              FloatingActionButtonLocation.centerDocked,
          floatingActionButton: buildFAB(),
          bottomNavigationBar: BuildBottomAppBar(),
          body: Container(
            padding: EdgeInsets.only(left: 25.0, right: 25, top: 25),
            width: MediaQuery.of(context).size.width,
            height: MediaQuery.of(context).size.height,
            child: Column(
              children: [
                TextFormField(
                  controller: searchTextController,
                  decoration: InputDecoration(
                      prefixIcon: Icon(Icons.search),
                      border: OutlineInputBorder(),
                      hintText: 'Szukaj',
                      fillColor: Color(0xffeeeeee),
                      filled: true),
                ),
                buildSizedBox(20.0),
                Padding(
                  padding: const EdgeInsets.only(left: 4),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.start,
                    children: [
                      Text(
                        'Najnowsze ogłoszenia',
                        style: TextStyle(
                            fontSize: 20, fontWeight: FontWeight.bold),
                        textAlign: TextAlign.left,
                      ),
                    ],
                  ),
                ),
                buildSizedBox(10.0),
                FutureBuilder<AdvertisementList>(
                  future: _listOfItems,
                  builder: (context, snapshot) {
                    if (!snapshot.hasData) {
                      return Center(child: CircularProgressIndicator());
                    } else {
                      return Expanded(
                        child:
                            AdvertisementTile(advertisements: snapshot.data!),
                      );
                    }
                  },
                ),
              ],
            ),
          ),
        ),
      );
}

class AdvertisementTile extends StatefulWidget {
  final AdvertisementList advertisements;

  AdvertisementTile({Key? key, required this.advertisements}) : super(key: key);

  @override
  State<StatefulWidget> createState() => AdvertisementTileState();
}

class AdvertisementTileState extends State<AdvertisementTile> {
  AdvertisementLoadMoreStatus loadMoreStatus =
      AdvertisementLoadMoreStatus.STABLE;
  final ScrollController scrollController = new ScrollController();
  late List<Advertisement> advertisements;
  late int currentPageNumber;
  bool _loading = false;


  @override
  void initState() {
    advertisements = widget.advertisements.items;
    currentPageNumber = widget.advertisements.pageNumber;
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    return NotificationListener(
      onNotification: onNotification,
      child: Padding(
        padding: const EdgeInsets.only(bottom: 28.0),
        child: new ListView.separated(
          padding: EdgeInsets.zero,
          scrollDirection: Axis.vertical,
          controller: scrollController,
          itemCount: advertisements.length,
          physics: const AlwaysScrollableScrollPhysics(),
          itemBuilder: (_, index) {
            return AdvertisementCard(data: advertisements[index]);
          },
          separatorBuilder: (BuildContext context, int index) {
            return SizedBox(
              height: 10,
            );
          },
        ),
      ),
    );
  }

  bool onNotification(ScrollNotification notification) {
    if (notification is ScrollUpdateNotification) {
      if (scrollController.position.maxScrollExtent > scrollController.offset &&
          scrollController.position.maxScrollExtent - scrollController.offset <=
              50) {
        if (loadMoreStatus == AdvertisementLoadMoreStatus.STABLE) {
          loadMoreStatus = AdvertisementLoadMoreStatus.LOADING;
          AdvertisementProdRepository.fetchAdvertisements(currentPageNumber + 1)
              .then((advertisementObject) {
            currentPageNumber = advertisementObject.pageNumber;
            loadMoreStatus = AdvertisementLoadMoreStatus.STABLE;
            setState(() => advertisements.addAll(advertisementObject.items));
          });
        }
      }
    }
    return true;
  }
}

enum AdvertisementLoadMoreStatus { LOADING, STABLE }
4

1 回答 1

0

您可以获取一个变量并将其设置为 false。

loadingNewData = false;

然后,您可以用一列包装您的列表视图。在 listview 之后,您可以添加条件代码。

Column(children: [
Listview(),
if (loadingNewData) CircularProgressIndicator() 
])

现在,无论何时到达列表视图的末尾,您都可以将 loadingNewData 设置为 true,并且在加载数据后,您可以将其设置回 false。

于 2021-08-05T04:59:36.600 回答