a widget provided to the flutter scroll component drop-down refresh and pull up load.

Last update: Jun 21, 2022

flutter_pulltorefresh

Intro

a widget provided to the flutter scroll component drop-down refresh and pull up load.support android and ios. If you are Chinese,click here(中文文档)

Features

  • pull up load and pull down refresh
  • It's almost fit for all Scroll witgets,like GridView,ListView...
  • provide global setting of default indicator and property
  • provide some most common indicators
  • Support Android and iOS default ScrollPhysics,the overScroll distance can be controlled,custom spring animate,damping,speed.
  • horizontal and vertical refresh,support reverse ScrollView also(four direction)
  • provide more refreshStyle: Behind,Follow,UnFollow,Front,provide more loadmore style
  • Support twoLevel refresh,implments just like TaoBao twoLevel,Wechat TwoLevel
  • enable link indicator which placing other place,just like Wechat FriendCircle refresh effect

Usage

add this line to pubspec.yaml

   dependencies:

    pull_to_refresh: ^2.0.0

import package

    import 'package:pull_to_refresh/pull_to_refresh.dart';

simple example,It must be noted here that ListView must be the child of SmartRefresher and cannot be separated from it. For detailed reasons, see here

  List<String> items = ["1", "2", "3", "4", "5", "6", "7", "8"];
  RefreshController _refreshController =
      RefreshController(initialRefresh: false);

  void _onRefresh() async{
    // monitor network fetch
    await Future.delayed(Duration(milliseconds: 1000));
    // if failed,use refreshFailed()
    _refreshController.refreshCompleted();
  }

  void _onLoading() async{
    // monitor network fetch
    await Future.delayed(Duration(milliseconds: 1000));
    // if failed,use loadFailed(),if no data return,use LoadNodata()
    items.add((items.length+1).toString());
    if(mounted)
    setState(() {

    });
    _refreshController.loadComplete();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      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: (c, i) => Card(child: Center(child: Text(items[i]))),
          itemExtent: 100.0,
          itemCount: items.length,
        ),
      ),
    );
  }

  // from 1.5.0, it is not necessary to add this line
  //@override
 // void dispose() {
    // TODO: implement dispose
  //  _refreshController.dispose();
  //  super.dispose();
 // }

The global configuration RefreshConfiguration, which configures all Smart Refresher representations under the subtree, is generally stored at the root of MaterialApp and is similar in usage to ScrollConfiguration. In addition, if one of your SmartRefresher behaves differently from the rest of the world, you can use RefreshConfiguration.copyAncestor() to copy attributes from your ancestor RefreshConfiguration and replace attributes that are not empty.

    // Smart Refresher under the global configuration subtree, here are a few particularly important attributes
     RefreshConfiguration(
         headerBuilder: () => WaterDropHeader(),        // Configure the default header indicator. If you have the same header indicator for each page, you need to set this
         footerBuilder:  () => ClassicFooter(),        // Configure default bottom indicator
         headerTriggerDistance: 80.0,        // header trigger refresh trigger distance
         springDescription:SpringDescription(stiffness: 170, damping: 16, mass: 1.9),         // custom spring back animate,the props meaning see the flutter api
         maxOverScrollExtent :100, //The maximum dragging range of the head. Set this property if a rush out of the view area occurs
         maxUnderScrollExtent:0, // Maximum dragging range at the bottom
         enableScrollWhenRefreshCompleted: true, //This property is incompatible with PageView and TabBarView. If you need TabBarView to slide left and right, you need to set it to true.
         enableLoadingWhenFailed : true, //In the case of load failure, users can still trigger more loads by gesture pull-up.
         hideFooterWhenNotFull: false, // Disable pull-up to load more functionality when Viewport is less than one screen
         enableBallisticLoad: true, // trigger load more by BallisticScrollActivity
        child: MaterialApp(
            ........
        )
    );

1.5.6 add new feather: localization ,you can add following code in MaterialApp or CupertinoApp:

    MaterialApp(
            localizationsDelegates: [
              // this line is important
              RefreshLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
              GlobalMaterialLocalizations.delegate
            ],
            supportedLocales: [
              const Locale('en'),
              const Locale('zh'),
            ],
            localeResolutionCallback:
                (Locale locale, Iterable<Locale> supportedLocales) {
              //print("change language");
              return locale;
            },
    )

ScreenShots

Examples

Style basic header in other place reverse + horizontal
Style twoLevel use with other widgets chat
Style simple custom header(使用SpinKit) dragableScrollSheet+LoadMore Gif Indicator

Indicator

各种指示器

refresh style pull up load style
RefreshStyle.Follow
Follow
RefreshStyle.UnFollow
不跟随
LoadStyle.ShowAlways
永远显示
LoadStyle.HideAlways
永远隐藏
RefreshStyle.Behind
背部
RefreshStyle.Front
前面悬浮
LoadStyle.ShowWhenLoading
当加载中才显示,其它隐藏
Style ClassicIndicator WaterDropHeader MaterialClassicHeader
Style WaterDropMaterialHeader Shimmer Indicator Bezier+Circle

about SmartRefresher's child explain

Since 1.4.3, the child attribute has changed from ScrollView to Widget, but this does not mean that all widgets are processed the same. SmartRefresher's internal implementation mechanism is not like NestedScrollView

There are two main types of processing mechanisms here, the first categoryis the component inherited from ScrollView. At present, there are only three types, ListView, GridView, CustomScrollView. The second category is components that are not inherited from ScrollView, which generally put empty views, NoScrollable views (NoScrollable convert Scrollable), PageView, and you don't need to estimate height by LayoutBuilder yourself.

For the first type of mechanism, slivers are taken out of the system "illegally". The second is to put children directly into classes such as `SliverToBox Adapter'. By splicing headers and footers back and forth to form slivers, and then putting slivers inside Smart Refresher into CustomScrollView, you can understand Smart Refresher as CustomScrollView, because the inside is to return to CustomScrollView. So, there's a big difference between a child node and a ScrollView.

Now, guess you have a requirement: you need to add background, scrollbars or something outside ScrollView. Here's a demonstration of errors and correct practices

   //error
   SmartRefresher(
      child: ScrollBar(
          child: ListView(
             ....
      )
    )
   )

   // right
   ScrollBar(
      child: SmartRefresher(
          child: ListView(
             ....
      )
    )
   )

Demonstrate another wrong doing,put ScrollView in another widget

   //error
   SmartRefresher(
      child:MainView()
   )

   class MainView extends StatelessWidget{
       Widget build(){
          return ListView(
             ....
          );
       }

   }

The above mistake led to scrollable nesting another scrollable, causing you to not see the header and footer no matter how slippery you are. Similarly, you may need to work with components like NotificationListener, ScrollConfiguration..., remember, don't store them outside ScrollView (you want to add refresh parts) and Smart Refresher memory.。

More

Exist Problems

  • about NestedScrollView,When you slide down and then slide up quickly, it will return back. The main reason is that NestedScrollView does not consider the problem of cross-border elasticity under bouncingScrollPhysics. Relevant flutter issues: 34316, 33367, 29264. This problem can only wait for flutter to fix this.
  • SmartRefresher does not have refresh injection into ScrollView under the subtree, that is, if you put AnimatedList or RecordableListView in the child is impossible. I have tried many ways to solve this problem and failed. Because of the principle of implementation, I have to append it to the head and tail of slivers. In fact, the problem is not that much of my Component issues, such as AnimatedList, can't be used with AnimatedList and GridView unless I convert AnimatedList to SliverAnimatedList is the solution. At the moment, I have a temporary solution to this problem, but it's a bit cumbersome to rewrite the code inside it and then outside ScrollView. Add SmartRefresher, see my two examples Example 1Example 2

Thanks

SmartRefreshLayout

LICENSE


MIT License

Copyright (c) 2018 Jpeng

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.


GitHub

https://github.com/peng8350/flutter_pulltorefresh
Comments
  • 1. App is not built using new version 1.6.4

    Trying to build a flutter app using new version of the library 1.6.4. Logs when building:

    [+18456 ms] ../../../../../../.pub-cache/hosted/pub.dartlang.org/pull_to_refresh-1.6.4/lib/src/smart_refresher.dart:434:9: Error: No named parameter with the name 'keyboardDismissBehavior'.
    [        ]         keyboardDismissBehavior:
    [        ]         ^^^^^^^^^^^^^^^^^^^^^^^
    [        ] ../../../../flutter/packages/flutter/lib/src/widgets/scroll_view.dart:588:9: Context: Found this candidate, but the arguments don't match.
    [        ]   const CustomScrollView({
    [        ]         ^^^^^^^^^^^^^^^^
    [+8058 ms] ../../../../../../.pub-cache/hosted/pub.dartlang.org/pull_to_refresh-1.6.4/lib/src/smart_refresher.dart:434:9: Error: No named parameter with the name 'keyboardDismissBehavior'.
    [   +2 ms]         keyboardDismissBehavior:
    [        ]         ^^^^^^^^^^^^^^^^^^^^^^^
    [        ] ../../../../flutter/packages/flutter/lib/src/widgets/scroll_view.dart:588:9: Context: Found this candidate, but the arguments don't match.
    [        ]   const CustomScrollView({
    [        ]         ^^^^^^^^^^^^^^^^
    [+9585 ms] FAILURE: Build failed with an exception.
    [        ] * Where:
    [        ] Script '/Users/sergey/Projects/Flutter/flutter/packages/flutter_tools/gradle/flutter.gradle' line: 904
    [        ] * What went wrong:
    [        ] Execution failed for task ':app:compileFlutterBuildDebug'.
    [        ] > Process 'command '/Users/sergey/Projects/Flutter/flutter/bin/flutter'' finished with non-zero exit value 1
    [        ] * Try:
    [        ] Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    [        ] * Get more help at https://help.gradle.org
    [        ] BUILD FAILED in 38s
    [{"event":"app.progress","params":{"appId":"13afa2cc-8a69-46e0-b928-0536b88bb6f7","id":"0","progressId":null,"finished":true}}]
    [ +481 ms] Exception: Gradle task assembleDebug failed with exit code 1
    [   +8 ms] 
               #0      throwToolExit (package:flutter_tools/src/base/common.dart:14:3)
               #1      RunCommand.runCommand (package:flutter_tools/src/commands/run.dart:474:9)
               <asynchronous suspension>
               #2      FlutterCommand.verifyThenRunCommand (package:flutter_tools/src/runner/flutter_command.dart:977:18)
               #3      _rootRunUnary (dart:async/zone.dart:1198:47)
               #4      _CustomZone.runUnary (dart:async/zone.dart:1100:19)
               #5      _FutureListener.handleValue (dart:async/future_impl.dart:143:18)
               #6      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:696:45)
               #7      Future._propagateToListeners (dart:async/future_impl.dart:725:32)
               #8      Future._completeWithValue (dart:async/future_impl.dart:529:5)
               #9      _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:40:15)
               #10     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:311:13)
               #11     RunCommand.usageValues (package:flutter_tools/src/commands/run.dart)
               #12     _rootRunUnary (dart:async/zone.dart:1198:47)
               #13     _CustomZone.runUnary (dart:async/zone.dart:1100:19)
               #14     _FutureListener.handleValue (dart:async/future_impl.dart:143:18)
               #15     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:696:45)
               #16     Future._propagateToListeners (dart:async/future_impl.dart:725:32)
               #17     Future._completeWithValue (dart:async/future_impl.dart:529:5)
               #18     _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:40:15)
               #19     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:311:13)
               #20     AndroidDevice.isLocalEmulator (package:flutter_tools/src/android/android_device.dart)
               #21     _rootRunUnary (dart:async/zone.dart:1198:47)
               #22     _CustomZone.runUnary (dart:async/zone.dart:1100:19)
               #23     _FutureListener.handleValue (dart:async/future_impl.dart:143:18)
               #24     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:696:45)
               #25     Future._propagateToListeners (dart:async/future_impl.dart:725:32)
               #26     Future._completeWithValue (dart:async/future_impl.dart:529:5)
               #27     Future._asyncCompleteWithValue.<anonymous closure> (dart:async/future_impl.dart:567:7)
               #28     _rootRun (dart:async/zone.dart:1190:13)
               #29     _CustomZone.run (dart:async/zone.dart:1093:19)
               #30     _CustomZone.runGuarded (dart:async/zone.dart:997:7)
               #31     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1037:23)
               #32     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
               #33     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
               #34     _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:118:13)
               #35     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:169:5)
    

    It seems the error is in smart_refresher.dart file on 434 line, "No named parameter with the name 'keyboardDismissBehavior'" for CustomScrollView widget.

    Reviewed by sergey-regotun at 2021-01-19 22:24
  • 2. 基于fish redux使用时报错 初始化问题

    flutter: ══╡ EXCEPTION CAUGHT BY SCHEDULER LIBRARY ╞═════════════════════════════════════════════════════════
    flutter: The following assertion was thrown during a scheduler callback:
    flutter: Try not to call requestRefresh() before build,please call after the ui was rendered
    flutter: 'package:pull_to_refresh/src/smart_refresher.dart': Failed assertion: line 259 pos 12: 'position !=
    flutter: null'
    flutter:
    flutter: Either the assertion indicates an error in the framework itself, or we should provide substantially
    flutter: more information in this error message to help you determine and fix the underlying cause.
    flutter: In either case, please report this assertion by filing a bug on GitHub:
    flutter:   https://github.com/flutter/flutter/issues/new?template=BUG.md
    flutter:
    flutter: When the exception was thrown, this was the stack:
    flutter: #2      RefreshController.requestRefresh (package:pull_to_refresh/src/smart_refresher.dart:259:12)
    flutter: #3      new RefreshController.<anonymous closure> (package:pull_to_refresh/src/smart_refresher.dart:251:9)
    flutter: #4      _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1012:15)
    flutter: #5      _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:960:9)
    flutter: #6      _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:864:5)
    flutter: #10     _invoke (dart:ui/hooks.dart:219:10)
    flutter: #11     _drawFrame (dart:ui/hooks.dart:178:3)
    flutter: (elided 5 frames from class _AssertionError and package dart:async)
    flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
    
    
    Reviewed by flutterbest at 2019-07-04 11:30
  • 3. flutter 3.0 support

                     ^
    

    /D:/soft/flutter/.pub-cache/hosted/pub.flutter-io.cn/pull_to_refresh-2.0.0/lib/src/internals/indicator_wrap.dart:393:22: Warning: Operand of null-aware operation '!' has type 'WidgetsBinding' which excludes null.

    • 'WidgetsBinding' is from 'package:flutter/src/widgets/binding.dart' ('/D:/soft/flutter/packages/flutter/lib/src/widgets/binding.dart'). WidgetsBinding.instance!.addPostFrameCallback((_) {
    Reviewed by jeromekai at 2022-05-18 07:49
  • 4. Looking up a deactivated widget's ancestor is unsafe.

    I change tab with pull_to_refresh and catch this exception:

    Exception
    ════════ Exception caught by animation library ═════════════════════════════════
    The following assertion was thrown while notifying listeners for AnimationController:
    Looking up a deactivated widget's ancestor is unsafe.
    
    At this point the state of the widget's element tree is no longer stable.
    
    To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.
    
    When the exception was thrown, this was the stack
    #0      Element._debugCheckStateIsActiveForAncestorLookup.<anonymous closure> 
    package:flutter/…/widgets/framework.dart:3825
    #1      Element._debugCheckStateIsActiveForAncestorLookup 
    package:flutter/…/widgets/framework.dart:3839
    #2      Element.dependOnInheritedWidgetOfExactType 
    package:flutter/…/widgets/framework.dart:3881
    #3      Scrollable.of 
    package:flutter/…/widgets/scrollable.dart:255
    #4      _MaterialClassicHeaderState.initState.<anonymous closure> 
    package:pull_to_refresh/…/indicator/material_indicator.dart:79
    ...
    The AnimationController notifying listeners was: AnimationController#14251(⏮ 0.000; paused)
    ════════════════════════════════════════════════════════════════════════════════
    ══╡ EXCEPTION CAUGHT BY ANIMATION LIBRARY ╞═════════════════════════════════════════════════════════
    The following assertion was thrown while notifying listeners for AnimationController:
    Looking up a deactivated widget's ancestor is unsafe.
    At this point the state of the widget's element tree is no longer stable.
    To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by
    calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.
    When the exception was thrown, this was the stack:
    #0      Element._debugCheckStateIsActiveForAncestorLookup.<anonymous closure> 
    package:flutter/…/widgets/framework.dart:3825
    #1      Element._debugCheckStateIsActiveForAncestorLookup 
    package:flutter/…/widgets/framework.dart:3839
    #2      Element.dependOnInheritedWidgetOfExactType 
    package:flutter/…/widgets/framework.dart:3881
    #3      Scrollable.of 
    package:flutter/…/widgets/scrollable.dart:255
    #4      _MaterialClassicHeaderState.initState.<anonymous closure> 
    package:pull_to_refresh/…/indicator/material_indicator.dart:79
    #5      AnimationLocalListenersMixin.notifyListeners 
    package:flutter/…/animation/listener_helpers.dart:137
    #6      AnimationController.value= 
    package:flutter/…/animation/animation_controller.dart:368
    #7      _MaterialClassicHeaderState.resetValue 
    package:pull_to_refresh/…/indicator/material_indicator.dart:146
    #8      _WaterDropMaterialHeaderState.resetValue 
    package:pull_to_refresh/…/indicator/material_indicator.dart:292
    #9      RefreshIndicatorState._handleModeChange 
    package:pull_to_refresh/…/internals/indicator_wrap.dart:239
    #10     ChangeNotifier.notifyListeners 
    package:flutter/…/foundation/change_notifier.dart:209
    #11     ValueNotifier.value= 
    package:flutter/…/foundation/change_notifier.dart:276
    #12     IndicatorStateMixin.initState 
    package:pull_to_refresh/…/internals/indicator_wrap.dart:622
    #13     _MaterialClassicHeaderState.initState 
    package:pull_to_refresh/…/indicator/material_indicator.dart:92
    #14     _WaterDropMaterialHeaderState.initState 
    package:pull_to_refresh/…/indicator/material_indicator.dart:227
    #15     StatefulElement._firstBuild 
    package:flutter/…/widgets/framework.dart:4684
    #16     ComponentElement.mount 
    package:flutter/…/widgets/framework.dart:4520
    #17     Element.inflateWidget 
    package:flutter/…/widgets/framework.dart:3490
    #18     MultiChildRenderObjectElement.mount 
    package:flutter/…/widgets/framework.dart:5991
    #19     _ViewportElement.mount 
    package:flutter/…/widgets/viewport.dart:207
    ...     Normal element mounting (88 frames)
    #107    Element.inflateWidget 
    package:flutter/…/widgets/framework.dart:3490
    #108    Element.updateChild 
    package:flutter/…/widgets/framework.dart:3258
    #109    _LayoutBuilderElement._layout.<anonymous closure> 
    package:flutter/…/widgets/layout_builder.dart:137
    #110    BuildOwner.buildScope 
    package:flutter/…/widgets/framework.dart:2620
    #111    _LayoutBuilderElement._layout 
    package:flutter/…/widgets/layout_builder.dart:117
    #112    RenderObject.invokeLayoutCallback.<anonymous closure> 
    package:flutter/…/rendering/object.dart:1868
    #113    PipelineOwner._enableMutationsToDirtySubtrees 
    package:flutter/…/rendering/object.dart:920
    #114    RenderObject.invokeLayoutCallback 
    package:flutter/…/rendering/object.dart:1868
    #115    RenderConstrainedLayoutBuilder.rebuildIfNecessary 
    package:flutter/…/widgets/layout_builder.dart:226
    #116    _RenderLayoutBuilder.performLayout 
    package:flutter/…/widgets/layout_builder.dart:299
    #117    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #118    RenderProxyBoxMixin.performLayout 
    package:flutter/…/rendering/proxy_box.dart:115
    #119    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #120    RenderProxyBoxMixin.performLayout 
    package:flutter/…/rendering/proxy_box.dart:115
    #121    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #122    RenderProxyBoxMixin.performLayout 
    package:flutter/…/rendering/proxy_box.dart:115
    #123    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #124    RenderSliverFixedExtentBoxAdaptor.performLayout 
    package:flutter/…/rendering/sliver_fixed_extent_list.dart:248
    #125    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #126    RenderSliverEdgeInsetsPadding.performLayout 
    package:flutter/…/rendering/sliver_padding.dart:137
    #127    _RenderSliverFractionalPadding.performLayout 
    package:flutter/…/widgets/sliver_fill.dart:170
    #128    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #129    RenderViewportBase.layoutChildSequence 
    package:flutter/…/rendering/viewport.dart:471
    #130    RenderViewport._attemptLayout 
    #131    RenderViewport.performLayout 
    package:flutter/…/rendering/viewport.dart:1374
    #132    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #133    RenderProxyBoxMixin.performLayout 
    package:flutter/…/rendering/proxy_box.dart:115
    #134    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #135    RenderProxyBoxMixin.performLayout 
    package:flutter/…/rendering/proxy_box.dart:115
    #136    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #137    RenderProxyBoxMixin.performLayout 
    package:flutter/…/rendering/proxy_box.dart:115
    #138    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #139    RenderProxyBoxMixin.performLayout 
    package:flutter/…/rendering/proxy_box.dart:115
    #140    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #141    RenderProxyBoxMixin.performLayout 
    package:flutter/…/rendering/proxy_box.dart:115
    #142    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #143    RenderProxyBoxMixin.performLayout 
    package:flutter/…/rendering/proxy_box.dart:115
    #144    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #145    RenderProxyBoxMixin.performLayout 
    package:flutter/…/rendering/proxy_box.dart:115
    #146    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #147    RenderProxyBoxMixin.performLayout 
    package:flutter/…/rendering/proxy_box.dart:115
    #148    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #149    RenderProxyBoxMixin.performLayout 
    package:flutter/…/rendering/proxy_box.dart:115
    #150    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #151    RenderProxyBoxMixin.performLayout 
    package:flutter/…/rendering/proxy_box.dart:115
    #152    RenderObject.layout 
    package:flutter/…/rendering/object.dart:1769
    #153    MultiChildLayoutDelegate.layoutChild 
    package:flutter/…/rendering/custom_layout.dart:173
    #154    _ScaffoldLayout.performLayout 
    package:flutter/…/material/scaffold.dart:495
    #155    MultiChildLayoutDelegate._callPerformLayout 
    package:flutter/…/rendering/custom_layout.dart:242
    #156    RenderCustomMultiChildLayoutBox.performLayout 
    package:flutter/…/rendering/custom_layout.dart:401
    #157    RenderObject._layoutWithoutResize 
    package:flutter/…/rendering/object.dart:1632
    #158    PipelineOwner.flushLayout 
    package:flutter/…/rendering/object.dart:889
    #159    RendererBinding.drawFrame 
    package:flutter/…/rendering/binding.dart:404
    #160    WidgetsBinding.drawFrame 
    package:flutter/…/widgets/binding.dart:867
    #161    RendererBinding._handlePersistentFrameCallback 
    package:flutter/…/rendering/binding.dart:286
    #162    SchedulerBinding._invokeFrameCallback 
    package:flutter/…/scheduler/binding.dart:1117
    #163    SchedulerBinding.handleDrawFrame 
    package:flutter/…/scheduler/binding.dart:1056
    #164    SchedulerBinding._handleDrawFrame 
    package:flutter/…/scheduler/binding.dart:972
    #168    _invoke  (dart:ui/hooks.dart:253:10)
    #169    _drawFrame  (dart:ui/hooks.dart:211:3)
    (elided 3 frames from dart:async)
    The AnimationController notifying listeners was:
      AnimationController#14251(⏮ 0.000; paused)
    
    flutter doctor --version
    Flutter 1.20.0-8.0.pre.75 • channel master • https://github.com/flutter/flutter.git
    Framework • revision bb3280885c (8 hours ago) • 2020-07-13 16:28:27 -0700
    Engine • revision f10f172573
    Tools • Dart 2.9.0 (build 2.9.0-20.0.dev 06cb010247)
    
    Reviewed by Gorniv at 2020-07-14 07:44
  • 5. 明明执行了RefreshCompleted(),但是还是提示刷新中

    image

    void _onRefresh(Action action, Context<RewardCollectionState> ctx) {
      getMoment().then((moments) {
        ctx.dispatch(RewardCollectionActionCreator.modify((clone) {
          clone.moments = moments;
        }));
        ctx.state.refreshController.refreshCompleted();
      }).catchError((e) {
        ctx.state.refreshController.refreshFailed();
      });
    }
    
    Reviewed by EaglesChen at 2020-04-15 18:42
  • 6. 这个代码中,怎么缓存页面

    https://github.com/peng8350/flutter_pulltorefresh/blob/master/example/lib/ui/example/useStage/Nested.dart

    怎么缓存页面。 我的解决办法是: class _RefreshListViewState extends State with AutomaticKeepAliveClientMixin {

    @override bool get wantKeepAlive => true; 了 但是这样 ,一个页面发生 更多加载,全部页面的都出发了

    Reviewed by Sabirjan at 2021-04-06 07:32
  • 7. How to remove animation with enableBallisticRefresh=false?

    When setting enableBallisticRefresh: false (which is the default), as expected, no refresh is triggered when scrolling up. However, the refresh animation is still visible. How can I only start the refresh animation when the drag/fling gesture was started when the scroll was at position 0?

    Reviewed by themadmrj at 2021-03-17 11:22
  • 8. Is it possible to pause collapse of header when refreshstatus.failed?

    Hi,

    I have a short question. Is it possible to stop the refresh header from collapsing when refreshstaus is set to .failed? Currently I am using the Shimmerheader like this:

    body: SafeArea(
            child: SmartRefresher(
              header: buildShimmerHeader(),
              controller: _refreshController,
              enablePullUp: false,
              onRefresh: () async {
                if (!_isOffline) {
                 // try refreshing... it fails
    
                  _refreshController.refreshFailed();
                } else {
                 //...
                }
              },
              child: ListView()
    

    Shimmerheader:

    final Widget body = ScaleTransition(
          scale: _scaleController,
          child: FadeTransition(
            opacity: _fadeController,
            child: mode == RefreshStatus.refreshing
                ? Shimmer.fromColors(
                    period: widget.period,
                    direction: widget.direction,
                    baseColor: widget.baseColor,
                    highlightColor: widget.highlightColor,
                    child: Center(
                      child: widget.text,
                    ),
                  )
                : mode == RefreshStatus.failed
                    ? Center(
              child: RichText(
                text: TextSpan(
                  children: [
                    WidgetSpan(
                      child: Padding(
                        padding: EdgeInsets.only(bottom: 1.5),
                        child: Icon(
                          Icons.error,
                          size: 23.0,
                          color: Colors.grey,
                        ),
                      ),
                    ),
                    TextSpan(
                      text: " Refresh failed",
                    ),
                  ],
                  style: TextStyle(
                    color: Colors.grey,
                    fontSize: 22,
                  ),
                ),
              ),
            )
                    : Center(
                        child: widget.text,
                      ),
          ),
        );
    
    

    What currently happens:

    1. onRefresh, ShimmerHeader does as normal
    2. refresh fails -> RefreshStatus.failed
    3. Shimmer Header text changes "Pull to refresh" -> "Refresh failed"
    4. Header collapses immediately

    What I want to do:

    1. onRefresh, ShimmerHeader does as normal
    2. refresh fails -> RefreshStatus.failed
    3. Shimmer Header text changes "Pull to refresh" -> "Refresh failed"
    4. Header waits 2 seconds before collapsing (<- How do I achieve this????)

    I know that onModeChange() exists, but this does not work:

     void onModeChange(RefreshStatus mode) async {
        if (mode == RefreshStatus.failed){
          _scaleController.stop(canceled: false);
          await Future.delayed(Duration(milliseconds: 2000));
          _scaleController.forward();
        }
      }
    

    How to I achieve this?

    I would be very grateful for your help :)

    Reviewed by vionc at 2020-07-26 14:20
  • 9. 关于在安卓中的惯性越界回弹

    在iOS中,利用惯性到达顶部的时候如果速度不为0,那么会触发越界回弹,但是SmartRefresher在安卓中利用惯性到达顶部的时候如果速度不为0时会弹出水波纹的效果而不是越界回弹,能否加一个这样的效果从而让安卓和iOS两端的体验一致呢,就是能够有越界回弹的效果,或者设置一个属性让用户定制是否启用越界回弹

    Reviewed by luckysmg at 2019-07-07 04:04
  • 10. 关于listview controller的问题

    我想做一个聊天的界面,首先加载15条,并且list view定位到最后, 当下拉的时候,我会在list view的0位置添加新的15条数据,但这时候会跳到第0条 我想加载新数据后,不要跳转,需要使用list view的controller控制位置,但是设置controller报错了

    不论给不给SmartRefresher设置controller都会报错

    Widget buildView(ChatContentListState state, Dispatch dispatch,
        ViewService viewService) {
      final ListAdapter adapter = viewService.buildAdapter();
      state.controller2.jumpTo(state.controller2.position.maxScrollExtent);
      return Column(children: <Widget>[
        Expanded(
            child: SmartRefresher(controller: null,
            onRefresh: () => dispatch(ChatContentListActionCreator.onRefreshAction()),
            enablePullDown: true,
            enablePullUp: false,
    //        controller: state.controller,
              child: ListView.builder(
                controller: state.controller2,
                itemBuilder: adapter.itemBuilder,
                itemCount: adapter.itemCount,),
            ))
      ],);
    
    Reviewed by crystal-lee at 2019-07-02 14:55
  • 11. iOs don't compile

    using iOs don't compile

     [+9041 ms] ../../../development/flutter/.pub-cache/hosted/pub.dartlang.org/pull_to_refresh-1.6.4/lib/src/smart_refresher.dart:434:9: Error: No named
    parameter with the name
                            'keyboardDismissBehavior'.
                            [   +2 ms]         keyboardDismissBehavior:
                            [        ]         ^^^^^^^^^^^^^^^^^^^^^^^
                            [        ] ../../../development/flutter/packages/flutter/lib/src/widgets/scroll_view.dart:588:9: Context: Found this candidate, but the arguments don't
    match.
                            [        ]   const CustomScrollView({
                            [        ]         ^^^^^^^^^^^^^^^^
                            [+7181 ms] Persisting file store
                            [  +16 ms] Done persisting file store
                            [   +3 ms] Target kernel_snapshot failed: Exception
                                       #0      KernelSnapshot.build (package:flutter_tools/src/build_system/targets/common.dart:267:7)
    

    flutter doctor -v

    [✓] Flutter (Channel stable, 1.22.5, on macOS 11.1 20C69 darwin-x64, locale it-IT)
        • Flutter version 1.22.5 at /Users/enrico/development/flutter
        • Framework revision 7891006299 (7 weeks ago), 2020-12-10 11:54:40 -0800
        • Engine revision ae90085a84
        • Dart version 2.10.4
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
        • Android SDK at /Users/enrico/Library/Android/sdk
        • Platform android-30, build-tools 30.0.2
        • ANDROID_HOME = /Users/enrico/Library/Android/sdk
        • ANDROID_SDK_ROOT = /Users/enrico/Library/Android/sdk
        • Java binary at: /Users/enrico/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/201.7042882/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
        • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
        • All Android licenses accepted.
    
    [✓] Xcode - develop for iOS and macOS (Xcode 12.2)
        • Xcode at /Applications/Xcode.app/Contents/Developer
        • Xcode 12.2, Build version 12B45b
        • CocoaPods version 1.9.3
    
    [!] Android Studio (version 4.1)
        • Android Studio at /Users/enrico/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/201.7042882/Android Studio.app/Contents
        ✗ Flutter plugin not installed; this adds Flutter specific functionality.
        ✗ Dart plugin not installed; this adds Dart specific functionality.
        • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
    
    [✓] VS Code (version 1.52.1)
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.18.1
    
    [✓] Connected device (1 available)
        • iPhone di Enrico (mobile) • 3943c5bf302b1f2af0cab6b8ce41a22381abb194 • ios • iOS 14.4
    
    ! Doctor found issues in 1 category.
    
    
    Reviewed by Miamoto-Musashi at 2021-01-27 22:23
  • 12. Warnings found when building the app and Flutter upgraded to 3.0

    These warning shows in red when building the app And shows in grey when using the --verbose flag:

    [ +903 ms] ../../Library/Flutter/.pub-cache/hosted/pub.dartlang.org/pull_to_refresh-2.0.0/lib/src/smart_refresher.dart:513:22: Warning: Operand of null-aware operation '!' has type 'WidgetsBinding' which excludes null.
    [        ]  - 'WidgetsBinding' is from 'package:flutter/src/widgets/binding.dart' ('../../Library/Flutter/packages/flutter/lib/src/widgets/binding.dart').
    [        ]       WidgetsBinding.instance!.addPostFrameCallback((_) {
    [        ]                      ^
    [        ] ../../Library/Flutter/.pub-cache/hosted/pub.dartlang.org/pull_to_refresh-2.0.0/lib/src/smart_refresher.dart:765:20: Warning: Operand of null-aware operation '!' has type 'WidgetsBinding' which excludes null.
    [        ]  - 'WidgetsBinding' is from 'package:flutter/src/widgets/binding.dart' ('../../Library/Flutter/packages/flutter/lib/src/widgets/binding.dart').
    [        ]     WidgetsBinding.instance!.addPostFrameCallback((_) {
    [        ]                    ^
    [        ] ../../Library/Flutter/.pub-cache/hosted/pub.dartlang.org/pull_to_refresh-2.0.0/lib/src/smart_refresher.dart:788:20: Warning: Operand of null-aware operation '!' has type 'WidgetsBinding' which excludes null.
    [        ]  - 'WidgetsBinding' is from 'package:flutter/src/widgets/binding.dart' ('../../Library/Flutter/packages/flutter/lib/src/widgets/binding.dart').
    [        ]     WidgetsBinding.instance!.addPostFrameCallback((_) {
    [        ]                    ^
    [        ] ../../Library/Flutter/.pub-cache/hosted/pub.dartlang.org/pull_to_refresh-2.0.0/lib/src/smart_refresher.dart:796:20: Warning: Operand of null-aware operation '!' has type 'WidgetsBinding' which excludes null.
    [        ]  - 'WidgetsBinding' is from 'package:flutter/src/widgets/binding.dart' ('../../Library/Flutter/packages/flutter/lib/src/widgets/binding.dart').
    [        ]     WidgetsBinding.instance!.addPostFrameCallback((_) {
    [        ]                    ^
    [        ] ../../Library/Flutter/.pub-cache/hosted/pub.dartlang.org/pull_to_refresh-2.0.0/lib/src/smart_refresher.dart:803:20: Warning: Operand of null-aware operation '!' has type 'WidgetsBinding' which excludes null.
    [        ]  - 'WidgetsBinding' is from 'package:flutter/src/widgets/binding.dart' ('../../Library/Flutter/packages/flutter/lib/src/widgets/binding.dart').
    [        ]     WidgetsBinding.instance!.addPostFrameCallback((_) {
    [        ]                    ^
    [  +23 ms] ../../Library/Flutter/.pub-cache/hosted/pub.dartlang.org/pull_to_refresh-2.0.0/lib/src/internals/indicator_wrap.dart:260:24: Warning: Operand of null-aware operation '!' has type 'WidgetsBinding' which excludes null.
    [        ]  - 'WidgetsBinding' is from 'package:flutter/src/widgets/binding.dart' ('../../Library/Flutter/packages/flutter/lib/src/widgets/binding.dart').
    [        ]         WidgetsBinding.instance!.addPostFrameCallback((_) {
    [        ]                        ^
    [        ] ../../Library/Flutter/.pub-cache/hosted/pub.dartlang.org/pull_to_refresh-2.0.0/lib/src/internals/indicator_wrap.dart:290:22: Warning: Operand of null-aware operation '!' has type 'WidgetsBinding' which excludes null.
    [        ]  - 'WidgetsBinding' is from 'package:flutter/src/widgets/binding.dart' ('../../Library/Flutter/packages/flutter/lib/src/widgets/binding.dart').
    [        ]       WidgetsBinding.instance!.addPostFrameCallback((_) {
    [        ]                      ^
    [        ] ../../Library/Flutter/.pub-cache/hosted/pub.dartlang.org/pull_to_refresh-2.0.0/lib/src/internals/indicator_wrap.dart:393:22: Warning: Operand of null-aware operation '!' has type 'WidgetsBinding' which excludes null.
    [   +1 ms]  - 'WidgetsBinding' is from 'package:flutter/src/widgets/binding.dart' ('../../Library/Flutter/packages/flutter/lib/src/widgets/binding.dart').
    [        ]       WidgetsBinding.instance!.addPostFrameCallback((_) {
    [        ]                      ^
    
    Reviewed by Ahmad-Hamwi at 2022-06-23 07:50

Related

filterList is a flutter package which provide utility to search/filter data from provided dynamic list.
filterList is a flutter package which provide utility to search/filter data from provided dynamic list.

filter_list Plugin FilterList is a flutter package which provide utility to search/filter on the basis of single/multiple selection from provided dyna

Jun 29, 2022
Clip your widgets with custom shapes provided.
Clip your widgets with custom shapes provided.

clippy_flutter Clip your widgets with custom shapes provided. #Arc, #Arrow, #Bevel, #ButtCheek, #Chevron, #Diagonal, #Label, #Message, #Paralellogram,

May 15, 2022
Load and get full control of your Rive files in a Flutter project using this library.
Load and get full control of your Rive files in a Flutter project using this library.

⚠️ Please migrate to the new Rive Flutter runtime. This runtime is for the old Rive (formerly Flare) and will only receive updates for breaking issues

Jun 21, 2022
Flutter UI challenge- Parallax scroll effect
Flutter UI challenge- Parallax scroll effect

Flutter UI Challenge- "Urban Planners" Parallax Scroll About project The application was written based on this great UI concept: https://dribbble.com/

Jun 24, 2022
A nested TabBarView overscroll unites outer TabBarView scroll event
A nested TabBarView overscroll unites outer TabBarView scroll event

union_tabs A nested TabBarView overscroll event unites outer TabBarView scroll event Getting Started 1.Install dependencies: union_tabs: ^1.0.0+7 2.

Jun 21, 2022
A Flutter widget that easily adds the flipping animation to any widget
A Flutter widget that easily adds the flipping animation to any widget

flip_card A component that provides a flip card animation. It could be used for hiding and showing details of a product. How to use import 'package:fl

Jun 22, 2022
A widget that allow user resize the widget with drag

Flutter-Resizable-Widget A widget that allow user resize the widget with drag Note: this widget uses Getx Example bandicam.2021-11-11.12-34-41-056.mp4

Jun 19, 2022
✨A clean and lightweight loading/toast widget for Flutter, easy to use without context, support iOS、Android and Web
✨A clean and lightweight loading/toast widget for Flutter, easy to use without context, support iOS、Android and Web

Flutter EasyLoading English | 简体中文 Live Preview ?? https://nslog11.github.io/flutter_easyloading Installing Add this to your package's pubspec.yaml fi

Jun 22, 2022
Flutter's core Dropdown Button widget with steady dropdown menu and many options you can customize to your needs.
Flutter's core Dropdown Button widget with steady dropdown menu and many options you can customize to your needs.

Flutter DropdownButton2 Intro Flutter's core Dropdown Button widget with steady dropdown menu and many options you can customize to your needs. Featur

Jun 23, 2022
A widget for stacking cards, which users can swipe horizontally and vertically with beautiful animations.
A widget for stacking cards, which users can swipe horizontally and vertically with beautiful animations.

A widget for stacking cards, which users can swipe horizontally and vertically with beautiful animations.

Jun 18, 2022
A draggable Flutter widget that makes implementing a SlidingUpPanel much easier!
A draggable Flutter widget that makes implementing a SlidingUpPanel much easier!

sliding_up_panel A draggable Flutter widget that makes implementing a SlidingUpPanel much easier! Based on the Material Design bottom sheet component,

Jun 23, 2022
Circular Reveal Animation as Flutter widget!
Circular Reveal Animation as Flutter widget!

Circular Reveal Animation Circular Reveal Animation as Flutter widget! Inspired by Android's ViewAnimationUtils.createCircularReveal(...). Статья с оп

Jun 12, 2022
A Flutter Package providing Avatar Glow Widget
A Flutter Package providing Avatar Glow Widget

Avatar Glow This Flutter package provides a Avatar Glow Widget with cool background glowing animation. Live Demo: https://apgapg.github.io/avatar_glow

Jun 28, 2022
A beautiful animated flutter widget package library. The tab bar will attempt to use your current theme out of the box, however you may want to theme it.
A beautiful animated flutter widget package library. The tab bar will attempt to use your current theme out of the box, however you may want to theme it.

Motion Tab Bar A beautiful animated widget for your Flutter apps Preview: | | Getting Started Add the plugin: dependencies: motion_tab_bar: ^0.1.5 B

Jun 30, 2022
Highly customizable, feature-packed calendar widget for Flutter
Highly customizable, feature-packed calendar widget for Flutter

TableCalendar Highly customizable, feature-packed calendar widget for Flutter. TableCalendar with custom styles TableCalendar with custom builders Fea

Jul 1, 2022
Flutter 3D Flip Animation Widget
Flutter 3D Flip Animation Widget

flutter_flip_view This is a flutter Widget base on pure Dart code that provides 3D flip card visuals. Usage add package in your pubspec.yaml dependenc

Jun 9, 2022
A simple toggle switch widget for Flutter.

Toggle Switch A simple toggle switch widget. It can be fully customized with desired icons, width, colors, text, corner radius, animation etc. It also

Jun 9, 2022
Base Flutter widget which triggers rebuild only of props changed

pure_widget Base widget which triggers rebuild only if props changed Installation pubspec.yaml: dependencies: pure_widget: ^1.0.0 Example import 'da

Dec 25, 2021
A Stepper Widget in Flutter using GetX

Stepper Flutter GetX Donate If you found this project helpful or you learned something from the source code and want to thank me, consider buying me a

Nov 27, 2021