Flutter下拉刷新与加载更多插件pull_to_refresh_flutter3的使用

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

Flutter下拉刷新与加载更多插件pull_to_refresh_flutter3的使用

插件介绍

pull_to_refresh_flutter3 是一个为Flutter滚动组件提供下拉刷新和上拉加载功能的插件,支持Android和iOS平台。它几乎适配所有滚动组件(如GridView、ListView等),并提供了全局默认指示器和属性设置,以及一些常见的指示器样式。

功能特性

  • 支持上拉加载和下拉刷新。
  • 适用于几乎所有的滚动组件。
  • 提供全局默认指示器和属性设置。
  • 支持自定义弹簧动画、阻尼、速度等。
  • 水平和垂直刷新,支持反向ScrollView(四个方向)。
  • 提供多种刷新样式:Behind, Follow, UnFollow, Front。
  • 支持二级刷新,实现类似淘宝、微信的二级刷新效果。
  • 支持将指示器放置在其他位置,例如微信朋友圈刷新效果。

使用方法

安装依赖

pubspec.yaml 文件中添加以下依赖:

dependencies:
  pull_to_refresh_flutter3: ^2.0.2

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

导入包

在 Dart 文件中导入包:

import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart';

示例代码

下面是一个完整的示例代码,展示了如何使用 pull_to_refresh_flutter3 实现下拉刷新和上拉加载功能:

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

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

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

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

class _MyHomePageState extends State<MyHomePage> {
  List<String> items = ["1", "2", "3", "4", "5", "6", "7", "8"];
  final RefreshController _refreshController = RefreshController(initialRefresh: false);

  void _onRefresh() async {
    // 监控网络请求
    await Future.delayed(Duration(milliseconds: 1000));
    // 如果失败,使用 refreshFailed()
    _refreshController.refreshCompleted();
  }

  void _onLoading() async {
    // 监控网络请求
    await Future.delayed(Duration(milliseconds: 1000));
    // 如果失败,使用 loadFailed();如果没有数据返回,使用 LoadNodata()
    if (mounted) {
      setState(() {
        items.add((items.length + 1).toString());
      });
    }
    _refreshController.loadComplete();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Pull To Refresh Demo'),
      ),
      body: SmartRefresher(
        enablePullDown: true,
        enablePullUp: true,
        header: WaterDropHeader(),
        footer: CustomFooter(
          builder: (BuildContext context, LoadStatus? mode) {
            Widget body;
            if (mode == LoadStatus.idle) {
              body = Text("pull up load");
            } else if (mode == LoadStatus.loading) {
              body = CupertinoActivityIndicator();
            } else if (mode == LoadStatus.failed) {
              body = Text("Load Failed! Click retry!");
            } else if (mode == LoadStatus.canLoading) {
              body = Text("release to load more");
            } else {
              body = Text("No more Data");
            }
            return Container(
              height: 55.0,
              child: Center(child: body),
            );
          },
        ),
        controller: _refreshController,
        onRefresh: _onRefresh,
        onLoading: _onLoading,
        child: ListView.builder(
          itemBuilder: (context, index) {
            return Card(
              child: Center(
                child: Text(items[index]),
              ),
            );
          },
          itemExtent: 100.0,
          itemCount: items.length,
        ),
      ),
    );
  }

  @override
  void dispose() {
    // 释放资源
    _refreshController.dispose();
    super.dispose();
  }
}

全局配置

RefreshConfiguration 用于配置所有子树中的 SmartRefresher 组件,通常放在 MaterialApp 的根部,类似于 ScrollConfiguration 的用法。如果需要某个 SmartRefresher 的行为与其他不同,可以使用 RefreshConfiguration.copyAncestor() 复制祖先的属性并替换非空属性。

RefreshConfiguration(
  headerBuilder: () => WaterDropHeader(), // 配置默认头部指示器
  footerBuilder: () => ClassicFooter(),   // 配置默认底部指示器
  headerTriggerDistance: 80.0,            // 头部触发刷新的距离
  springDescription: SpringDescription(stiffness: 170, damping: 16, mass: 1.9), // 自定义弹簧动画
  maxOverScrollExtent: 100,               // 头部最大拖拽范围
  maxUnderScrollExtent: 0,                // 底部最大拖拽范围
  enableScrollWhenRefreshCompleted: true, // 刷新完成后是否允许滚动
  enableLoadingWhenFailed: true,          // 加载失败时是否允许继续加载
  hideFooterWhenNotFull: false,           // 视图不满一屏时不显示加载更多
  enableBallisticLoad: true,              // 是否允许惯性加载更多
  child: MaterialApp(
    // ...
  ),
);

国际化支持

从版本1.5.6开始,插件增加了国际化支持,可以在 MaterialAppCupertinoApp 中添加以下代码:

MaterialApp(
  localizationsDelegates: [
    RefreshLocalizations.delegate, // 这一行很重要
    GlobalWidgetsLocalizations.delegate,
    GlobalMaterialLocalizations.delegate,
  ],
  supportedLocales: [
    const Locale('en'),
    const Locale('zh'),
  ],
  localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) {
    return locale;
  },
  // ...
);

注意事项

  • SmartRefresher 的子组件必须是继承自 ScrollView 的组件(如 ListView, GridView, CustomScrollView),不能分离。
  • 不要将 SmartRefresher 的子组件嵌套在其他可滚动组件中,否则会导致刷新头和加载脚无法正常显示。

更多信息

希望这个帖子能帮助你更好地理解和使用 pull_to_refresh_flutter3 插件!如果有任何问题或建议,请随时提问。


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

1 回复

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


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

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

dependencies:
  flutter:
    sdk: flutter
  pull_to_refresh_flutter3: ^x.y.z  # 替换为最新版本号

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

接下来,是一个完整的示例代码,展示如何在Flutter中使用pull_to_refresh_flutter3插件:

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

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

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

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

class _MyHomePageState extends State<MyHomePage> {
  final RefreshController _refreshController = RefreshController();
  List<String> _items = List.generate(20, (i) => "Item ${i + 1}");
  bool _isLoading = false;

  @override
  void initState() {
    super.initState();
    // 监听刷新状态
    _refreshController.addListener(() {
      if (_refreshController.refreshState == RefreshState.Idle &&
          _refreshController.loadState == RefreshState.Idle) {
        _isLoading = false;
      }
    });
  }

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

  Future<void> _onRefresh() async {
    // 模拟网络请求
    await Future.delayed(Duration(seconds: 2));
    setState(() {
      _items = List.generate(20, (i) => "Refreshed Item ${i + 1}");
    });
    // 完成刷新
    _refreshController.finishRefresh(success: true);
  }

  Future<void> _onLoad() async {
    setState(() {
      _isLoading = true;
    });
    // 模拟网络请求
    await Future.delayed(Duration(seconds: 2));
    setState(() {
      int start = _items.length;
      int end = start + 10;
      _items.addAll(List.generate(10, (i) => "Loaded Item ${start + i}"));
      _isLoading = false;
    });
    // 完成加载
    _refreshController.finishLoad(noMoreData: _items.length >= 50);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Pull To Refresh Flutter3 Demo'),
      ),
      body: SmartRefresher(
        controller: _refreshController,
        enablePullDown: true,
        enablePullUp: true,
        header: WaterDropHeader(),
        footer: ClassicsFooter(),
        onRefresh: _onRefresh,
        onLoad: _onLoad,
        child: ListView.builder(
          itemCount: _items.length + (_isLoading ? 1 : 0),
          itemBuilder: (context, index) {
            if (index == _items.length && _isLoading) {
              return Padding(
                padding: const EdgeInsets.all(16.0),
                child: CircularProgressIndicator(),
              );
            }
            return ListTile(
              title: Text(_items[index]),
            );
          },
        ),
      ),
    );
  }
}

在这个示例中,我们:

  1. 创建了一个RefreshController来控制刷新逻辑。
  2. 使用SmartRefresher组件来包裹ListView,并配置了刷新和加载更多的头部和底部。
  3. 实现了_onRefresh_onLoad方法来处理下拉刷新和加载更多的逻辑。
  4. 使用ListView.builder来构建列表项,并在加载更多时显示一个进度指示器。

你可以根据实际需求修改这个示例,比如更改网络请求逻辑或调整UI样式。

回到顶部