Flutter 实现下拉刷新和自动加载更多

2024-07-17  本文已影响0人  有没有口罩给我一个

Flutter 简单封装http网络框架
Flutter 实现下拉刷新和自动加载更多
Flutter Banner封装
Flutter使用官方CustomScrollView实现复杂页面下拉刷新和加载更多
Flutter之Router和Navigator实现页面跳转
Flutter的基本应用

Flutter中ListView 是不具有下拉刷新和加载更多的功能的,当然Flutter 提供了RefreshIndicator实现了下拉刷新,但是这些组件仍然是需要在开发中再次封装便于维护。

@immutable
class SmartRefreshListView extends StatefulWidget {
final List<dynamic> data;
final Future<void> Function()? onRefresh;
final Future<void> Function()? onLoadMore;
final Widget Function(int index, dynamic item) itemBuilder;

/// 是否有下一页 ,由外部提供状态
final bool hasNextPage;

const SmartRefreshListView(
  {super.key,
  required this.data,
  required this.itemBuilder,
  this.hasNextPage = true,
  this.onRefresh,
  this.onLoadMore});

@override
State<SmartRefreshListView> createState() => _SmartRefreshListViewState();
}

class _SmartRefreshListViewState extends State<SmartRefreshListView> {
  bool _isRefreshing = false;
  bool _isLoading = false;
  final ScrollController _scrollController = ScrollController();

  @override
void initState() {
super.initState();
_scrollController.addListener(() {
  if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent &&
      widget.hasNextPage) {
    _load();
  }
});
}

@override
Widget build(BuildContext context) {
return RefreshIndicator(
  onRefresh: _onRefresh,
  child: ListView.builder(
    controller: _scrollController,
    itemCount: widget.data.length + 1,
    itemBuilder: (context, index) {
      if (index == widget.data.length) {
        return _footer();
      }
      return widget.itemBuilder.call(index, widget.data[index]);
    },
  ),
);
}

/// 下拉刷新 此方法结束,刷新完成
Future<void> _onRefresh() async {
if (_isLoading && _isRefreshing) {
  return;
}
_isRefreshing = true;
await widget.onRefresh?.call();
_isRefreshing = false;
return;
}

/// 加载更多
Future<void> _load() async {
if (_isLoading && _isRefreshing) {
  return;
}
_isLoading = true;
await widget.onLoadMore?.call();
_isLoading = false;
return;
}

_footer() {
if (!widget.hasNextPage) {
  return Container(
    padding: const EdgeInsets.only(top: 20, bottom: 20),
    decoration: const BoxDecoration(color: Colors.white),
    child: const Center(
      child: Text("没有更多数据",
          style: TextStyle(fontSize: 12, color: Colors.black)),
    ),
  );
}

return const Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    SizedBox(
        height: 10,
        width: 10,
        child: CircularProgressIndicator(
          strokeWidth: 2,
        )),
    SizedBox(width: 10),
    Text("加载更多", style: TextStyle(fontSize: 16, color: Colors.black))
  ],
);
}
}

因为项目中的代码不能直接拿来使用,所以我重新简单的写了一遍,有很多功能没有暴露出来,代码很简单,组件内部维护刷新和加载状态,仅提供hasNextPage 是否有下一页供外部操作。

使用:

@override
  Widget build(BuildContext context) {
return MaterialApp(
  title: "垂直列表",
  theme: ThemeData(
    colorScheme: ColorScheme.fromSeed(seedColor: Colors.white),
    useMaterial3: false,
  ),
  home: Scaffold(
    appBar: AppBar(
        title: const Text(
          "垂直列表",
          style: TextStyle(color: Colors.black),
        ),
        backgroundColor: Colors.white),
    body: SmartRefreshListView(
      data: _list,
      hasNextPage: hasNextPage,
      onRefresh: () async {
        print("onRefresh start");
        await Future.delayed(const Duration(seconds: 3));
        setState(() {
          _list = List.generate(20, (idnex) {
            return "onRefresh 第$idnex个";
          });
          hasNextPage = !hasNextPage;
        });
        print("onRefresh end");
      },
      onLoadMore: () async {
        print("onLoadMore");
        await Future.delayed(const Duration(seconds: 3));
        setState(() {
          var list = List.generate(10, (index) => "loading:$index");
          _list.addAll(list);
          hasNextPage = !hasNextPage;
        });
        print("onLoadMore end");
      },
      itemBuilder: (index, item) {
        return ListTile(
          leading: const Icon(Icons.people),
          title: Text(item),
        );
      },
    ),
  ),
);
}

为了演示方便我使用 Future.delayed做了延时,真正项目中这里就是网络请求或者其他IO操作等。

上一篇 下一篇

猜你喜欢

热点阅读