A flutter widget that provides pull-down refresh and pull-up load.

Overview

flutter_easyrefresh

License Awesome Flutter Pub

English | 中文

正如名字一样,EasyRefresh很容易就能在Flutter应用上实现下拉刷新以及上拉加载操作,它支持几乎所有的Flutter控件。它的功能与Android的SmartRefreshLayout很相似,同样也吸取了很多三方库的优点。EasyRefresh中集成了多种风格的Header和Footer,但是它并没有局限性,你可以很轻松的自定义。使用Flutter强大的动画,甚至随便一个简单的控件也可以完成。EasyRefresh的目标是为Flutter打造一个强大,稳定,成熟的下拉刷新框架。

Web版本移步:vue-easyrefresh

Demo:下载 apk | web

特点功能:

  • 支持绝大多数Widget
  • 支持自定义并且已经集成了很多炫酷的 Header 和 Footer
  • 支持下拉刷新、上拉加载(可控制触发)
  • 支持 Header 和 Footer 列表嵌入以及视图浮动两种形式
  • 支持列表事件监听,制作任何样子的 Header 和 Footer,并且能够放在任何位置
  • 支持首次刷新,并自定义视图
  • 支持自定义列表空视图

传送门

项目演示

基本样式 个人中心
BasicPage UserProfilePage
NestedScrollView Header连接器
NestedScrollViewPage LinkHeaderPage
首次刷新 空视图
FirstRefreshPage EmptyPage
二楼 聊天页面
SecondFloorPage ChatPage

样式演示

Material BallPulse
MaterialPage BallPulsePage
BezierCircle BezierHourGlass
BezierCirclePage BezierHourGlassPage
Phoenix Delivery
PhoenixPage TaurusPage
Space Delivery
SpacePage DeliveryPage

简单用例

1.在 pubspec.yaml 中添加依赖

//pub方式
dependencies:
  flutter_easyrefresh: version

//导入方式
dependencies:
  flutter_easyrefresh:
    path: 项目路径

//git方式
dependencies:
  flutter_easyrefresh:
    git:
      url: git://github.com/xuelongqy/flutter_easyrefresh.git

2.在布局文件中添加 EasyreFresh

import 'package:flutter_easyrefresh/easy_refresh.dart';
....
  // 方式一
  EasyRefresh(
    child: ScrollView(),
    onRefresh: () async{
      ....
    },
    onLoad: () async {
      ....
    },
  )
  // 方式二
  EasyRefresh.custom(
    slivers: <Widget>[],
    onRefresh: () async{
      ....
    },
    onLoad: () async {
      ....
    },
  )
  // 方式三
  EasyRefresh.builder(
    builder: (context, physics, header, footer) {
      return CustomScrollView(
        physics: physics,
        slivers: <Widget>[
          ...
          header,
          ...
          footer,
        ],
      );
    }
    onRefresh: () async{
      ....
    },
    onLoad: () async {
      ....
    },
  )

3.触发刷新和加载动作

  EasyRefreshController _controller = EasyRefreshController();
  ....
  EasyRefresh(
    controller: _controller,
    ....
  );
  ....
  _controller.callRefresh();
  _controller.callLoad();

4.控制加载和刷新完成

  EasyRefreshController _controller = EasyRefreshController();
  ....
  EasyRefresh(
	enableControlFinishRefresh: true,
	enableControlFinishLoad: true,
    ....
  );
  ....
  _controller.finishRefresh(success: true);
  _controller.finishLoad(success: true, noMore: false);

使用指定的 Header 和 Footer

import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_easyrefresh/material_header.dart';
import 'package:flutter_easyrefresh/material_footer.dart';
....
  new EasyRefresh(
    header: MaterialHeader(),
    footer: MaterialFooter(),
    child: ScrollView(),
    ....
  )

添加国际化支持

不提供自带国际化支持,请自行设置ClassicalHeader和ClassicalFooter中需要展示的文字。

捐赠

如果你喜欢我的项目,请在项目右上角 "Star" 一下。你的支持是我最大的鼓励! ^_^ 你也还可以扫描下面的二维码,或者通过Donate to this project using Paypal,对作者进行打赏。

如果在捐赠留言中备注名称,将会被记录到列表中~ 如果你也是github开源作者,捐赠时可以留下github项目地址或者个人主页地址,链接将会被添加到列表中起到互相推广的作用
捐赠列表

QQ讨论群 - 554981921

进群须知

这个群不仅仅是解决EasyreFresh的问题,任何Flutter相关的问题都可以进行讨论。正如它的名字一样,有问必答,只要群主有时间,都会帮大家一起解决问题。

感谢

flutter_pulltorefresh
SmartRefreshLayout
flutter_spinkit

开源协议

 
MIT License

Copyright (c) 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.

 
Comments
  • ValueNotifier<TaskState> was used after being disposed

    ValueNotifier was used after being disposed

    您好,感谢项目开源。项目里使用了您的这个开源列表刷新库,很不错。 项目背景:项目中现在用的状态管理框架是Provider,版本4.3.2。项目目前是混合开发,框架用的是flutte boost.版本1.17.1.这是项目背景. 问题描述:不过刚升级了版本到2.1.5.去掉之前2.1.1版本国际化代码,改用demo中现用的这种方式。2.1.1版本使用没什么问题。升级后,项目第一次请求数据没有问题,再次请求其他数据会报以下崩溃错误信息。 Unhandled Exception: A ValueNotifier<TaskState> was used after being disposed. Once you have called dispose() on a ValueNotifier<TaskState>, it can no longer be used. #0 ChangeNotifier._debugAssertNotDisposed.<anonymous closure> (package:flutter/src/foundation/change_notifier.dart:106:9) #1 ChangeNotifier._debugAssertNotDisposed (package:flutter/src/foundation/change_notifier.dart:112:6) #2 ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:201:12) #3 ValueNotifier.value= (package:flutter/src/foundation/change_notifier.dart:274:5) #4 _EasyRefreshSliverLoadControlState.finishLoad (package:flutter_easyrefresh/src/footer/load_indicator.dart:635:25) #5 EasyRefreshController.finishLoad (package:flutter_easyrefresh/src/refresher.dart:652:25) #6 RefreshListViewModel.reload (package:ischool/provider1/view_model.dart:172:23) <asynchronous suspension> #7 RefreshListViewModel.refresh (package:ischool/provider1/view_model.dart:155:11) #8 _ActivistEvaluationListPageState.initState (package:ischool/modules/party/activist/page/activist_evaluation_list.dart:37:15) #9 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4640:58) #10 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4476:5) #11 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14) #12 Element.updateChild (package:flutter/src/widgets/framework.dart:3214:18) #13 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5830:14) #14 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14) #15 Element.updateChild (package:flutter/src/widgets/framework.dart:3214:18) #16 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4527:16) #17 Element.rebuild (package:flutter/src/widgets/framework.dart:4218:5) #18 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4481:5) #19 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4476:5) #20 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14) #21 Element.updateChild (package:flutter/src/widgets/framework.dart:3214:18) #22 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5830:14) #23 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14) #24 Element.updateChild (package:flutter/src/widgets/framework.dart:3214:18) #25 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5830:14) #26 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14) #27 Element.updateChild (package:flutter/src/widgets/framework.dart:3214:18) #28 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4527:16) #29 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4675:11) #30 Element.rebuild (package:flutter/src/widgets/framework.dart:4218:5) #31 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4481:5) #32 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4666:11) #33 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4476:5) #34 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14) #35 Element.updateChild (package:flutter/src/widgets/framework.dart:3214:18) #36 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5830:14) #37 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14) #38 Element.updateChild (package:flutter/src/widgets/framework.dart:3214:18) #39 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5830:14) #40 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14) #41 Element.updateChild (package:flutter/src/widgets/framework.dart:3214:18) #42 ComponentElement.performR

    opened by JanusKun 21
  • 需要迁移 Flutter 3.0

    需要迁移 Flutter 3.0

    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/header/refresh_indicator.dart:200:30: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
            if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.idle) {
                                 ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/header/refresh_indicator.dart:203:28: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
              SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
                               ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/header/refresh_indicator.dart:675:24: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
          SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
                           ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/header/refresh_indicator.dart:718:28: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
          if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.idle) {
                               ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/header/refresh_indicator.dart:721:26: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
            SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
                             ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/header/refresh_indicator.dart:766:30: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
                SchedulerBinding.instance!
                                 ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/header/refresh_indicator.dart:774:28: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
              SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
                               ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/header/refresh_indicator.dart:788:32: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
                  SchedulerBinding.instance!
                                   ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/header/header.dart:235:22: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
        SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
                         ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/footer/footer.dart:244:22: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
        SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
                         ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/footer/load_indicator.dart:198:30: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
            if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.idle) {
                                 ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/footer/load_indicator.dart:201:28: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
              SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
                               ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/footer/load_indicator.dart:596:24: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
          SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
                           ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/footer/load_indicator.dart:663:24: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
          SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
                           ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/footer/load_indicator.dart:705:28: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
          if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.idle) {
                               ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/footer/load_indicator.dart:708:26: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
            SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
                             ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/footer/load_indicator.dart:751:30: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
                SchedulerBinding.instance!
                                 ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/footer/load_indicator.dart:759:28: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
              SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
                               ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/footer/load_indicator.dart:770:32: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
                  SchedulerBinding.instance!
                                   ^
    ../../flutter_sdk/.pub-cache/hosted/pub.dartlang.org/flutter_easyrefresh-2.2.1/lib/src/refresher.dart:293:24: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../flutter_sdk/packages/flutter/lib/src/scheduler/binding.dart').
          SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
                           ^
    
    opened by RA1NO3O 16
  • SliverGeometry is not valid: The

    SliverGeometry is not valid: The "layoutExtent" exceeds the "paintExtent".

    快速滑动的时候偶尔出现出错(There are occasional mistakes when sliding fast)

    SliverGeometry is not valid: The "layoutExtent" exceeds the "paintExtent".

    opened by chougaigai 12
  • NestedScrollView包裹EasyRefresh的问题

    NestedScrollView包裹EasyRefresh的问题

    我使用一个没有Appbar的NestedScrollView在最外层,包裹一个EasyRefresh,下拉不松手,然后再上拉的时候每次都是NestedScrollView向上滚动,而EasyRefresh仍然保持原状态,我想实现类似于支付包首页的下拉效果,不松手上拉的时候改变的是EasyRefresh的状态,而不是最外层的NestedScrollView的状态。

    opened by MrDreamCatcher 12
  • On flutter 3.0.1, I recived some warning msg

    On flutter 3.0.1, I recived some warning msg

    ../../../../../../.pub-cache/hosted/pub.flutter-io.cn/flutter_easyrefresh-2.2.1/lib/src/header/refresh_indicator.dart:200:30: Warning: Operand of null-aware operation '!' has type 'SchedulerBinding' which excludes null.
     - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('../../../../../../fvm/versions/3.0.1/packages/flutter/lib/src/scheduler/binding.dart').
            if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.idle) {
    
    opened by codepgq 10
  • 数据不足时,每次上拉加载都需要往上滚动一下

    数据不足时,每次上拉加载都需要往上滚动一下

       onRefresh: () async {
                  controller.updateCcurrentIssuePageIndex(1);
                  await controller.getIssueList();
                  controller.refreshController.finishRefresh();
                  controller.refreshController.resetFooter();
                },
                onLoad: () async {
                  if (controller.pdaIssueListData.list!.length < controller.pdaIssueListData.total!) {
                    controller.updateCcurrentIssuePageIndex(controller.currentIssuePageIndex + 1);
                  }
    
                  await controller.getIssueList();
                  controller.refreshController.finishLoad(
                    controller.pdaIssueListData.list!.length >= controller.pdaIssueListData.total!
                        ? IndicatorResult.noMore
                        : IndicatorResult.success,
                  );
                },
    
    opened by jahnli 9
  • 在extended.NestedScrollView下 使用了控制器后自定义 firstRefreshWidget 无效 调用 finishRefresh 无效  topBouncing false 无效

    在extended.NestedScrollView下 使用了控制器后自定义 firstRefreshWidget 无效 调用 finishRefresh 无效 topBouncing false 无效

    代码层级 extended.NestedScrollViewRefreshIndicator( child : extended.NestedScrollView(body:extended.NestedScrollViewInnerScrollPositionKeyWidget('key',EasyRefresh())) , )

    opened by tom0gao 9
  • easyrefresh嵌套NestedScrollView时为了实现同时能下拉刷新和吸顶效果导致运行崩溃

    easyrefresh嵌套NestedScrollView时为了实现同时能下拉刷新和吸顶效果导致运行崩溃

    一直提示The following assertion was thrown during performResize(): Vertical viewport was given unbounded height. Viewports expand in the scrolling direction to fill their container.In this case, a vertical viewport was given an unlimited amount of vertical space in which to expand. This situation typically happens when a scrollable widget is nested inside another scrollable widget. If this widget is always nested in a scrollable widget there is no need to use a viewport because there will always be enough vertical space for the children. In this case, consider using a Column instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size the height of the viewport to the sum of the heights of its children. 以上错误,当把easyrefresh换成RefreshIndicator之后又一切正常了,请问到底哪里有问题?

    opened by ahtrun 9
  • 首次刷新有个bug

    首次刷新有个bug

      /// 首次刷新
      final bool firstRefresh;
    
      /// 首次刷新组件
      /// 不设置时使用header
      final Widget? firstRefreshWidget;
    
    // 判断是否开启首次刷新
        _enableFirstRefresh = widget.firstRefresh;
        if (_enableFirstRefresh) {
          _firstRefreshHeader = FirstRefreshHeader(widget.firstRefreshWidget!);
          SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
            callRefresh();
          });
        }
    

    上面说了不设置用header,使用的时候用了!!!!

    opened by SJJ-dot 8
  • How to add easyrefresh inside scrollview?

    How to add easyrefresh inside scrollview?

    - ListView
       - Container // my header
       - Container  // my body
         - EasyRefresh // pull to refresh
            - StaggeredGridView // my data
    

    How if I want add link this? Because I try, but it's not working. This is my example code I create:

    Widget build(BuildContext context) {
        var image = [
          "kinu3.jpg",
          "thailan2.jpg",
          "thailan5.jpg",
          "flatmarbel2.jpg",
          "ohvacoda2.jpg",
          "thailan1.jpg"
        ];
        Random _random = new Random();
        return Scaffold(
          backgroundColor: Colors.white,
          appBar: AppBar(),
          body: ListView(
            children: <Widget>[
              GestureDetector(
                onTap: () {
                  _getPermission(context);
                },
                child: Image.asset(StringImageAsset.maps),
              ),
              InkWell(
                onTap: () {
                  Navigation.intent(context, AddsBannerDetail());
                },
                child: BannerHome(),
              ),
              ListFilterFood(),
              Container(
                height: Sizes.height(context),
                width: Sizes.width(context),
                child: EasyRefresh(
                  header: SpaceHeader(),
                  onRefresh: () async {},
                  onLoad: () async {},
                  child: StaggeredGridView.countBuilder(
                    physics: NeverScrollableScrollPhysics(),
                    shrinkWrap: true,
                    crossAxisCount: 4,
                    mainAxisSpacing: 4.0,
                    crossAxisSpacing: 4.0,
                    itemCount: _sizes.length,
                    itemBuilder: (context, index) => _Tile(
                        index,
                        _sizes[index],
                        "http://202.157.176.102/pusaka/" +
                            image[_random.nextInt(image.length)]),
                    staggeredTileBuilder: (index) => StaggeredTile.fit(2),
                  ),
                ),
              ),
            ],
          ),
        );
      }
    

    The problem is, If I scroll to the top, the ListView not scroll, then if I scroll to the bottom, only in the StaggeredGridView is scroll. How I make this like using Sliver? Because I try using Sliver it's not working to with EasyRefresh with inside it have a GridView (StaggeredGridView).

    opened by rrifafauzikomara 8
  • how can use waiting loading As it exists in FutureBuilder

    how can use waiting loading As it exists in FutureBuilder

    hello, how can use waiting loading As it exists in FutureBuilder

    switch (snapshot.connectionState) {
            case ConnectionState.none:
            return Text('Press button to start.');
          case ConnectionState.active:
          case ConnectionState.waiting:
            return Text('Awaiting result...');
          case ConnectionState.done:
            if (snapshot.hasError)
              return Text('Error: ${snapshot.error}');
            return Text('Result: ${snapshot.data}');
        }
    
    opened by techpoints 8
  • Add Android-like scroll physics

    Add Android-like scroll physics

    The current _ERScrollPhysics is based on BouncingScrollPhysics, which is iOS-like behavior. For Android however, it is a bit strange, and I have not been able to figure out how to implement Android-like scroll behavior that works with this library.

    Could you please add Android-like scroll physics as well?

    opened by Pwuts 3
  • _AssertionError ('package:extended_nested_scroll_view/src/extended_nested_scroll_view.dart': Failed assertion: line 1760 pos 9: 'result': is not true.)

    _AssertionError ('package:extended_nested_scroll_view/src/extended_nested_scroll_view.dart': Failed assertion: line 1760 pos 9: 'result': is not true.)

    i used extended nested scrollview with easy refresh but i have some issues.one of them is (_AssertionError ('package:extended_nested_scroll_view/src/extended_nested_scroll_view.dart': Failed assertion: line 1760 pos 9: 'result': is not true.)) when i pull down page to refresh and then scrolling down cause this issue but not every time...(1 time in 5 try). the app is not crashing and i dont have any issu in performance but i want to know how can i handle this issue and it can cause proble in my project or not? thanks @xuelongqy @fluttercandies

    https://user-images.githubusercontent.com/120022216/206173224-d9df0ae8-2940-495c-8e59-ddbc97f26341.mp4

    `import 'dart:async';

    import 'package:example/widget/skeleton_item.dart'; import 'package:flutter/material.dart'; import 'package:easy_refresh/easy_refresh.dart'; import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'; import 'package:get/get.dart';

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

    @override TabBarViewPageState createState() { return TabBarViewPageState(); } }

    class TabBarViewPageState extends State with SingleTickerProviderStateMixin { late TabController _tabController; int _listCount = 20; int _gridCount = 20;

    @override void initState() { super.initState(); _tabController = TabController(length: 2, vsync: this); }

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

    @override Widget build(BuildContext context) { final themeData = Theme.of(context); return Scaffold( body: EasyRefresh.builder( header: ClassicHeader( clamping: true, position: IndicatorPosition.locator, mainAxisAlignment: MainAxisAlignment.end, dragText: 'Pull to refresh'.tr, armedText: 'Release ready'.tr, readyText: 'Refreshing...'.tr, processingText: 'Refreshing...'.tr, processedText: 'Succeeded'.tr, noMoreText: 'No more'.tr, failedText: 'Failed'.tr, messageText: 'Last updated at %T'.tr, ), footer: ClassicFooter( position: IndicatorPosition.locator, dragText: 'Pull to load'.tr, armedText: 'Release ready'.tr, readyText: 'Loading...'.tr, processingText: 'Loading...'.tr, processedText: 'Succeeded'.tr, noMoreText: 'No more'.tr, failedText: 'Failed'.tr, messageText: 'Last updated at %T'.tr, ), onRefresh: () async { await Future.delayed(const Duration(seconds: 2), () { if (mounted) { setState(() { if (_tabController.index == 0) { _listCount = 20; } else { _gridCount = 20; } }); } }); }, onLoad: () async { await Future.delayed(const Duration(seconds: 2), () { if (mounted) { setState(() { if (_tabController.index == 0) { _listCount += 10; } else { _gridCount += 10; } }); } }); }, childBuilder: (context, physics) { return ScrollConfiguration( behavior: const ERScrollBehavior(), child: ExtendedNestedScrollView( physics: physics, onlyOneScrollInBody: true, pinnedHeaderSliverHeightBuilder: () { return MediaQuery.of(context).padding.top + kToolbarHeight; }, headerSliverBuilder: (context, innerBoxIsScrolled) { return [ const HeaderLocator.sliver(clearExtent: false), SliverAppBar( expandedHeight: 300, pinned: true, bottom: PreferredSize( preferredSize: Size.fromHeight(70), child: TabBar( controller: _tabController, labelColor: themeData.colorScheme.primary, indicatorColor: themeData.colorScheme.primary, tabs: const [ Tab( text: 'List', ), Tab( text: 'Grid', ), ], ), ), ), ]; }, body: TabBarView( controller: _tabController, children: [ ExtendedVisibilityDetector( uniqueKey: const Key('Tab0'), child: _AutomaticKeepAlive( child: CustomScrollView( physics: physics, slivers: [ SliverList( delegate: SliverChildBuilderDelegate((context, index) { return const SkeletonItem(); }, childCount: _listCount)), const FooterLocator.sliver(), ], ), ), ), ExtendedVisibilityDetector( uniqueKey: const Key('Tab1'), child: _AutomaticKeepAlive( child: CustomScrollView( physics: physics, slivers: [ SliverGrid( delegate: SliverChildBuilderDelegate((context, index) { return const SkeletonItem( direction: Axis.horizontal, ); }, childCount: _gridCount), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 6 / 7, )), const FooterLocator.sliver(), ], ), ), ), ], ), ), ); }, ), ); } }

    class _AutomaticKeepAlive extends StatefulWidget { final Widget child;

    const _AutomaticKeepAlive({ Key? key, required this.child, }) : super(key: key);

    @override State<_AutomaticKeepAlive> createState() => _AutomaticKeepAliveState(); }

    class _AutomaticKeepAliveState extends State<_AutomaticKeepAlive> with AutomaticKeepAliveClientMixin { @override Widget build(BuildContext context) { super.build(context); return widget.child; }

    @override bool get wantKeepAlive => true; } `

    opened by RezaKhajvand 2
  • EasyRefreshPhysics.applyBoundaryConditions returned invalid overscroll value.

    EasyRefreshPhysics.applyBoundaryConditions returned invalid overscroll value.

    ======== Exception caught by animation library ===================================================== The following assertion was thrown while notifying listeners for AnimationController: EasyRefreshPhysics.applyBoundaryConditions returned invalid overscroll value.

    The method was called to consider a change from 429.5809482932091 to 415.98749604902747, which is a delta of -13.6 units. However, it returned an overscroll of 25.0 units, which has a greater magnitude than the delta. The applyBoundaryConditions method is only supposed to reduce the possible range of movement, not increase it. The scroll extents are 0.0 .. 391.0, and the viewport dimension is 651.0. When the exception was thrown, this was the stack: #0 ScrollPosition.applyBoundaryConditions. (package:flutter/src/widgets/scroll_position.dart:481:9) #1 ScrollPosition.applyBoundaryConditions (package:flutter/src/widgets/scroll_position.dart:493:6) #2 ScrollPosition.setPixels (package:flutter/src/widgets/scroll_position.dart:262:33) #3 ScrollPositionWithSingleContext.setPixels (package:flutter/src/widgets/scroll_position_with_single_context.dart:82:18) #4 BallisticScrollActivity.applyMoveTo (package:flutter/src/widgets/scroll_activity.dart:566:21) #5 BallisticScrollActivity._tick (package:flutter/src/widgets/scroll_activity.dart:553:10) #6 AnimationLocalListenersMixin.notifyListeners (package:flutter/src/animation/listener_helpers.dart:155:19) #7 AnimationController._tick (package:flutter/src/animation/animation_controller.dart:830:5) #8 Ticker._tick (package:flutter/src/scheduler/ticker.dart:238:12) #9 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1146:15) #10 SchedulerBinding.handleBeginFrame. (package:flutter/src/scheduler/binding.dart:1059:11) #11 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:614:13) #12 SchedulerBinding.handleBeginFrame (package:flutter/src/scheduler/binding.dart:1057:17) #13 SchedulerBinding._handleBeginFrame (package:flutter/src/scheduler/binding.dart:976:5) #17 _invoke1 (dart:ui/hooks.dart:170:10) #18 PlatformDispatcher._beginFrame (dart:ui/platform_dispatcher.dart:286:5) #19 _beginFrame (dart:ui/hooks.dart:104:31) (elided 3 frames from dart:async) The AnimationController notifying listeners was: AnimationController#44335(▶ 415.987; for BallisticScrollActivity)

    opened by WangDan1989 1
  • Null check operator used on a null value

    Null check operator used on a null value

    版本 easy_refresh: ^3.0.4+3

    代码

    view

    class MessageView extends GetView<MessageController> {
      const MessageView({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Obx(() => Scaffold(
              appBar: AppBar(
                title: Text(controller.appBarTitle.value),
                actions: [
                  IconButton(onPressed: () {}, icon: const Icon(Icons.notifications))
                ],
              ),
              body: EasyRefresh(
                  refreshOnStart: true,
                  controller: controller.easyRefreshController,
                  onRefresh: () => controller.onRefresh(),
                  onLoad: () => controller.onLoad(),
                  child: CustomListView(
                    builder: (int index) =>
                        buildItem(index, controller.dataList.value[index]),
                    dataList: controller.dataList.value,
                  )),
            ));
      }
    
    /// 自定义ListView
    class CustomListView extends StatelessWidget {
      const CustomListView(
          {Key? key,
          required this.builder,
          required this.count,
          this.padding = EdgeInsets.zero,
          this.space = 5.0})
          : super(key: key);
    
      /// 单元格
      final Function(int index) builder;
    
      /// 数据源数据
      final int count;
    
      final EdgeInsets padding;
    
      final double space;
    
      @override
      Widget build(BuildContext context) {
        return CustomScrollView(
          slivers: [
            count == 0
                ? const SliverFillRemaining(child: EmptyView())
                : SliverToBoxAdapter(child: Container()),
            SliverPadding(
              padding: padding,
              sliver: SliverList(
                delegate: SliverChildBuilderDelegate(
                  (context, index) {
                    final int itemIndex = index ~/ 2;
                    if (index.isEven) {
                      return builder.call(itemIndex);
                    }
                    return Divider(height: space, color: Colors.transparent);
                  },
                  semanticIndexCallback: (Widget widget, int localIndex) {
                    if (localIndex.isEven) {
                      return localIndex ~/ 2;
                    }
                    return null;
                  },
                  childCount: max(0, count * 2 - 1),
                ),
              ),
            ),
          ],
        );
      }
    }
    

    异常信息

    ======== Exception caught by scheduler library =====================================================
    The following _CastError was thrown during a scheduler callback:
    Null check operator used on a null value
    
    When the exception was thrown, this was the stack: 
    #0      IndicatorNotifier._canProcess (package:easy_refresh/src/notifier/indicator_notifier.dart:245:40)
    #1      IndicatorNotifier.callTask (package:easy_refresh/src/notifier/indicator_notifier.dart:396:59)
    #2      _EasyRefreshState._callRefresh (package:easy_refresh/src/easy_refresh.dart:427:28)
    #3      _EasyRefreshState.initState.<anonymous closure>.<anonymous closure> (package:easy_refresh/src/easy_refresh.dart:295:11)
    #4      SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1175:15)
    #5      SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1113:9)
    #6      SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1015:5)
    #7      _invoke (dart:ui/hooks.dart:148:13)
    #8      PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5)
    #9      _drawFrame (dart:ui/hooks.dart:115:31)
    
    
    opened by xyhuangjia 1
Releases(v3.2.0)
Owner
KnoYo
KnoYo
Flutter plugin for building pull to refresh effects with PullToRefreshNotification and PullToRefreshContainer quickly.

pull_to_refresh_notification Language: English | 中文简体 widget to build pull to refresh effects. Web demo for PullToRefreshNotification Chinese blog pul

FlutterCandies 165 Dec 28, 2022
GetX Architecture for large scale project, This project include - pagination, pull to refresh, localization, network call and advance error handling

GetX Architecture for large scale project, This project include - pagination, pull to refresh, localization, network call and advance error handling

Wai Han Ko 5 Nov 29, 2022
An easy way to use pull-to-refresh.

MJRefresh An easy way to use pull-to-refresh ?? ✍??Release Notes: more details Contents New Features Dynamic i18n Switching SPM Supported Swift Chaini

M了个J 13.7k Dec 29, 2022
This is an auction application just like eBay. Using firebase as the backend for signup & sign-in functionality. In addition to that, it's a two pages application with user bid in input and count down view.

Nilam This is an auction application just like eBay. Using firebase as the backend for signup & sign-in functionality. In addition to that, it's a two

Md. Siam 5 Nov 9, 2022
The classic to-do application where a user can write down all the things he wants to accomplish. Android only.

todo-app The classic to-do application where a user can write down all the things he wants to accomplish. Android only. Table of Contents todo-app Tab

Samuel Marques 9 Sep 23, 2022
A page transition which supports drag-down-to-pop gesture.

drag_down_to_pop A page transition which supports drag-down-to-pop gesture. The main source code is copied from the cupertino/route.dart in Flutter SD

nekocode 16 Aug 6, 2022
A font loader to download, cache and load web fonts in flutter with support for Firebase Cloud Storage.

Dynamic Cached Fonts A simple, easy to use yet customizable font loader to use web fonts. Demo: https://sidrao2006.github.io/dynamic_cached_fonts ?? I

Aneesh Rao 18 Dec 21, 2022
Simple flutter package to load and search string.

flutter_text_viewer flutter_text_viewer is a simple text viewer package to load and search text from assets,file. Demo Features Load text from assets/

Kunchok Tashi 3 Dec 15, 2022
A small library support load infinite for ListView - GridView on Flutter.

Paging A Flutter package that supports pagination(load infinite) for ListView, GridView Demo DataSource PageKeyedDataSource To create a PagingListView

Đặng Ngọc Đức 32 Dec 4, 2022
Flutter dynamically load translation in your app.

Flutter dynamically load translation in your app.

null 1 Apr 4, 2022
A command-line application provide an load optimization solution for flutter web

一个命令行工具,针对flutter web加载慢和缓存问题提供了一套解决方案。 功能 通过大文件分片和资源文件cdn化方式,优化flutter web页面加载慢问题。 通过资源文件hash化,解决浏览器强缓存导致功能无法更新问题。 开始 局部安装 dev_dependencies: flutte

Barry 10 Dec 29, 2022
A library for widgets that load their content one page (or batch) at a time.

A library for widgets that load their content one page (or batch) at a time (also known as lazy-loading and pagination). Features Load data one page a

null 224 Oct 20, 2022
Sangre - Sangre streams your backend queries in realtime to your clients minimizing the load via diffs

Sangre Sangre streams your backend queries in realtime to your clients minimizin

P.O.M 5 Nov 27, 2022
Boozin fitness - A sample app to that will pull data from Google Fit to get the steps count and calories burned

boozin_fitness A sample app to that will pull data from Google Fit to get the st

Abhishek Kumar Gupta 1 Nov 23, 2022
📖 A Guide for your first pull request

?? A Guide for your first pull request This project has been excluded by Hacktoberfest 2022 ✨ This project will help you to make your first pull reque

Dip Hire 27 Dec 2, 2022
A CLI tool to verify the test coverage of a pull request only, ignoring the rest of the project

This is a CI tool that analyzes the coverage rate of a pull request, ignoring the lines that were not changed in the PR. Motivation The coverage rate

Tales Barreto 3 Dec 15, 2022
A flutter UI package provides a cell widget that has leading and trailing swipe action menu.

Language: English |中文简体 flutter_swipe_action_cell A package that can give you a cell that can be swiped ,effect is like iOS native If you like this pa

WenJingRui 261 Jan 7, 2023
A Flutter package that provides an Emoji Keyboard widget.

Flutter Choose Keyboard A Flutter package that provides an Emoji Keyboard widget. BASED IN: https://github.com/JeffG05/emoji_picker Key Features Flutt

null 1 Oct 22, 2021
This Flutter package provides a Search Widget for selecting an option from a data list

Search Widget This Flutter package provides a Search Widget for selecting an option from a data list. Provides filtering of items based on the search

Ayush P Gupta 194 Oct 31, 2022