silky_scroll 2.6.0 copy "silky_scroll: ^2.6.0" to clipboard
silky_scroll: ^2.6.0 copied to clipboard

Silky Scroll is a package developed in Flutter to provide a smooth scrolling experience.

Silky Scroll #

SilkyScroll is a Flutter package that provides natural and smooth scroll animations for mouse wheel, trackpad, and touch inputs.

✨ SilkyScroll vs ↔ Default comparison

✨ SilkyScroll   ↔   Default


Features #

  • Smooth Scroll Animation — Interpolates mouse wheel input for seamless scrolling
  • Smart Input Detection — Automatically detects mouse, trackpad, and touch to apply appropriate physics
  • Edge Locking & Nested Forwarding — Locks scrolling at boundaries and automatically forwards touch/trackpad deltas to the parent scroll view
  • Stretch Effect — Supports Android stretch and iOS bounce overscroll effects
  • Horizontal Scroll — Supports both horizontal and vertical directions
  • Preset Widgets — Drop-in SilkyListView, SilkyGridView, SilkyCustomScrollView, SilkySingleChildScrollView with zero boilerplate
  • All Platforms — Android, iOS, Web, Windows, macOS, Linux

Getting Started #

flutter pub add silky_scroll

Basic Usage #

Simply wrap your scrollable widget with SilkyScroll.

SilkyScroll(
  builder: (context, controller, physics, pointerDeviceKind) => ListView(
    controller: controller,
    physics: physics,
    children: [...],
  ),
)

Preset Widgets #

Preset widgets are drop-in replacements for Flutter's scrollable widgets. They eliminate the builder boilerplate by automatically wiring controller and physics internally.

Preset Widget Wraps
SilkyListView ListView
SilkyListView.builder ListView.builder
SilkyListView.separated ListView.separated
SilkyGridView GridView
SilkyGridView.builder GridView.builder
SilkyGridView.count GridView.count
SilkyGridView.extent GridView.extent
SilkyCustomScrollView CustomScrollView
SilkySingleChildScrollView SingleChildScrollView

Before (builder pattern) #

SilkyScroll(
  builder: (context, controller, physics, _) => ListView.builder(
    controller: controller,
    physics: physics,
    itemCount: 100,
    itemBuilder: (context, i) => ListTile(title: Text('Item $i')),
  ),
)

After (preset) #

SilkyListView.builder(
  itemCount: 100,
  itemBuilder: (context, i) => ListTile(title: Text('Item $i')),
)

SilkyCustomScrollView #

SilkyCustomScrollView(
  slivers: [
    SliverAppBar(title: Text('Header')),
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (context, i) => ListTile(title: Text('Item $i')),
        childCount: 50,
      ),
    ),
  ],
)

SilkySingleChildScrollView #

SilkySingleChildScrollView(
  padding: EdgeInsets.all(16),
  child: Column(children: [...]),
)

Customizing SilkyScroll behavior #

Preset widgets accept all SilkyScroll parameters directly, or via a shared SilkyScrollConfig:

// Individual parameters
SilkyListView.builder(
  scrollSpeed: 1.5,
  animationCurve: Curves.easeOutCubic,
  itemCount: 100,
  itemBuilder: (context, i) => Text('$i'),
)

// Shared config (overrides individual parameters when provided)
final config = SilkyScrollConfig(scrollSpeed: 1.5);

SilkyListView.builder(
  silkyConfig: config,
  itemCount: 100,
  itemBuilder: (context, i) => Text('$i'),
)

Detecting pointer device kind #

SilkyListView.builder(
  itemCount: 100,
  itemBuilder: (context, i) => Text('$i'),
  onPointerDeviceKindChanged: (kind) {
    // PointerDeviceKind.mouse, .trackpad, .touch
  },
)

Custom Usage #

You can connect an external ScrollController and fine-tune animation properties.

class _ScrollExampleState extends State<ScrollExample> {
  late final ScrollController _scrollController;

  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SilkyScroll(
        controller: _scrollController,
        physics: const BouncingScrollPhysics(),
        silkyScrollDuration: const Duration(milliseconds: 2000),
        scrollSpeed: 1.5,
        animationCurve: Curves.easeOutQuart,
        direction: Axis.vertical,
        builder: (context, controller, physics, pointerDeviceKind) {
          return ListView.builder(
            controller: controller,
            physics: physics,
            itemCount: 50,
            itemBuilder: (context, index) => ListTile(title: Text('Item $index')),
          );
        },
      ),
    );
  }
}

Using SilkyScrollConfig #

You can share the same configuration across multiple SilkyScroll widgets.

const config = SilkyScrollConfig(
  silkyScrollDuration: Duration(milliseconds: 1000),
  scrollSpeed: 1.5,
  animationCurve: Curves.easeOutCubic,
  enableStretchEffect: true,
);

SilkyScroll.fromConfig(
  config: config,
  builder: (context, controller, physics, pointerDeviceKind) => ListView(...),
)

Web: Overscroll Behavior Control #

On web, SilkyScroll automatically sets overscroll-behavior-x: none while the widget is mounted (controlled by the blockWebOverscrollBehaviorX parameter, default true). This blocks browser back/forward swipe gestures.

When all SilkyScroll widgets with blocking enabled are disposed, the CSS is automatically restored to auto.

Per-widget control #

// Disable browser swipe blocking for this widget
SilkyScroll(
  blockWebOverscrollBehaviorX: false,
  builder: (context, controller, physics, pointerDeviceKind) => ListView(...),
)

Global control #

You can also set a global block flag that persists independently of widgets:

import 'package:silky_scroll/silky_scroll.dart';

// Force block browser swipe gestures globally
SilkyScrollGlobalManager.instance
    .setBlockOverscrollBehaviorX(true);

// Remove the global block (widgets may still block individually)
SilkyScrollGlobalManager.instance
    .setBlockOverscrollBehaviorX(false);

The actual CSS is set to none when any widget requests blocking or the global flag is true. It reverts to auto only when both are inactive.

On non-web platforms this is a no-op.


Parameters #

Parameter Type Default Description
controller ScrollController? null External scroll controller
silkyScrollDuration Duration 850ms Scroll animation duration
scrollSpeed double 1 Scroll speed multiplier
animationCurve Curve Curves.easeOutQuart Animation curve
direction Axis vertical Scroll direction
physics ScrollPhysics ScrollPhysics() Scroll physics
edgeLockingDelay Duration 650ms Lock delay after reaching edge
overScrollingLockingDelay Duration 700ms Overscroll lock delay
enableStretchEffect bool true Overscroll stretch effect
edgeForwardingMode EdgeForwardingMode EdgeForwardingMode.sameAxisOnly Edge delta forwarding to ancestor
decayLogFactor double 12 Smooth-scroll convergence speed
blockWebOverscrollBehaviorX bool true Block browser swipe on web
setManualPointerDeviceKind Function? null Manual pointer device override
onScroll Function(double)? null Scroll event callback
onEdgeOverScroll Function(double)? null Edge overscroll callback
debugMode bool false Debug logging

License #

MIT

4
likes
160
points
667
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Silky Scroll is a package developed in Flutter to provide a smooth scrolling experience.

Repository (GitHub)
View/report issues

Topics

#scroll #smooth-scroll #animation #widget

License

MIT (license)

Dependencies

flutter, flutter_web_plugins, web

More

Packages that depend on silky_scroll