Flutter plugin for building pull to refresh effects with PullToRefreshNotification and PullToRefreshContainer quickly.

Overview

pull_to_refresh_notification

pub package GitHub stars GitHub forks GitHub license GitHub issues flutter-candies

Language: English | 中文简体

widget to build pull to refresh effects.

Web demo for PullToRefreshNotification

Chinese blog

RefreshIndicatorMode

enum RefreshIndicatorMode {
  drag, // Pointer is down.
  armed, // Dragged far enough that an up event will run the onRefresh callback.
  snap, // Animating to the indicator's final "displacement".
  refresh, // Running the refresh callback.
  done, // Animating the indicator's fade-out after refreshing.
  canceled, // Animating the indicator's fade-out after not arming.
  error, //refresh failed
}

Sample 1 appbar

build appbar to pull to refresh with PullToRefreshContainer

   Widget build(BuildContext context) {
 return PullToRefreshNotification(
      color: Colors.blue,
      pullBackOnRefresh: true,
      onRefresh: onRefresh,
      child: CustomScrollView(
        slivers: <Widget>[
          PullToRefreshContainer(buildPulltoRefreshAppbar),
          SliverList(
              delegate:
                  SliverChildBuilderDelegate((BuildContext context, int index) {
            return Container(
                padding: EdgeInsets.only(bottom: 4.0),
                child: Column(
                  children: <Widget>[
                    Text(
                      "List item : ${listlength - index}",
                      style: TextStyle(fontSize: 15.0, inherit: false),
                    ),
                    Divider(
                      color: Colors.grey,
                      height: 2.0,
                    )
                  ],
                ));
          }, childCount: listlength)),
        ],
      ),
    );
}
    
     Widget buildPulltoRefreshAppbar(PullToRefreshScrollNotificationInfo info) {
        var action = Padding(
          child: info?.refreshWidget ?? Icon(Icons.more_horiz),
          padding: EdgeInsets.all(15.0),
        );
        var offset = info?.dragOffset ?? 0.0;
        return SliverAppBar(
            pinned: true,
            title: Text("PullToRefreshAppbar"),
            centerTitle: true,
            expandedHeight: 200.0 + offset,
            actions: <Widget>[action],
            flexibleSpace: FlexibleSpaceBar(
                //centerTitle: true,
                title: Text(
                  info?.mode?.toString() ?? "",
                  style: TextStyle(fontSize: 10.0),
                ),
                collapseMode: CollapseMode.pin,
                background: Image.asset(
                  "assets/467141054.jpg",
                  //fit: offset > 0.0 ? BoxFit.cover : BoxFit.fill,
                  fit: BoxFit.cover,
                )));
      }

Sample 2 header

build header to pull to refresh with PullToRefreshContainer. and you can easy to handle the status in pulling.

  Widget build(BuildContext context) {
    return PullToRefreshNotification(
       color: Colors.blue,
       onRefresh: onRefresh,
       maxDragOffset: 80.0,
       child: CustomScrollView(
         slivers: <Widget>[
           SliverAppBar(
             pinned: true,
             title: Text("PullToRefreshHeader"),
           ),
           PullToRefreshContainer(buildPulltoRefreshHeader),
           SliverList(
               delegate:
                   SliverChildBuilderDelegate((BuildContext context, int index) {
             return Container(
                 padding: EdgeInsets.only(bottom: 4.0),
                 child: Column(
                   children: <Widget>[
                     Text(
                       "List item : ${listlength - index}",
                       style: TextStyle(fontSize: 15.0, inherit: false),
                     ),
                     Divider(
                       color: Colors.grey,
                       height: 2.0,
                     )
                   ],
                 ));
           }, childCount: listlength)),
         ],
       ),
     );
   }
 
   Widget buildPulltoRefreshHeader(PullToRefreshScrollNotificationInfo info) {
     var offset = info?.dragOffset ?? 0.0;
     var mode = info?.mode;
     Widget refreshWidget = Container();
     //it should more than 18, so that RefreshProgressIndicator can be shown fully
     if (info?.refreshWidget != null &&
         offset > 18.0 &&
         mode != RefreshIndicatorMode.error) {
       refreshWidget = info.refreshWidget;
     }
 
     Widget child = null;
     if (mode == RefreshIndicatorMode.error) {
       child = GestureDetector(
           onTap: () {
             // refreshNotification;
             info?.pullToRefreshNotificationState?.show();
           },
           child: Container(
             color: Colors.grey,
             alignment: Alignment.bottomCenter,
             height: offset,
             width: double.infinity,
             //padding: EdgeInsets.only(top: offset),
             child: Container(
               padding: EdgeInsets.only(left: 5.0),
               alignment: Alignment.center,
               child: Text(
                 mode?.toString() + "  click to retry" ?? "",
                 style: TextStyle(fontSize: 12.0, inherit: false),
               ),
             ),
           ));
     } else {
       child = Container(
         color: Colors.grey,
         alignment: Alignment.bottomCenter,
         height: offset,
         width: double.infinity,
         //padding: EdgeInsets.only(top: offset),
         child: Row(
           mainAxisAlignment: MainAxisAlignment.center,
           children: <Widget>[
             refreshWidget,
             Container(
               padding: EdgeInsets.only(left: 5.0),
               alignment: Alignment.center,
               child: Text(
                 mode?.toString() ?? "",
                 style: TextStyle(fontSize: 12.0, inherit: false),
               ),
             )
           ],
         ),
       );
     }
 
     return SliverToBoxAdapter(
       child: child,
     );
   }

Sample 3 image

build zoom image to pull to refresh with using PullToRefreshContainer.

 Widget build(BuildContext context) {
     return PullToRefreshNotification(
       color: Colors.blue,
       pullBackOnRefresh: true,
       onRefresh: onRefresh,
       child: CustomScrollView(
         slivers: <Widget>[
           SliverAppBar(
             title: Text("PullToRefreshImage"),
           ),
           PullToRefreshContainer(buildPulltoRefreshImage),
           SliverList(
               delegate:
                   SliverChildBuilderDelegate((BuildContext context, int index) {
             return Container(
                 padding: EdgeInsets.only(bottom: 4.0),
                 child: Column(
                   children: <Widget>[
                     Text(
                       "List item : ${listlength - index}",
                       style: TextStyle(fontSize: 15.0, inherit: false),
                     ),
                     Divider(
                       color: Colors.grey,
                       height: 2.0,
                     )
                   ],
                 ));
           }, childCount: listlength)),
         ],
       ),
     );
   }
   
   Widget buildPulltoRefreshImage(PullToRefreshScrollNotificationInfo info) {
     var offset = info?.dragOffset ?? 0.0;
     Widget refreshWidget = Container();
     if (info?.refreshWidget != null) {
       refreshWidget = Material(
         type: MaterialType.circle,
         color: Theme.of(context).canvasColor,
         elevation: 2.0,
         child: Padding(
           padding: EdgeInsets.all(12),
           child: info.refreshWidget,
         ),
       );
     }
 
     return SliverToBoxAdapter(
       child: Stack(
         alignment: Alignment.center,
         children: <Widget>[
           Container(
               height: 200.0 + offset,
               width: double.infinity,
               child: Image.asset(
                 "assets/467141054.jpg",
                 //fit: offset > 0.0 ? BoxFit.cover : BoxFit.fill,
                 fit: BoxFit.cover,
               )),
           Center(
             child: Row(
               mainAxisAlignment: MainAxisAlignment.center,
               children: <Widget>[
                 refreshWidget,
                 Container(
                   padding: EdgeInsets.only(left: 5.0),
                   alignment: Alignment.center,
                   child: Text(
                     info?.mode?.toString() ?? "",
                     style: TextStyle(fontSize: 12.0, inherit: false),
                   ),
                 )
               ],
             ),
           )
         ],
       ),
     );
   }

Sample 4 candies

build candies animation to pull to refresh with using PullToRefreshContainer.

  Widget build(BuildContext context) {
    return Material(
      child: Stack(
        children: <Widget>[
          PullToRefreshNotification(
            color: Colors.blue,
            onRefresh: onRefresh,
            maxDragOffset: maxDragOffset,
            armedDragUpCancel: false,
            key: key,
            child: CustomScrollView(
              ///in case list is not full screen and remove ios Bouncing
              physics: AlwaysScrollableClampingScrollPhysics(),
              slivers: <Widget>[
                SliverAppBar(
                  title: Text("PullToRefreshCandies"),
                ),
                PullToRefreshContainer((info) {
                  var offset = info?.dragOffset ?? 0.0;
                  Widget child = Container(
                    alignment: Alignment.center,
                    height: offset,
                    width: double.infinity,
                    child: RefreshLogo(
                      mode: info?.mode,
                      offset: offset,
                    ),
                  );

                  return SliverToBoxAdapter(
                    child: child,
                  );
                }),
                SliverList(
                    delegate: SliverChildBuilderDelegate(
                        (BuildContext context, int index) {
                  return Container(
                      padding: EdgeInsets.only(bottom: 4.0),
                      child: Column(
                        children: <Widget>[
                          Text(
                            "List item : ${listlength - index}",
                            style: TextStyle(fontSize: 15.0),
                          ),
                          Divider(
                            color: Colors.grey,
                            height: 2.0,
                          )
                        ],
                      ));
                }, childCount: listlength)),
              ],
            ),
          ),
          Positioned(
            right: 20.0,
            bottom: 20.0,
            child: FloatingActionButton(
              child: Icon(Icons.refresh),
              onPressed: () {
                key.currentState.show(notificationDragOffset: maxDragOffset);
              },
            ),
          )
        ],
      ),
    );
  }

Sample 5 candies

Show how to use pull to refresh notification for reverse list like chat list.

        PullToRefreshNotification(
          onRefresh: onRefresh,
          maxDragOffset: 48,
          armedDragUpCancel: false,
          reverse: true,
          child: Column(
            children: <Widget>[
              PullToRefreshContainer(
                  (PullToRefreshScrollNotificationInfo info) {
                final double offset = info?.dragOffset ?? 0.0;

                //loading history data
                return Container(
                  height: offset,
                  child: const RefreshProgressIndicator(
                    valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
                    strokeWidth: 2.0,
                  ),
                );
              }),
              Expanded(
                child: ExtendedListView.builder(
                  ///in case list is not full screen and remove ios Bouncing
                  physics: const AlwaysScrollableClampingScrollPhysics(),
                  reverse: true,
                  extendedListDelegate:
                      const ExtendedListDelegate(closeToTrailing: true),
                  itemBuilder: (BuildContext context, int index) {
                    List<Widget> children = <Widget>[
                      Text('$index. ${chats[index]}'),
                      Image.asset(
                        'assets/avatar.jpg',
                        width: 30,
                        height: 30,
                      ),
                    ];
                    if (index % 2 == 0) {
                      children = children.reversed.toList();
                    }
                    return Row(
                      mainAxisAlignment: index % 2 == 0
                          ? MainAxisAlignment.start
                          : MainAxisAlignment.end,
                      children: children,
                    );
                  },
                  itemCount: chats.length,
                ),
              )
            ],
          ),
        ),

refresh with code

  • define key
  final GlobalKey<PullToRefreshNotificationState> key =
      new GlobalKey<PullToRefreshNotificationState>();

        PullToRefreshNotification(
          key: key,    
  • use key

if you define pull Container hegith with dragOffset, you need set notificationDragOffset when refresh.

  key.currentState.show(notificationDragOffset: maxDragOffset);
Comments
  • 希望可以开放部分参数

    希望可以开放部分参数

    希望可以开放此参数

    // When the scroll ends, the duration of the refresh indicator's animation // to the RefreshIndicator's displacement. const Duration _kIndicatorSnapDuration = Duration(milliseconds: 150);

    有些需求只是下拉放大图片。

    现在回弹需要等待该时长。

    很怪

    help wanted 
    opened by DizzyDuan 11
  • * add [PullToRefreshNotification] to support automate refresh animati…

    * add [PullToRefreshNotification] to support automate refresh animati…

    • add [PullToRefreshNotification] to support automate refresh animation when call [show] function
    • delete when RefreshIndicatorMode == error ,click retry function. Change to pullback Animation. do not need click. Let use drag again.
    opened by YYwishp 4
  • Show error and dismiss instead of wait for user input

    Show error and dismiss instead of wait for user input

    Hey, Thanks for the awesome package. It would be great if you could add the option to show an error without waiting for user input. Only show error and dismiss after a certain duration delay.

    Thanks

    opened by naamapps 2
  • 为什么我设置的滑动监听,没有反应?

    为什么我设置的滑动监听,没有反应?

    代码如下,打印一直没有输出。

    Scaffold( appBar: new MyAppBar( child: Container( color: Colors.white30, child: Text("Title"), ), ), body: PullToRefreshNotification( onRefresh: _onRefresh, maxDragOffset: 250.0, notificationPredicate: (info) { print("---1----->${info?.metrics?.pixels}"); return true; }, child: CustomScrollView( controller: _scrollControler, slivers: <Widget>[ PullToRefreshContainer((info) { var offset = info?.dragOffset ?? 0.0; return SliverToBoxAdapter( child: Stack( children: <Widget>[ new Container( height: 240 + offset, width: double.infinity, child: Image.asset( "images/img_mine_top_bg.jpg", fit: BoxFit.cover, ), ), ], ), ); }), SliverList( delegate: SliverChildListDelegate(_listItem()), ) ], ), ), );

    opened by qlang122 2
  • 报错'_notificationDragOffset == null': is not true.

    报错'_notificationDragOffset == null': is not true.

    有强迫症,能不让它报错吗

    
    ════════ Exception caught by gesture ═══════════════════════════════════════════════════════════════
    The following assertion was thrown while handling a gesture:
    'package:pull_to_refresh_notification/src/pull_to_refresh_notification.dart': Failed assertion: line 287 pos 12: '_notificationDragOffset == null': is not true.
    
    When the exception was thrown, this was the stack: 
    #2      PullToRefreshNotificationState._start (package:pull_to_refresh_notification/src/pull_to_refresh_notification.dart:287:12)
    #3      PullToRefreshNotificationState._innerhandleScrollNotification (package:pull_to_refresh_notification/src/pull_to_refresh_notification.dart:205:9)
    #4      PullToRefreshNotificationState._handleScrollNotification (package:pull_to_refresh_notification/src/pull_to_refresh_notification.dart:189:25)
    #5      NotificationListener._dispatch (package:flutter/src/widgets/notification_listener.dart:129:41)
    #6      Notification.visitAncestor (package:flutter/src/widgets/notification_listener.dart:47:20)
    ...
    Handler: "onStart"
    Recognizer: VerticalDragGestureRecognizer#395e6
      start behavior: start
    ════════════════════════════════════════════════════════════════════════════════════════════════════
    
    

    我这样用的

    PullToRefreshNotification(
              maxDragOffset: 80.0,
              armedDragUpCancel: false,
              onRefresh: () async {
                return await _purchaseRepository.refresh();
              },
              child: LoadingMoreCustomScrollView(
    
    opened by mdddj 0
  • Nested scroll

    Nested scroll

    Hello! I have a vertical CustomScrollView wrapped with PullToRefreshNotification, and inside CustomScrollView there is a widget with horizontal SingleChildScrollView. Which of them PullToRefreshNotification will be listening to? Does it work correctly? Thanks.

    opened by bonsoirelliot 1
  • 滚动条 jumpTo到顶部 会触发刷新

    滚动条 jumpTo到顶部 会触发刷新

    headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
              return [
                SliverAppBar(
                  // forceElevated: innerBoxIsScrolled,
                  title: Text(widget.title),
                  actions: widget.actions,
                  flexibleSpace: widget.flexibleSpace,
                  expandedHeight: widget.expandedHeight,
                ),
                PullToRefreshContainer((info) => PullToRefreshHeader(info: info)),
                SliverTabBar(
                  child: TabBar(
                    controller: tabController,
                    isScrollable: widget.isScrollable,
                    onTap: (int index) => tabBarOnTap(context, index),
                    tabs: [
                      for (final tab in widget.tabs) Tab(child: Text(tab.name)),
                    ],
                  ),
                  pinned: true,
                ),
              ];
            }
    
    PrimaryScrollController.of(context)!.jumpTo(widget.expandedHeight ?? 0);
    
    opened by git-xiaocao 0
  • Delay pull back

    Delay pull back

    Hey, Currently the refresher pulls back immediately after returning true in the onRefresh function. It would be nice to have a little delay to the pull back, so the user would be able to see the text longer after the refresh is done. Maybe add a delayPullBack property that accepts a duration. Thanks.

    opened by naamapps 2
Releases(v1.5.4-hotfix.2)
Owner
FlutterCandies
Custom Flutter candies (packages) for you to build your Flutter app easily. Enjoy it!
FlutterCandies
🧾 Flutter widget allowing easy cache-based data display in a ListView featuring pull-to-refresh and error banners.

Often, apps just display data fetched from some server. This package introduces the concept of fetchable streams. They are just like normal Streams, b

Marcel Garus 17 Jan 18, 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
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
Add beautiful animated effects & builders in Flutter, via an easy, highly customizable unified API.

Flutter Animate A performant library that makes it simple to add almost any kind of animated effect in Flutter. Pre-built effects, like fade, scale, s

Grant Skinner 352 Dec 25, 2022
An all-in-one Fllutter package for state management, reactive objects, animations, effects, timed widgets etc.

Frideos An all-in-one package for state management, streams and BLoC pattern, animations and timed widgets, effects. Contents 1. State management Gett

Francesco Mineo 188 Dec 23, 2022
A new flutter package project which contains lots of beautiful alert dialog that will help you lot to create beautiful awesome alert box very quickly and easily.

A new flutter package project which contains lots of beautiful alert dialog that will help you lot to create beautiful awesome alert box very quickly and easily.

Karan Soni 8 Jan 8, 2022
Quickly is build as a tool to enhance your Flutter UI development experience and make code easier

Quickly is build as a tool to enhance your Flutter UI development experience and make code easier. It is highly inspired by Bootstrap and Tailwind CSS. It also provide lots of extension methods on String, List and Map.

Aniket Khote 11 Oct 24, 2022
Localize your flutter application quickly and easily.

EzLocalization This package allows you to setup a powerful localization system with ease and in only a few minutes. Features Here are some features: E

Hugo Delaunay 13 Sep 22, 2022
A super powerful widget to help developers build complex views quickly and comfortably.

FSuper FSuper can help developers build complex views quickly and comfortably. It supports rich text, rounded corners, borders, pictures, small red do

Fliggy Mobile 481 Dec 29, 2022
A super powerful widget to help developers build complex views quickly and comfortably.

FSuper FSuper can help developers build complex views quickly and comfortably. It supports rich text, rounded corners, borders, pictures, small red do

Fliggy Mobile 481 Dec 29, 2022
腾讯云 1 Feb 10, 2022
Show beautiful bottom sheet as confirmation dialog quickly and easily.

sweetsheet Show beautiful bottom sheet as confirmation dialog quickly and easily. nice warning success danger and since version 0.2.0 , it is fully cu

Ayao Corneille ALLOGBALO 80 Sep 27, 2022
Flutter qidgets - Build widgets hierarchies quickly with qidgets

Build widgets hierarchies quickly with qidgets. Quick widgets → qidgets. Feature

Edward Patel 1 Mar 31, 2022
Quickly configure three theme styles

flytheme 快速实现三种主题效果。 本插件是从矿小助App中拆分出来的,优化了很多细节,更加简单易用。 内置持久化存储(使用share_preference实现) 矿小助App:https://kxz.atcumt.com/ pub插件地址:https://pub.dev/packages/f

CUMT-Atom 2 Aug 2, 2022
Draggable Scrollbar - A scrollbar that can be dragged for quickly navigation through a vertical list.

A scrollbar that can be dragged for quickly navigation through a vertical list. Additionaly it can show label next to scrollthumb with information about current item, for example date of picture created

Flutter Community 425 Dec 10, 2022
Customizable ScrollBar for quickly navigation.

material_scrollbar This package provides customizable scrollbar for your widget and easy to implement with the few lines of code. Material Scrollbar.

Sahil Hamirani 3 Jul 27, 2022