Flutter声明式下拉刷新插件declarative_refresh_indicator的使用

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

Flutter声明式下拉刷新插件declarative_refresh_indicator的使用

介绍

DeclarativeRefreshIndicator 是一个声明式的下拉刷新组件,灵感来源于 SwitchCheckbox 组件。与传统的 RefreshIndicator 不同,DeclarativeRefreshIndicator 通过 refreshingonRefresh 参数来接收状态和分发事件,本身不持有任何状态。这使得它在使用基于事件的状态管理(如 BLoC 或 Redux)时更加灵活。

使用方法

DeclarativeRefreshIndicator 的使用非常简单,只需要提供两个参数:

  • refreshing: 一个布尔值,表示当前是否正在刷新。
  • onRefresh: 一个异步函数,当用户触发下拉刷新时调用。

下面是一个完整的示例代码,展示了如何使用 DeclarativeRefreshIndicator 实现一个带有下拉刷新功能的列表。

完整示例代码

import 'dart:async';
import 'dart:math';

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

/// 一个使用 [DeclarativeRefreshIndicator] 的示例应用。
///
/// 应用显示一个随机颜色的列表,生成延迟为2秒。支持下拉刷新,并且可以通过 AppBar 中的开关强制显示刷新指示器。
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: 'declarative_refresh_indicator 示例',
      home: MyListPage(),
    );
  }
}

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

  @override
  _MyListPageState createState() => _MyListPageState();
}

class _MyListPageState extends State<MyListPage> {
  static const _rowHeight = 56.0;

  var _randomColors = const <Color>[]; // 存储随机颜色的列表
  var _loading = false; // 标记是否正在加载
  var _forceShowIndicator = false; // 强制显示刷新指示器

  @override
  void initState() {
    super.initState();
    _load(); // 初始化时加载数据
  }

  /// 模拟加载数据的过程
  void _load() async {
    setState(() => _loading = true); // 设置加载状态为 true
    await Future<void>.delayed(const Duration(seconds: 2)); // 模拟2秒的加载延迟
    _randomColors = _generateRandomColors(); // 生成随机颜色
    if (mounted) setState(() => _loading = false); // 加载完成后设置状态为 false
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('declarative_refresh_indicator 示例'),
        actions: [
          Tooltip(
            message: '强制显示指示器',
            child: Switch(
              value: _forceShowIndicator, // 开关的当前状态
              onChanged: (value) => setState(() => _forceShowIndicator = value), // 切换开关时更新状态
            ),
          ),
        ],
      ),
      body: DeclarativeRefreshIndicator(
        refreshing: _loading || _forceShowIndicator, // 判断是否显示刷新指示器
        onRefresh: _load, // 下拉刷新时调用的函数
        child: ListView.builder(
          physics: const AlwaysScrollableScrollPhysics(), // 确保列表可以一直滚动
          itemCount: _randomColors.length, // 列表项的数量
          itemExtent: _rowHeight, // 每个列表项的高度
          itemBuilder: (context, index) {
            return ColoredBox(
              color: _randomColors[index], // 设置背景颜色
              child: const SizedBox(height: _rowHeight), // 占位容器
            );
          },
        ),
      ),
    );
  }

  /// 生成100个随机颜色
  static List<Color> _generateRandomColors() {
    final random = Random();
    return List.generate(100, (_) {
      const alpha = 0x80; // 透明度
      final rgb = random.nextInt(0xFFFFFF + 1); // 随机生成 RGB 值
      return Color((alpha << (8 * 3)) | rgb); // 合成颜色
    });
  }
}

代码说明

  1. _loading: 用于标记是否正在加载数据。当用户下拉刷新时,_loading 会被设置为 true,并在数据加载完成后设置为 false
  2. _forceShowIndicator: 用于强制显示刷新指示器。通过 AppBar 中的开关可以控制是否始终显示刷新指示器,方便调试。
  3. _load: 模拟数据加载的过程,使用 Future.delayed 模拟2秒的延迟,然后生成100个随机颜色。
  4. DeclarativeRefreshIndicator: 通过 refreshing 参数控制是否显示刷新指示器,onRefresh 参数指定下拉刷新时调用的函数。
  5. ListView.builder: 构建一个可滚动的列表,每个列表项是一个带有随机颜色的 ColoredBox

为什么需要这个插件?

虽然上面的例子看起来并不复杂,但传统的 RefreshIndicator 在与基于事件的状态管理(如 BLoC 或 Redux)结合使用时可能会变得复杂。DeclarativeRefreshIndicator 提供了一种更简洁的方式来处理下拉刷新,特别是在这些状态管理框架中,事件或动作是同步分发的,而没有返回 Future 的情况下。

许可证

该插件遵循 MIT 许可证,允许自由使用、复制、修改和分发。具体的许可证内容如下:

MIT License

Copyright (c) 2021 hacker1024

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声明式下拉刷新插件declarative_refresh_indicator的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


当然,下面是一个关于如何在Flutter项目中使用declarative_refresh_indicator插件的代码示例。这个插件允许你以声明式的方式来实现下拉刷新功能,而不是使用传统的回调方法。

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

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

然后,运行flutter pub get来获取依赖。

接下来,是一个简单的使用示例:

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

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

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

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

class _MyHomePageState extends State<MyHomePage> {
  // 模拟数据列表
  List<String> items = List.generate(20, (i) => "Item ${i + 1}");

  // 模拟刷新操作
  Future<void> refresh() async {
    await Future.delayed(Duration(seconds: 2)); // 模拟网络延迟
    // 更新数据列表(这里简单添加新项)
    setState(() {
      items = List.generate(items.length + 5, (i) => "Item ${i + 1}");
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Declarative Refresh Indicator Demo'),
      ),
      body: DeclarativeRefreshIndicator<RefreshState>(
        onRefresh: refresh,
        state: RefreshState.idle,
        builder: (context, state, refreshTrigger) {
          return ListView.builder(
            itemCount: items.length,
            itemBuilder: (context, index) {
              return ListTile(
                title: Text(items[index]),
              );
            },
          );
        },
        idleWidget: Container(), // 当不刷新时显示的占位widget
        refreshingWidget: CircularProgressIndicator(), // 刷新时显示的widget
        triggerDistance: 20.0, // 触发刷新的距离(滚动到顶部多少距离时触发)
      ),
    );
  }
}

// 定义刷新状态枚举
enum RefreshState {
  idle,
  triggering,
  refreshing,
}

在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个列表和一些模拟数据。DeclarativeRefreshIndicator被用来包装这个列表,并允许用户通过下拉来刷新数据。

  • onRefresh 参数是一个函数,当触发刷新时被调用。
  • state 参数表示当前的刷新状态,这允许你自定义不同状态下的UI。
  • builder 参数是一个函数,它接收上下文、当前刷新状态和刷新触发器,并返回一个widget(在这个例子中是ListView)。
  • idleWidgetrefreshingWidget 分别表示刷新空闲状态和刷新中状态的widget。
  • triggerDistance 参数定义了触发刷新的滚动距离。

请注意,这个示例中使用了RefreshState枚举来管理刷新状态,但DeclarativeRefreshIndicator本身并不依赖于这个枚举,你可以根据自己的需求来管理状态。

回到顶部