simple_parallax 1.2.0
simple_parallax: ^1.2.0 copied to clipboard
Parallax widgets for Flutter, with a container mode and a per-item mode, vertical or horizontal. Pure Dart, no dependencies, any ImageProvider.
Simple Parallax #
Parallax widgets for Flutter, in pure Dart. Two modes, either axis, any ImageProvider, and no
dependencies beyond the Flutter SDK.
Container mode above, item mode below; scrolling down on the left, sideways on the right.
Install #
flutter pub add simple_parallax
Requires Flutter 3.22 or later.
Container mode #
One background drifting behind a scrolling area. autoSpeed derives the speed from the real scroll
extent, so the background uses exactly the travel overscan gives it and never runs out of image:
SimpleParallaxContainer(
image: const AssetImage('assets/images/background.webp'),
autoSpeed: true,
overscan: 1.5,
child: Column(children: items),
);
| Parameter | Default | Effect |
|---|---|---|
image |
required | Any ImageProvider: asset, network, file or memory. |
child |
required | The scrolling content, laid out as a single box sliver. |
slivers |
required | The scrolling content as slivers, on the .slivers constructor. |
scrollDirection |
Axis.vertical |
The axis the content scrolls and the background drifts along. |
speed |
0.3 |
Background travel per pixel scrolled. Ignored when autoSpeed is set. |
autoSpeed |
false |
Derives the speed from the scroll extent. |
overscan |
1.5 |
How much larger than the viewport the background is drawn along the scroll axis. |
height |
null |
Forces the viewport height instead of using the constraints. |
width |
null |
Forces the viewport width instead of using the constraints. |
fit |
BoxFit.cover |
How the background fills its layer. |
alignment |
Alignment.center |
How the background sits inside its layer. |
Slivers #
The container is a CustomScrollView, and child is put in a single box sliver. Use the
.slivers constructor instead to hand it the slivers yourself, so the content builds as it scrolls
and other slivers can ride over the background:
SimpleParallaxContainer.slivers(
image: const AssetImage('assets/images/background.webp'),
autoSpeed: true,
slivers: <Widget>[
const SliverAppBar(title: Text('Chapters'), floating: true),
SliverList.builder(
itemCount: 500,
itemBuilder: (BuildContext context, int index) =>
ListTile(title: Text('Chapter $index')),
),
],
);
Everything else behaves the same: the background still drifts along scrollDirection, and
autoSpeed still reads the real scroll extent. On a long list, prefer a fixed speed: autoSpeed
spreads the travel overscan allows over the whole extent, so the drift becomes imperceptible.
Item mode #
Each block slides its own background as it crosses the viewport. The item finds the enclosing
Scrollable by itself, so it works in a ListView, a CustomScrollView, or anything else that
scrolls:
ListView(
children: <Widget>[
SimpleParallaxItem(
image: const NetworkImage('https://example.com/cover.jpg'),
height: 300,
child: const Center(child: Text('Chapter one')),
),
],
);
| Parameter | Default | Effect |
|---|---|---|
image |
required | Any ImageProvider. |
child |
null |
Content drawn over the background. |
speed |
1.0 |
Fraction of the available travel used, from 0 to 1. |
overscan |
1.5 |
How much larger than the item the background is drawn along the scroll axis. |
height |
screen height, or constraints when horizontal | Item height. |
width |
constraints, or screen width when horizontal | Item width. |
fit |
BoxFit.cover |
How the background fills its layer. |
SimpleParallaxWidget is a convenience scroll view for a list of items. It is a CustomScrollView
over one SliverList, so the blocks build as they come into view and each one is laid out across
the full cross axis, the way a ListView lays its children out.
SimpleParallaxWidget(
children: <Widget>[
const SimpleParallaxItem(image: AssetImage('assets/a.webp'), height: 300),
Container(height: 400, color: Colors.blueGrey),
],
);
Scrolling sideways #
Both modes work on either axis. The container takes a scrollDirection, exactly like a
ListView:
SimpleParallaxContainer(
image: const AssetImage('assets/images/background.webp'),
scrollDirection: Axis.horizontal,
autoSpeed: true,
child: Row(children: items),
);
An item has nothing to pass: it reads the axis from the scrollable it sits in, so dropping it into a
horizontal list is enough. Give it a width there, the way you give it a height in a vertical one:
ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
SimpleParallaxItem(
image: const AssetImage('assets/images/background.webp'),
width: 300,
child: const Center(child: Text('Chapter one')),
),
],
);
SimpleParallaxWidget takes the same scrollDirection and lays its blocks out along that axis.
How it performs #
Scrolling repaints the background and nothing else. In container mode the moving layer sits behind a
RepaintBoundary and only its transform is rebuilt, so your content is built once. In item mode the
background is painted by a Flow bound directly to the scroll position, which repaints without
rebuilding a single widget.
Both scroll views are CustomScrollViews, so content handed over as slivers is built only as far as
the viewport reaches.
Migrating from 0.1.x #
| Before | Now |
|---|---|
imagePath: 'assets/a.webp' |
image: AssetImage('assets/a.webp') |
decal: 1.5 |
overscan: 1.5 |
SimpleParallaxItem(speed: 0.3) |
speed is a 0..1 fraction now, default 1.0 |
SimpleParallaxItem only inside SimpleParallaxWidget |
works inside any scrollable |
autoSpeed needed a GlobalKey on your child |
nothing to pass |
The package is no longer a Flutter plugin: the native platform folders are gone, and so is the
provider dependency.
Dependencies #
None beyond the Flutter SDK.
Example #
example/ is one app with four screens, one per combination: container mode and item mode, each
vertical and horizontal.
cd example && flutter run
Tests #
flutter test
License #
MIT, see LICENSE.
