Flutter下拉刷新与上拉加载插件easy_refresh的使用

发布于 1周前 作者 htzhanglong 来自 Flutter

Flutter下拉刷新与上拉加载插件easy_refresh的使用

flutter_easy_refresh

License Platform Flutter Pub

英文文档 | 中文文档

EasyRefresh正如其名,可以在Flutter应用程序中轻松实现下拉刷新和上拉加载功能。它几乎支持所有可滚动的小部件,功能类似于Android的SmartRefreshLayout,并吸收了许多第三方库的优点。EasyRefresh集成了多种风格的Header和Footer,但并不局限于此,你可以轻松自定义它们。利用Flutter强大的动画功能,即使是一个简单的控件也能完成复杂的操作。EasyRefresh的目标是为Flutter创建一个强大、稳定且成熟的下拉刷新框架。

在线演示

APK下载

API参考

Features

  • 支持所有可滚动的小部件
  • 滚动物理范围,精确匹配可滚动小部件
  • 集成多种炫酷的Header和Footer
  • 支持自定义样式以实现各种动画效果
  • 支持下拉刷新、上拉加载(可以通过控制器触发和完成)
  • 支持指示器位置设置,结合监听器可以放置在任意位置
  • 支持页面启动时刷新,并自定义视图
  • 支持安全区域,避免遮挡
  • 自定义滚动参数,允许列表具有不同的滚动反馈和惯性

示例代码

以下是一个完整的示例demo,展示了如何使用EasyRefresh实现下拉刷新和上拉加载:

import 'package:flutter/material.dart';
import 'package:easy_refresh/easy_refresh.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'EasyRefresh',
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _count = 10;
  late EasyRefreshController _controller;

  @override
  void initState() {
    super.initState();
    _controller = EasyRefreshController(
      controlFinishRefresh: true,
      controlFinishLoad: true,
    );
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('EasyRefresh'),
      ),
      body: EasyRefresh(
        controller: _controller,
        header: const ClassicHeader(),
        footer: const ClassicFooter(),
        onRefresh: () async {
          await Future.delayed(const Duration(seconds: 2));
          if (!mounted) {
            return;
          }
          setState(() {
            _count = 10;
          });
          _controller.finishRefresh();
          _controller.resetFooter();
        },
        onLoad: () async {
          await Future.delayed(const Duration(seconds: 2));
          if (!mounted) {
            return;
          }
          setState(() {
            _count += 5;
          });
          _controller.finishLoad(
              _count >= 20 ? IndicatorResult.noMore : IndicatorResult.success);
        },
        child: ListView.builder(
          itemBuilder: (context, index) {
            return Card(
              child: Container(
                alignment: Alignment.center,
                height: 80,
                child: Text('${index + 1}'),
              ),
            );
          },
          itemCount: _count,
        ),
      ),
    );
  }
}

使用说明

1. 默认构造函数

在子作用域中,所有滚动组件将共享一个物理属性。如果有嵌套滚动,使用EasyRefresh.builder或通过ScrollConfiguration设置作用域。

EasyRefresh(
  onRefresh: () async {
    // 刷新逻辑
  },
  onLoad: () async {
    // 加载逻辑
  },
  child: ListView(),
);

2. Builder构造函数

EasyRefresh.builder(
  onRefresh: () async {
    // 刷新逻辑
    return IndicatorResult.success; 
  },
  onLoad: () async {
    // 加载逻辑
  },
  childBuilder: (context, physics) {
    return ListView(
      physics: physics,
    );
  },
);

3. 指示器位置

EasyRefresh(
  header: Header(
    position: IndicatorPosition.locator,
  ),
  footer: Footer(
    position: IndicatorPosition.locator,
  ),
  onRefresh: () async {
    // 刷新逻辑
  },
  onLoad: () async {
    // 加载逻辑
    return IndicatorResult.noMore;
  },
  child: CustomScrollView(
    slivers: [
      SliverAppBar(),
      const HeaderLocator.sliver(),
      // 其他Sliver组件
      const FooterLocator.sliver(),
    ],
  ),
);

4. 使用控制器

EasyRefreshController _controller = EasyRefreshController(
  controlFinishRefresh: true,
  controlFinishLoad: true,
);

// ...

EasyRefresh(
  controller: _controller,
  onRefresh: () async {
    // 刷新逻辑
    _controller.finishRefresh();
    _controller.resetFooter();
  },
  onLoad: () async {
    // 加载逻辑
    _controller.finishLoad(IndicatorResult.noMore);
  },
  // ...
);

// 调用刷新或加载
_controller.callRefresh();
_controller.callLoad();

5. 指定Header和Footer

EasyRefresh(
  header: MaterialHeader(),
  footer: MaterialFooter(),
  child: ListView(),
  // ...
);

// 全局设置
EasyRefresh.defaultHeaderBuilder = () => ClassicHeader();
EasyRefresh.defaultFooterBuilder = () => ClassicFooter();

6. NestedScrollView

EasyRefresh.builder(
  header: MaterialHeader(
    clamping: true,
  ),
  onRefresh: () async {
    // 刷新逻辑
  },
  onLoad: () async {
    // 加载逻辑
  },
  childBuilder: (context, physics) {
    return NestedScrollView(
      physics: physics,
      body: ListView(
        physics: physics,
      );
    );
  },
);

// 或者
EasyRefresh.builder(
  header: MaterialHeader(
    clamping: true,
    position: IndicatorPosition.locator,
  ),
  onRefresh: () async {
    // 刷新逻辑
  },
  onLoad: () async {
    // 加载逻辑
  },
  childBuilder: (context, physics) {
    return NestedScrollView(
      physics: physics,
      headerSliverBuilder: (context, innerBoxIsScrolled) {
        return [
          const HeaderLocator.sliver(clearExtent: false),
          // 其他Sliver组件
        ];
      },
      body: ListView(
        physics: physics,
      );
    );
  },
);

参与贡献

如果你有好的建议和改进,请随时贡献你的代码。如果你有一些非常酷的样式,分享给大家就更棒了!

感谢所有已经为此项目做出贡献的人!

QQ群 - 554981921

这个群不仅解决EasyRefresh的问题,任何Flutter相关的问题都可以讨论。只要时间允许,群主会帮助你一起解决问题。

致谢

许可证

MIT License

Copyright © 2018 xuelongqy

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


更多关于Flutter下拉刷新与上拉加载插件easy_refresh的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter下拉刷新与上拉加载插件easy_refresh的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter中使用easy_refresh插件来实现下拉刷新和上拉加载功能的示例代码。

首先,确保你已经在pubspec.yaml文件中添加了easy_refresh依赖:

dependencies:
  flutter:
    sdk: flutter
  easy_refresh: ^2.2.10  # 请根据需要检查最新版本号

然后运行flutter pub get来安装依赖。

接下来,创建一个Flutter应用,并在其中使用EasyRefresh组件。以下是一个完整的示例:

import 'package:flutter/material.dart';
import 'package:easy_refresh/easy_refresh.dart';

void main() {
  runApp(MyApp());
}

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

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

class _MyHomePageState extends State<MyHomePage> {
  List<String> dataList = List.generate(20, (index) => "Item ${index + 1}");
  bool isLoading = false;
  bool hasMore = true;

  void _onRefresh() async {
    // 模拟网络请求延迟
    await Future.delayed(Duration(seconds: 2));
    setState(() {
      dataList = List.generate(20, (index) => "Refreshed Item ${index + 1}");
      isLoading = false;
    });
  }

  void _onLoad() async {
    // 模拟网络请求延迟
    if (hasMore) {
      await Future.delayed(Duration(seconds: 2));
      setState(() {
        dataList.addAll(List.generate(10, (index) => "Loaded Item ${dataList.length + index + 1}"));
        if (dataList.length >= 50) {
          hasMore = false; // 假设最多加载到50条数据
        }
        isLoading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('EasyRefresh Demo'),
      ),
      body: EasyRefresh(
        onRefresh: _onRefresh,
        onLoad: _onLoad,
        isFirstRefresh: true,
        isFirstLoad: true,
        loadingText: "Loading...",
        noMoreText: "No More Data",
        refreshFooter: ClassicsFooter(),
        refreshHeader: ClassicsHeader(),
        child: ListView.builder(
          itemCount: dataList.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(dataList[index]),
            );
          },
        ),
      ),
    );
  }
}

在这个示例中:

  1. EasyRefresh组件用于包裹ListView,它提供了下拉刷新和上拉加载的功能。
  2. onRefreshonLoad回调分别处理下拉刷新和上拉加载的逻辑。
  3. ClassicsFooterClassicsHeadereasy_refresh提供的默认刷新和加载指示器,你可以根据需要自定义它们。
  4. ListView.builder用于动态生成列表项。

这个示例演示了如何使用easy_refresh插件来实现下拉刷新和上拉加载功能,并展示了如何管理加载状态和数据。

回到顶部