Onboarding View
A modern, highly customizable onboarding package for Flutter.
Five ready-made looks β glassmorphism, Apple liquid glass, minimal, material and adaptive β with rich page & indicator animations, network / GIF / asset / icon / custom media, and zero-dependency local persistence. Runs on mobile, desktop and web.
π Live demo
Try every style right in your browser: π torchingale.com/packages/onboarding-view/index.html
Pick a style on the left and preview it live inside a phone mockup on the right.
Contents
- Features
- Install
- Quick start
- Show onboarding only once
- Styles
- Media types
- Page transitions
- Indicators
- Theming
- Persistence
- Custom buttons & builders
- Controlling the flow
- Desktop & web
- API overview
- Example app
Features
- π¨ Five built-in styles (
OnboardingStyle) β or craft your ownOnboardingTheme. - πΌοΈ Any media β
OnboardingMedia.network(with loading/error states),.gif,.asset,.icon,.custom. - π Page transitions β fade, scale, parallax, cube, depth. Driven by the live swipe position, with a shared "connected gradient" background so pages feel linked.
- β Animated indicators β dots, expanding, worm, scale, line/progress (tappable).
- ποΈ Fully customizable β builder hooks for skip/back/next/finish + the indicator, configurable labels, button variants, layout ratios, blur/opacity.
- πΎ Local persistence, no dependencies β a JSON file on device (web falls back to memory), with a runtime on/off toggle and callbacks for your own storage.
- β¨οΈ Desktop & web ready β responsive wide layout and β / β keyboard navigation.
- π¦ Zero dependencies β pure Flutter/Dart (
BackdropFilter,Image,dart:io).
Install
dependencies:
onboarding_view: ^1.0.1
import 'package:onboarding_view/onboarding_view.dart';
Requires Flutter >=3.27.0 (uses Color.withValues).
Quick start
The whole flow is two widgets: OnboardingView (the flow) and a list of
OnboardingPage (plain data β the theme handles the visuals).
OnboardingView(
style: OnboardingStyle.glassmorphism, // pick a look
storageKey: 'seen_intro', // remembers completion (JSON file)
onFinish: () => Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (_) => const HomeScreen()),
),
pages: const [
OnboardingPage(
title: 'Welcome aboard',
description: 'Everything you need, in one beautiful place.',
media: OnboardingMedia.network('https://picsum.photos/600'),
),
OnboardingPage(
title: 'Any media you want',
description: 'Images, GIFs, icons or custom widgets.',
media: OnboardingMedia.gif('https://example.com/intro.gif'),
),
OnboardingPage(
title: 'You are all set',
description: 'Tap get started to jump in.',
media: OnboardingMedia.icon(Icons.rocket_launch),
),
],
);
That's it. Skip / back / next / finish buttons, the animated indicator, page
transitions and the background are all wired up by the chosen style.
Show onboarding only once
Check completion at startup and route accordingly:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final seen = await OnboardingView.hasCompleted('seen_intro');
runApp(MyApp(showOnboarding: !seen));
}
When the user finishes (or skips, if completeOnSkip is true β the default),
the key is written to storage automatically.
Styles
Each OnboardingStyle maps to a fully-formed theme. Preview them all in the
live demo.
| Style | Look | Default transition | Default indicator |
|---|---|---|---|
glassmorphism |
Frosted translucent cards over a vivid gradient | parallax | expanding |
liquidGlass |
Apple-style heavy blur, sheen & springy motion | depth | worm |
minimal |
Flat, typography-first | fade | line/progress |
material |
Material 3, filled buttons | scale | expanding |
adaptive |
Responsive layout + keyboard nav for desktop/web | parallax | scale |
You can pass a style or a fully custom theme (see Theming).
Media types
OnboardingMedia is the hero visual at the top of each page:
OnboardingMedia.asset('assets/intro.png'); // bundled image (or GIF)
OnboardingMedia.network('https://β¦/photo.jpg'); // remote image, with
// loading + error states
OnboardingMedia.gif('https://β¦/anim.gif'); // network GIF (or isAsset:true)
OnboardingMedia.icon(Icons.rocket_launch); // Material icon
OnboardingMedia.custom(MyLottieOrRiveWidget()); // literally anything
Network media shows a progress spinner while loading and a graceful fallback on
error β override both with placeholder: / errorWidget:.
Page transitions
Set transition: on OnboardingView (or in the theme). Every effect is driven
by the live scroll position, so pages stay visually connected instead of
animating in isolation:
OnboardingTransition.none Β· fade Β· scale Β· parallax Β· cube Β· depth
Styles that define connectedGradientColors also blend the background color
between pages as you swipe β the flow reads as one continuous surface.
Indicators
Configure via IndicatorConfig (colors, sizes, spacing). Effects:
IndicatorEffect.dots Β· expanding Β· worm Β· scale Β· line
The indicator sits on its own row above the buttons, is tappable (jumps to a page), and animates smoothly with the swipe.
theme: OnboardingTheme.fromStyle(OnboardingStyle.material).copyWith(
indicator: const IndicatorConfig(
effect: IndicatorEffect.worm,
activeColor: Colors.teal,
dotSize: 10,
spacing: 8,
),
),
Theming
Start from a preset and tweak anything with copyWith, or build an
OnboardingTheme from scratch:
final theme = OnboardingTheme.fromStyle(
OnboardingStyle.material,
brightness: Brightness.dark,
seedColor: Colors.teal,
).copyWith(
accentColor: Colors.teal,
transition: OnboardingTransition.parallax,
indicator: const IndicatorConfig(effect: IndicatorEffect.worm),
buttons: const OnboardingButtonConfig(
variant: OnboardingButtonVariant.tonal,
finishLabel: "Let's go",
borderRadius: 24,
),
animation: const OnboardingAnimationConfig(
pageDuration: Duration(milliseconds: 500),
pageCurve: Curves.easeOutCubic,
),
mediaFlex: 5, // media vs text height ratio
textFlex: 4,
glassBlur: 24,
glassOpacity: 0.14,
);
OnboardingView(theme: theme, onFinish: ..., pages: ...);
Per-page overrides live on OnboardingPage (backgroundColor,
backgroundGradient, foregroundColor, accentColor, or a full
contentBuilder escape hatch).
Persistence
Persistence is dependency-free. By default, state is written to a local JSON
file (JsonFileOnboardingStorage); on the web it transparently falls back to
MemoryOnboardingStorage.
final storage = OnboardingStorage.defaultStorage();
OnboardingView(
storage: storage,
storageKey: 'seen_intro',
persistenceEnabled: true, // master on/off toggle
onCompleted: (key) => log('done: $key'), // bring-your-own hook
onFinish: ...,
pages: ...,
);
// Flip persistence at runtime (e.g. from a settings switch):
storage.persistenceEnabled = false;
// Read / clear:
final seen = await storage.isCompleted('seen_intro');
await storage.reset('seen_intro');
Custom backend (Hive, SQLite, a REST APIβ¦): extend OnboardingStorage and
pass it as storage:.
class MyStorage extends OnboardingStorage {
@override
Future<bool> isCompleted(String key) async => /* your read */;
@override
Future<void> setCompleted(String key, {bool value = true}) async { /* write */ }
// β¦reset / readAll / writeAll
}
Custom buttons & builders
Replace any piece of chrome without touching the rest:
OnboardingView(
skipBuilder: (ctx, c) => TextButton(onPressed: c.skipToEnd, child: const Text('Skip')),
backBuilder: (ctx, c) => IconButton(onPressed: c.back, icon: const Icon(Icons.chevron_left)),
nextBuilder: (ctx, c) => IconButton(onPressed: c.next, icon: const Icon(Icons.chevron_right)),
finishBuilder:(ctx, c) => FilledButton(onPressed: () {}, child: const Text('Done')),
indicatorBuilder: (ctx, c) => MyCustomIndicator(controller: c),
onFinish: ...,
pages: ...,
);
Or just change labels/variants via OnboardingButtonConfig in the theme.
Controlling the flow
Pass your own OnboardingController to drive navigation from outside:
final controller = OnboardingController();
// β¦
controller.next();
controller.back();
controller.animateToPage(2);
controller.skipToEnd();
controller.progress; // 0..1
controller.isLast;
OnboardingView(controller: controller, onFinish: ..., pages: ...);
Desktop & web
- Responsive: above
wideLayoutBreakpoint(default 720px) the layout switches to a side-by-side media/text arrangement. - Keyboard: β / β and Page Up/Down navigate pages (
enableKeyboardNavigation). - Content scrolls internally on short screens, so it never overflows.
API overview
| Type | Purpose |
|---|---|
OnboardingView |
The flow widget |
OnboardingPage |
Per-page data (title, description, media, overrides) |
OnboardingMedia |
.asset / .network / .gif / .icon / .custom |
OnboardingStyle |
Preset look |
OnboardingTheme |
Full visual config (fromStyle, copyWith) |
OnboardingButtonConfig |
Button labels, variant, shape |
IndicatorConfig / IndicatorEffect |
Indicator look & animation |
OnboardingTransition |
Page transition effect |
OnboardingAnimationConfig |
Durations & curves |
OnboardingController |
External navigation control |
OnboardingStorage |
Persistence interface (JsonFileOnboardingStorage, MemoryOnboardingStorage) |
GlassContainer |
Reusable frosted-glass surface |
Example app
The example/ app is the same web showcase as the live demo:
a style picker on the left, a live phone preview on the right.
cd example
flutter run -d chrome # or any device
License
MIT
Libraries
- onboarding_view
- A modern, highly customizable onboarding package for Flutter.