pull_to_refresh_notification 0.3.4

  • Readme
  • Changelog
  • Example
  • Installing
  • 90

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) {
        print(info?.mode);
        print(info?.dragOffset);
    //    print("------------");
        var action = Padding(
          child: info?.refreshWiget ?? 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,
                )));
      }

see demo

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) {
     //print(info?.mode);
     //print(info?.dragOffset);
 //    print("------------");
     var offset = info?.dragOffset ?? 0.0;
     var mode = info?.mode;
     Widget refreshWiget = Container();
     //it should more than 18, so that RefreshProgressIndicator can be shown fully
     if (info?.refreshWiget != null &&
         offset > 18.0 &&
         mode != RefreshIndicatorMode.error) {
       refreshWiget = info.refreshWiget;
     }
 
     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>[
             refreshWiget,
             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,
     );
   }
 
   bool success = false;
   Future<bool> onRefresh() {
     final Completer<bool> completer = new Completer<bool>();
     new Timer(const Duration(seconds: 2), () {
       completer.complete(success);
       success = true;
     });
     return completer.future.then((bool success) {
       if (success) {
         setState(() {
           listlength += 10;
         });
       }
       return success;
     });
   }

see demo

Sample 3 image #

build zoom image to pull to refresh with using PullToRefreshContainer.

 Widget build(BuildContext context) {
     // TODO: implement build
     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 refreshWiget = Container();
     if (info?.refreshWiget != null) {
       refreshWiget = Material(
         type: MaterialType.circle,
         color: Theme.of(context).canvasColor,
         elevation: 2.0,
         child: Padding(
           padding: EdgeInsets.all(12),
           child: info.refreshWiget,
         ),
       );
     }
 
     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>[
                 refreshWiget,
                 Container(
                   padding: EdgeInsets.only(left: 5.0),
                   alignment: Alignment.center,
                   child: Text(
                     info?.mode?.toString() ?? "",
                     style: TextStyle(fontSize: 12.0, inherit: false),
                   ),
                 )
               ],
             ),
           )
         ],
       ),
     );
   }

see demo

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);
              },
            ),
          )
        ],
      ),
    );
  }

see demo

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);

[0.3.4] #

  • web support

[0.3.3] #

  • add candies pull to refresh demo
  • add readme-zh

[0.3.2] #

  • allow custom curve to be passed to the widget for the pullback animation

[0.3.1] #

  • fix api error base on v1.7.8

[0.3.0] #

  • fix issue that AlwaysScrollableClampingScrollPhysics is not working in new flutter version

[0.2.4] #

  • add notificationDragOffset parameter for show method in PullToRefreshNotificationState it's used to change offset when call refresh by coding
  • show how to call refresh by coding

[0.2.3] #

  • add AlwaysScrollableClampingScrollPhysics in case list is not full screen and remove ios Bouncing.

[0.2.0] #

  • add armedDragUpCancel property. //Dragged far enough that an up event will run the onRefresh callback. //when use drag up,whether should cancel refresh final bool armedDragUpCancel;

[0.1.5] #

  • Format code.

[0.1.4] #

  • Remove dead code.

[0.1.3] #

  • Fix issue in case negative value of _dragOffset

[0.1.2] #

  • Fix issue in case notification.depth != 0

[0.1.1] #

  • Fix threshold to refresh not right when set maxDragOffset

[0.1.0] #

  • Upgrade Some Commments.

[0.0.1] #

  • Initial Open Source release.

example/lib/main.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_candies_demo_library/flutter_candies_demo_library.dart';
import 'example_route.dart';
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'extended image demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      builder: (c, w) {
        ScreenUtil.init(width: 750, height: 1334, allowFontScaling: true);
        // ScreenUtil.instance =
        //     ScreenUtil(width: 750, height: 1334, allowFontScaling: true)
        //       ..init(c);
        if (!kIsWeb) {
          final data = MediaQuery.of(c);
          return MediaQuery(
            data: data.copyWith(textScaleFactor: 1.0),
            child: w,
          );
        }
        return w;
      },
      initialRoute: "fluttercandies://mainpage",
      onGenerateRoute: (RouteSettings settings) {
        var routeName = settings.name;
        //when refresh web, route will as following
        //   /
        //   /fluttercandies:
        //   /fluttercandies:/
        //   /fluttercandies://mainpage

        if (kIsWeb && routeName.startsWith('/')) {
          routeName = routeName.replaceFirst('/', '');
        }

        var routeResult =
            getRouteResult(name: routeName, arguments: settings.arguments);

        var page = routeResult.widget ??
            getRouteResult(
                    name: 'fluttercandies://mainpage',
                    arguments: settings.arguments)
                .widget;

        final platform = Theme.of(context).platform;
        switch (routeResult.pageRouteType) {
          case PageRouteType.material:
            return MaterialPageRoute(settings: settings, builder: (c) => page);
          case PageRouteType.cupertino:
            return CupertinoPageRoute(settings: settings, builder: (c) => page);
          case PageRouteType.transparent:
            return platform == TargetPlatform.iOS
                ? TransparentCupertinoPageRoute(
                    settings: settings, builder: (c) => page)
                : TransparentMaterialPageRoute(
                    settings: settings, builder: (c) => page);
//            return FFTransparentPageRoute(
//                settings: settings,
//                pageBuilder: (BuildContext context, Animation<double> animation,
//                        Animation<double> secondaryAnimation) =>
//                    page);
          default:
            return platform == TargetPlatform.iOS
                ? CupertinoPageRoute(settings: settings, builder: (c) => page)
                : MaterialPageRoute(settings: settings, builder: (c) => page);
        }
      },
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  pull_to_refresh_notification: ^0.3.4

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:pull_to_refresh_notification/pull_to_refresh_notification.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
80
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
90
Learn more about scoring.

We analyzed this package on May 24, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.1
  • pana: 0.13.8-dev
  • Flutter: 1.17.0

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0-dev.68.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.12
meta 1.1.8
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
flutter_test