Skip to content

QuangNH0606/smart_scroll

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

21 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Smart Scroll

pub package pub points License: MIT

πŸ“¦ pub.dev: https://pub.dev/packages/smart_scroll

A powerful Flutter widget for pull-to-refresh and infinite scroll (load more / pagination). Works seamlessly with ListView, GridView, CustomScrollView, and any scrollable widget.

Reuse flutter_pulltorefresh by peng8350, due to issue related to updating version dart.

✨ Features

  • ↕️ Pull down to refresh & pull up to load more
  • 🎨 Multiple built-in indicators β€” Material, Cupertino, WaterDrop, Bezier, Classic, Shimmer
  • πŸ”„ Platform-adaptive headers/footers β€” PlatformHeader & PlatformFooter auto-detect iOS/Android
  • πŸ› οΈ Custom indicator builder β€” full control with BuilderHeader / BuilderFooter
  • 🌐 Horizontal & vertical scrolling, including reverse scroll direction
  • βš™οΈ Global configuration via RefreshConfiguration (shared across all pages)
  • 🌍 Localization support for indicator text
  • πŸ“± Cross-platform: iOS, Android, Web, Desktop

πŸ“¦ Installation

Add to your pubspec.yaml:

dependencies:
  smart_scroll: ^1.0.2

Then run:

flutter pub get

πŸš€ Quick Start

import 'package:smart_scroll/smart_scroll.dart';

class MyPage extends StatefulWidget {
  @override
  State<MyPage> createState() => _MyPageState();
}

class _MyPageState extends State<MyPage> {
  final RefreshController _refreshController =
      RefreshController(initialRefresh: false);
  List<String> items = List.generate(10, (i) => 'Item ${i + 1}');

  void _onRefresh() async {
    await Future.delayed(const Duration(seconds: 1));
    _refreshController.refreshCompleted();
  }

  void _onLoading() async {
    await Future.delayed(const Duration(seconds: 1));
    setState(() {
      items.add('Item ${items.length + 1}');
    });
    _refreshController.loadComplete();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SmartScroll(
        enablePullDown: true,
        enablePullUp: true,
        header: const WaterDropHeader(),
        controller: _refreshController,
        onRefresh: _onRefresh,
        onLoading: _onLoading,
        child: ListView.builder(
          itemCount: items.length,
          itemBuilder: (context, index) => ListTile(title: Text(items[index])),
        ),
      ),
    );
  }
}

🎨 Built-in Indicators

Refresh Headers

Classic WaterDrop Material
Classic WaterDrop Material
Material WaterDrop Shimmer Bezier + Circle
Material WaterDrop Shimmer Bezier

Refresh Styles

RefreshStyle.Follow RefreshStyle.UnFollow RefreshStyle.Behind RefreshStyle.Front
Follow UnFollow Behind Front

Load More Styles

LoadStyle.ShowAlways LoadStyle.HideAlways LoadStyle.ShowWhenLoading
ShowAlways HideAlways ShowWhenLoading

πŸ“Έ Examples

Basic Link Header Reverse + Horizontal
Basic Link Header Reverse
Two Level Other Widgets Chat List
Two Level Other Widgets Chat
Custom Header (SpinKit) DraggableSheet + LoadMore GIF Indicator
SpinKit DraggableSheet GIF

βš™οΈ Global Configuration

Use RefreshConfiguration at the root of your app to set defaults for all SmartScroll widgets:

RefreshConfiguration(
  headerBuilder: () => const WaterDropHeader(),
  footerBuilder: () => const ClassicFooter(),
  headerTriggerDistance: 80.0,
  maxOverScrollExtent: 100,
  maxUnderScrollExtent: 0,
  enableScrollWhenRefreshCompleted: true,
  enableLoadingWhenFailed: true,
  hideFooterWhenNotFull: false,
  enableBallisticLoad: true,
  child: MaterialApp(
    // ...
  ),
);

πŸ› οΈ Custom Indicator (Builder API)

Build fully custom refresh/load indicators using BuilderHeader and BuilderFooter:

SmartScroll(
  header: BuilderHeader(
    builder: (context, data) {
      return Container(
        height: 60,
        alignment: Alignment.center,
        child: Text(
          data.triggered ? 'Release to refresh' : 'Pull down...',
          style: TextStyle(
            color: Colors.grey,
            fontSize: 14,
          ),
        ),
      );
    },
  ),
  // ...
);

🌍 Localization

MaterialApp(
  localizationsDelegates: [
    RefreshLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalMaterialLocalizations.delegate,
  ],
  supportedLocales: const [
    Locale('en'),
    Locale('zh'),
  ],
);

⚠️ Important: Child Widget Rules

SmartScroll works best when its child is a direct ScrollView (ListView, GridView, CustomScrollView).

// βœ… Correct
ScrollBar(
  child: SmartScroll(
    child: ListView(...),
  ),
)

// ❌ Wrong β€” don't wrap ScrollView before passing to SmartScroll
SmartScroll(
  child: ScrollBar(
    child: ListView(...),
  ),
)
// ❌ Wrong β€” don't hide ScrollView inside another widget
SmartScroll(
  child: MyCustomWidget(), // contains ListView internally
)

πŸ“‹ API Reference

SmartScroll Properties

Property Type Description
child Widget The scrollable content (ListView, GridView, etc.)
controller RefreshController Controls refresh/load state
header Widget? Custom refresh header indicator
footer Widget? Custom load-more footer indicator
enablePullDown bool Enable pull-down-to-refresh (default: true)
enablePullUp bool Enable pull-up-to-load-more (default: false)
onRefresh VoidCallback? Called when pull-down refresh is triggered
onLoading VoidCallback? Called when pull-up load-more is triggered

RefreshController Methods

Method Description
refreshCompleted() Notify refresh is done
refreshFailed() Notify refresh failed
loadComplete() Notify load-more is done
loadFailed() Notify load-more failed
loadNoData() Notify no more data to load
resetNoData() Reset no-data state

πŸ› Known Issues

  • NestedScrollView: Quick scroll direction changes may cause bounce-back due to Flutter's BouncingScrollPhysics handling. Related Flutter issues: #34316, #33367, #29264.
  • AnimatedList / ReorderableListView: Not directly supported as child. Use SliverAnimatedList inside a CustomScrollView instead.

πŸ™ Credits

πŸ“„ License

MIT License β€” see LICENSE for details.

About

Libraries help simplify working with lists

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages