Flutter - 自定义插件 - 01 - zeking_refresh

1,385 阅读8分钟

目录

1. 快速使用
    1. 依赖
    2. 安装
    3. 引用
    4. 简单使用
2. ZekingRefreshController
3. ZekingRefresh
4. 先看下Example代码结构 和 主页面
5. Example 介绍
    5.1 默认场景UI展示
        5.1.1 效果图
        5.1.2 关键代码
    5.2 配置默认场景UI展示
    5.2.1 效果图
        5.2.2 关键代码
    5.3 自定义场景UI展示
        5.3.1 效果图
        5.3.2 关键代码
    5.4 设置 全局 场景UI展示
        5.4.1 效果图
        5.4.2 关键代码
    5.5 默认场景下动态改变 提示语 和 吐司提示
        5.5.1 效果图
        5.5.2 关键代码
    5.6 默认场景下动态改变 提示语 和 吐司提示
        5.6.1 效果图
        5.6.2 关键代码
    5.7 自定义 吐司 样式 为 弹框提示
        5.7.1 效果图
        5.7.2 关键代码
    5.8 和 CustomScrollView 使用
        5.8.1 效果图
        5.8.2 关键代码
    5.9 和 NestedScrollView 使用
        5.9.1 效果图
        5.9.2 关键代码

pub地址: pub.dev/packages/ze…

github地址:github.com/LZQL/zeking…

一个支持刷新加载中,刷新失败,刷新空数据,加载更多加载中,加载更多失败,加载更多加载全部数据,业务loading的刷新组件

zeking_refresh暂时不支持自定义刷新头部,现在用的是官方的RefreshIndicator,不过对它进行了修改onRefresh不在返回Future.

想看具体在项目中的应用?

可以查看

Flutter 练手项目 - WandroidBloc : juejin.cn/post/684490…

1. 快速使用

1. 依赖

dependencies:
  zeking_refresh: ^0.0.x  具体看pub

2. 安装

flutter packages get

3. 引用

import 'package:zeking_refresh/zeking_refresh.dart';

4. 简单使用

  ZekingRefreshController _refreshController;

  @override
  void initState() {
    _refreshController = ZekingRefreshController();
    super.initState();

    /// 首次进去 加载数据 ,会自动调用 onRefresh 方法
    _refreshController.refreshingWithLoadingView();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ZekingRefresh(
        controller: _refreshController,  // 必须参数
        onRefresh: onRefresh,            
        onLoading: onLoading,
        child: ListView.builder(
          padding: EdgeInsets.all(0),
          itemBuilder: (BuildContext context, int index) {
            return ItemWidget(data[index], () {});
          },
          itemCount: data.length,
        ),
      ),
    );
  }

2. ZekingRefreshController

通过 ZekingRefreshController 的方法来进行不同场景的UI展示

方法 说明
refreshingWithLoadingView() 刷新:打开一个新的页面,首先有一个圈圈在中间转,同时请求数据 widget
refreshFaild({String uiMsg, String toastMsg}) 刷新:数据为空 widget
refreshEmpty({String uiMsg, String toastMsg}) 刷新:失败 widget
refreshSuccess({String toastMsg}) 刷新:成功,修改状态,显示结果
loadMoreFailed({String uiMsg, String toastMsg}) 加载更多:失败 widget
loadMoreNoMore({String uiMsg, String toastMsg}) 加载更多:已加载全部数据widget
loadMoreSuccess({String toastMsg}) 加载更多:成功,修改状态,
loading() 业务加载中:loading widget ( 业务加载中:比如,上传图片,登录,提交数据的loading widget )
loadingEnd({String toastMsg}) 业务加载中: 结束 loading widget 的展示

说明一下:在上面的方法中,有的方法有uiMsgtoastMsg参数,是干什么的呢?

uiMsg 是用来动态修改 场景Ui上面的提示语的, 但是这个只对使用了框架默认的UI 才会起作用,若是自定义的 widget,需要在外部自己去setState

toastMsg 是用来谈吐司提示的,默认已经实现了 toast ,当然你不满足于默认的吐司样式, 可以自己去定义,也可以弹一个dialog,或者打印一个log,到时候传一个方法给我就好了, 具体的看ZekingRefreshtoastMethod参数,下面

3. ZekingRefresh

这个就是我们的刷新控件了,

ZekingRefresh({
        @required this.controller,
        @required this.onRefresh,
                  this.onLoading,
                  this.child,
                  this.displacement,
                  this.canLoadMore = true,
                  this.canRefresh = true,
                  this.scrollController,
                  this.physics,
                  this.useScrollController = true,
                  this.refreshLoadingWidget,
                  this.refreshLoadingImagePath,
                  this.refreshEmptyWidget,
                  this.refreshEmptyMessage,
                  this.refreshEmptyImagePath,
                  this.refreshEmptyImageWidth,
                  this.refreshEmptyImageHeight,
                  this.refreshEmptyCenterPadding,
                  this.refreshFailWidget,
                  this.refreshFailMessage,
                  this.refreshFailImagePath,
                  this.refreshFailImageWidth,
                  this.refreshFailImageHeight,
                  this.refreshFailCenterPadding,
                  this.loadLoadingWidget,
                  this.loadLoadingMessage,
                  this.loadFailWidget,
                  this.loadFailMessage,
                  this.loadNoMoreWidget,
                  this.loadNoMoreMessage,
                  this.loadingWidget,
                  this.toastMethod
              });
参数 说明
controller 其实就是 ZekingRefreshController 用来控制不同场景的切换
onRefresh 刷新方法
onLoading 加载更多方法
child 其实最后都会转为CustomScrollview,所以写特殊布局的时候需要注意一下
displacement 下拉刷新圈圈的偏移量,默认是40
canLoadMore 是否支持加载更多,默认 true
canRefresh 是否支持 下拉刷新,默认 true
useScrollController 是否给默认的ScrollController ,默认 true
scrollController 当useScrollController为true,ScrollController也为null的话,会new 一个 useScrollController
physics ScrollPhysics
======== ======================
refreshLoadingWidget 自定义的 刷新 加载中 widget
refreshLoadingImagePath 设置框架 默认 的 刷新 加载中 widget的图片路径,会自动旋转 ,refreshLoadingWidget 和 refreshLoadingImagePath 都不设置的话,默认显示一个CircularProgressIndicator
======== ======================
refreshEmptyWidget 自定义的 刷新 空数据 的 widget
refreshEmptyMessage 设置框架 默认 刷新 空数据 widget 的 提示语 ( 默认为 : '暂无数据,请点击屏幕重试' )
refreshEmptyImagePath 设置框架 默认 刷新 空数据 widget 的 图片路径,(图片和提示语的位置是居中,图片在上,提示语在下)
refreshEmptyImageWidth 设置框架 默认 刷新 空数据 widget 的 图片 宽度 ,( 默认 136 )
refreshEmptyImageHeight 设置框架 默认 刷新 空数据 widget 的 图片 高度 , ( 默认 122 )
refreshEmptyCenterPadding 设置框架 默认 刷新 空数据 widget 的 图片 和 提示语 的间隔,( 默认 36 )
======== ======================
refreshFailWidget 自定义的 刷新 失败 widget
refreshFailMessage 设置框架 默认 刷新 失败 widget 的 提示语 ( 默认为 : '加载失败,请点击屏幕重试' )
refreshFailImagePath 设置框架 默认 刷新 失败 widget 的 图片路径 ,(图片和提示语的位置是居中,图片在上,提示语在下)
refreshFailImageWidth 设置框架 默认 刷新 失败 widget 的 图片 宽度 ,( 默认 136 )
refreshFailImageHeight 设置框架 默认 刷新 失败 widget 的 图片 高度 , ( 默认 122 )
refreshFailCenterPadding 设置框架 默认 刷新 失败 widget 的 图片 和 提示语 的间隔,( 默认 36 )
======== ======================
loadLoadingWidget 自定义的 加载更多 加载中 widget
loadLoadingMessage 设置框架 默认 的 加载更多 加载中 widget的提示语( 默认为: '正在加载更多数据' )
======== ======================
loadFailWidget 自定义的 加载更多 失败 widget
loadFailMessage 设置框架 默认 的 加载更多 失败 widget的提示语( 默认为: '加载失败,请点击重试' )
======== ======================
loadNoMoreWidget 自定义的 加载更多 已加载全部数据 widget
loadNoMoreMessage 设置框架 默认 的 加载更多 已加载全部数据 widget的提示语( 默认为: '已加载全部数据' )
======== ======================
loadingWidget 自定义的 业务加载中 widget (业务加载中:比如,上传图片,登录,提交数据的loading widge)
======== ======================
toastMethod 自定义的 弹吐司方法,

4. 先看下Example代码结构 和 主页面

5. Example 介绍

5.1 默认场景UI展示

代码位置 example_page_01.dart

5.1.1 效果图

5.1.2 关键代码

5.2 配置默认场景UI展示

代码位置 example_page_02.dart

5.2.1 效果图

5.2.2 关键代码

5.3 自定义场景UI展示

代码位置 example_page_03.dart

5.3.1 效果图

5.3.2 关键代码

5.4 设置 全局 场景UI展示

代码位置 example_page_04.dartmy_refresh.dart

这个demo的效果图和 5.2的效果图是一样的,只是把 配置 封装成了 一个 MyRefreshWidget

5.4.1 效果图

5.4.2 关键代码

example_page_04.dart

my_refresh.dart

import 'package:zeking_refresh_example/common/index_all.dart';
import 'package:zeking_refresh/zeking_refresh.dart';

/// 自定义 配置全局 的 ZekingRefresh
class MyRefresh extends StatefulWidget {

  final ZekingRefreshController controller;
  final Function onRefresh; // 下拉刷新回调,
  final Function onLoading; // 加载更多回调
  final Widget child;
  final double displacement;
  final bool canLoadMore; // 是否支持加载更多操作,默认支持
  final ScrollController scrollController;
  final bool canRefresh; // 是否支持下拉刷新操作,默认支持

  final ScrollPhysics physics;
  final bool useScrollController; // 是否自动绑定scrollController

  // 刷新 加载中 widget
  final Widget refreshLoadingWidget;
  final String refreshLoadingImagePath;

  // 刷新 空数据 widget
  final Widget refreshEmptyWidget;
  final String refreshEmptyMessage;
  final String refreshEmptyImagePath;
  final double refreshEmptyImageWidth;
  final double refreshEmptyImageHeight;
  final double refreshEmptyCenterPadding;

  // 刷新 失败 widget
  final Widget refreshFailWidget;
  final String refreshFailMessage;
  final String refreshFailImagePath;
  final double refreshFailImageWidth;
  final double refreshFailImageHeight;
  final double refreshFailCenterPadding;

  // 加载更多 加载中  widget
  final Widget loadLoadingWidget;
  final String loadLoadingMessage;

  // 加载更多 失败 widget
  final Widget loadFailWidget;
  final String loadFailMessage;


  // 加载更多 已加载全部数据 widget
  final Widget loadNoMoreWidget;
  final String loadNoMoreMessage;

  // 加载中 widget (一般用户,事件的操作,比如 登录,上传数据,提交等操作场景)
  final Widget loadingWidget;

  final Function toastMethod; // 支持 自定义 吐司

  MyRefresh({@required this.controller,
                    this.onRefresh,
                    this.onLoading,
                    this.child,
                    this.displacement,
                    this.canLoadMore = true,
                    this.canRefresh = true,
                    this.scrollController,
                    this.physics,
                    this.useScrollController = true,
                    this.refreshLoadingWidget,
                    this.refreshLoadingImagePath,
                    this.refreshEmptyWidget,
                    this.refreshEmptyMessage,
                    this.refreshEmptyImagePath,
                    this.refreshEmptyImageWidth,
                    this.refreshEmptyImageHeight,
                    this.refreshEmptyCenterPadding,
                    this.refreshFailWidget,
                    this.refreshFailMessage,
                    this.refreshFailImagePath,
                    this.refreshFailImageWidth,
                    this.refreshFailImageHeight,
                    this.refreshFailCenterPadding,
                    this.loadLoadingWidget,
                    this.loadLoadingMessage,
                    this.loadFailWidget,
                    this.loadFailMessage,
                    this.loadNoMoreWidget,
                    this.loadNoMoreMessage,
                    this.loadingWidget,
                    this.toastMethod});

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

class _MyRefreshState extends State<MyRefresh> {
  @override
  Widget build(BuildContext context) {
    return ZekingRefresh(
      controller: widget.controller,
      onRefresh: widget.onRefresh,
      onLoading: widget.onLoading,
      child: widget.child,
      displacement: widget.displacement,
      canLoadMore: widget.canLoadMore,
      canRefresh: widget.canRefresh,
      scrollController: widget.scrollController,
      physics: widget.physics,
      useScrollController: widget.useScrollController,
      refreshLoadingWidget: widget.refreshLoadingWidget,
      refreshLoadingImagePath: widget.refreshLoadingImagePath ?? 'images/common_loading.png',
      refreshEmptyWidget: widget.refreshEmptyWidget,
      refreshEmptyMessage: widget.refreshEmptyMessage ,
      refreshEmptyImagePath: widget.refreshEmptyImagePath ?? 'images/empty.png',
      refreshEmptyImageWidth: widget.refreshEmptyImageWidth,
      refreshEmptyImageHeight: widget.refreshEmptyImageHeight ,
      refreshEmptyCenterPadding: widget.refreshEmptyCenterPadding ,
      refreshFailWidget: widget.refreshFailWidget,
      refreshFailMessage: widget.refreshFailMessage ,
      refreshFailImagePath: widget.refreshFailImagePath  ?? 'images/failure.png',
      refreshFailImageWidth: widget.refreshFailImageWidth,
      refreshFailImageHeight: widget.refreshFailImageHeight,
      refreshFailCenterPadding: widget.refreshFailCenterPadding,
      loadLoadingWidget: widget.loadLoadingWidget,
      loadLoadingMessage: widget.loadLoadingMessage ,
      loadFailWidget: widget.loadFailWidget,
      loadFailMessage: widget.loadFailMessage ,
      loadNoMoreWidget: widget.loadNoMoreWidget,
      loadNoMoreMessage: widget.loadNoMoreMessage ,
      loadingWidget: widget.loadingWidget,
      toastMethod: widget.toastMethod ,
    );
  }
}

5.5 默认场景下动态改变 提示语 和 吐司提示

代码位置 example_page_05.dart

其实这种场景,往往是配合了 5.4 设置 全局 场景UI展示一起使用的

5.5.1 效果图

5.5.2 关键代码

         new PopupMenuButton<String>(
            itemBuilder: (BuildContext context) => <PopupMenuItem<String>>[
              this.selectView('1. refreshingWithLoadingView', '1'),
              this.selectView('2. refreshEmpty', '2'),
              this.selectView('2.1 refreshEmpty 动态改变 提示语', '2.1'),
              this.selectView('2.2 refreshEmpty 弹吐司', '2.2'),
              this.selectView('3. refreshFaild', '3'),
              this.selectView('3.1 refreshFaild 动态改变 提示语', '3.1'),
              this.selectView('3.2 refreshFaild 弹吐司', '3.2'),
              this.selectView('4. loading', '4'),
              this.selectView('5. loadingEnd', '5'),
              this.selectView('5.1 loadingEnd 弹吐司', '5.1'),
              this.selectView('6. loadMoreFailed', '6'),
              this.selectView('6.1 loadMoreFailed 动态改变 提示语', '6.1'),
              this.selectView('6.2 loadMoreFailed 弹吐司', '6.2'),
              this.selectView('7. loadMoreNoMore', '7'),
              this.selectView('7.1 loadMoreNoMore 动态改变 提示语', '7.1'),
              this.selectView('7.2 loadMoreNoMore 弹吐司', '7.2'),
            ],
            onSelected: (String action) {
              // 点击选项的时候
              switch (action) {
                case '1':
                  _refreshController.refreshingWithLoadingView();
                  break;
                case '2':
                  _refreshController.refreshEmpty();
                  break;
                case '2.1':
                  _refreshController.refreshEmpty(uiMsg: '刷新 空数据 动态改变 -》 2.1');
                  break;
                case '2.2':
                  _refreshController.refreshEmpty(toastMsg: '刷新空数据 2.2 ');
                  break;
                case '3':
                  _refreshController.refreshFaild();
                  break;
                case '3.1':
                  _refreshController.refreshFaild(uiMsg: '刷新 失败 动态改变 -》 3.1');
                  break;
                case '3.2':
                  _refreshController.refreshFaild(toastMsg: '刷新空数据 3.2 ');
                  break;
                case '4':
                  _refreshController.loading();
                  break;
                case '5':
                  _refreshController.loadingEnd();
                  break;
                case '5.1':
                  _refreshController.loadingEnd(toastMsg: '请求数据结束 -》 5.1');
                  break;
                case '6':
                  _refreshController.loadMoreFailed();
                  break;
                case '6.1':
                  _refreshController.loadMoreFailed(uiMsg: '加载更多 失败 -》 6.1');
                  break;
                case '6.2':
                  _refreshController.loadMoreFailed(toastMsg: '加载更多 失败 -》6.2');
                  break;
                case '7':
                  _refreshController.loadMoreNoMore();
                  break;
                case '7.1':
                  _refreshController.loadMoreNoMore(uiMsg: '加载更多 已加载全部数据 -》 7.1');
                  break;
                case '7.2':
                  _refreshController.loadMoreNoMore(toastMsg: '加载更多 已加载全部数据 -》7.2');
                  break;
              }
            },
          )

5.6 默认场景下动态改变 提示语 和 吐司提示

代码位置 example_page_06.dart

这个场景其实和5.5一样 都是要配合 5.4 设置 全局 场景UI展示 使用 才有意义。

5.6.1 效果图

5.6.2 关键代码

这个demo我懒得写了,大概的思路就是

自定义场景 下 动态改变 提示语 和 吐司提示

吐司提示 和 example_page_04 是一样的 

动态改变提示语  的话 ,因为你的  布局是自定义的,

所以 你直接改变你传入的  下面这些 widget 就可以了。

        refreshLoadingWidget: buildRefreshLoading(), /// 自定义 刷新 加载中 布局
        refreshFailWidget: buildRefreshFaild(),      /// 自定义 刷新 失败 布局
        refreshEmptyWidget: buildRefreshEmpty(),     /// 自定义 刷新 空数据 布局
        loadLoadingWidget: buildLoadLoading(),       /// 自定义 加载更多 加载中 布局
        loadFailWidget: buildLoadFaild(),            /// 自定义 加载更多 失败 布局
        loadNoMoreWidget: buildLoadNoMore(),         /// 自定义 加载更多 已加载全部 布局
        loadingWidget:'),

5.7 自定义 吐司 样式 为 弹框提示

代码位置 example_page_07.dart

5.7.1 效果图

5.7.2 关键代码

_refreshController.refreshEmpty(toastMsg: '11111');

5.8 和 CustomScrollView 使用

代码位置 example_page_08.dart

5.8.1 效果图

5.8.2 关键代码

5.9 和 NestedScrollView 使用

代码位置 example_page_09.darttab_page.dart

5.9.1 效果图

5.9.2 关键代码

tab_page.dart

扫一扫,关注我的微信公众号
都是一些个人学习笔记

点击下面阅读原文,用电脑看,有目录,更舒服哦