IntroductionScreen: a first-launch walkthrough for Flutter apps
Add easily to your app an introduction screen to provide informations to new users
At a glance
- What is it?
- IntroductionScreen is a Flutter widget package that renders a paginated onboarding screen built from PageViewModel objects, with optional skip, back and next controls and a separate dots_indicator package for progress dots. Version 5 moved it off flutter/material.dart to the standalone material_ui package, which raises the Flutter and Dart floor for adopters.
- Who is it for?
- IntroductionScreen fits Flutter apps that want a guided first-run walkthrough with per-page images, footers and styled text, and it fits badly if you need the widget to remember that it has already been shown, since persistence is explicitly left to shared_preferences.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 37 days ago.
- What is it written in?
- Mainly Dart, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A first-launch walkthrough assembled from PageViewModel objects
IntroductionScreen is a Dart package published on pub.dev for Flutter applications that need to explain themselves to a new user. The core idea is small enough to state in one line: you hand the widget a list of pages and it renders them as a swipeable carousel with progress dots and a set of navigation controls. Each page is a PageViewModel instance, and each of those carries its own title, body, image, decoration and optional footer.
What separates this from a hand-rolled PageView is the amount of per-page styling that lives in the model rather than in your own build methods. A page can carry its own background color, its own title and body TextStyles, a network image, an asset image, an arbitrary widget as the image slot, a widget instead of a string body, and a footer widget such as a button. The IntroductionScreen widget itself then holds the list plus the navigation configuration, so the page content and the chrome are separated in a way that keeps screen code short.
The package also pulls in dots_indicator, written by the same author, for the row of progress dots at the bottom of the screen. That dependency matters if you plan to restyle those dots, since the styling object you pass in comes from that separate package rather than from IntroductionScreen itself.
PageViewModel holds content, decoration and optional footers per page
The simplest page sets three things, title, body and image, where image accepts any widget:
PageViewModel(
title: "Title of introduction page",
body: "Welcome to the app! This is a description of how it works.",
image: const Center(
child: Icon(Icons.waving_hand, size: 50.0),
),
)Color and typography are handled by the decoration parameter. The page color comes from PageDecoration.pageColor, and titleTextStyle and bodyTextStyle take ordinary TextStyle values:
PageViewModel(
title: "Title of blue page",
body: "Welcome to the app! This is a description on a page with a blue background.",
image: Center(
child: Image.network("https://example.com/image.png", height: 175.0),
),
decoration: const PageDecoration(
pageColor: Colors.blue,
),
)Two escape hatches exist for richer content. bodyWidget accepts a Widget in place of the body string, with titleWidget doing the same for the title, and the documentation is explicit that you use body or bodyWidget, not both. A footer slot accepts any widget, which is how you put a call to action under a page:
PageViewModel(
title: "Title of custom button page",
body: "This is a description on a page with a custom button below.",
image: Image.asset("res/images/logo.png", height: 175.0),
footer: ElevatedButton(
onPressed: () {
// On button pressed
},
child: const Text("Let's Go!"),
),
)Because the model takes widgets rather than asset paths, the package does not dictate an asset pipeline. You supply an Image.asset or an Image.network and handle any missing file or unreachable URL in your own error handling.
Version 5 moved the package off flutter/material.dart onto material_ui
The breaking change in 5.0.0 is the single most important fact for anyone upgrading. The package no longer imports package:flutter/material.dart. It now uses the standalone material_ui package, which means your app must also depend on material_ui, or keep the deprecated MaterialUiCompatibilityBridge in place. The stated requirements are Flutter >=3.44.0 and Dart ^3.12.0, and the CHANGELOG is referenced for the details of the change.
The practical consequence is that this is no longer a drop-in dependency for an app pinned to an older Flutter release. A team on Flutter 3.24 cannot take version 5 without a toolchain upgrade, and a team that wants to avoid the extra dependency can stay on the 4.x line, whose most recent listed release is v4.0.0 from 2025-08-27.
The same change has a side effect worth knowing before you start. Because the material widgets now come from a separate package rather than the Flutter SDK, the widget types you pass in, an ElevatedButton in the footer example above, and the style objects you build must resolve consistently. Mixed imports of Material types across two packages are the sort of thing that shows up as a type error at compile time rather than as a subtle visual glitch, so build early after upgrading.
Adding the dependency and rendering the screen for the first time
Installation is a single line in pubspec.yaml, as the README states:
dependencies:
introduction_screen: ^5.0.1With that in place, the widget needs a list of PageViewModel objects and a done action. The minimal configuration sets pages, disables the Next button, and supplies the done label and its callback:
IntroductionScreen(
pages: listPagesViewModel,
showNextButton: false,
done: const Text("Done"),
onDone: () {
// On button pressed
},
)The Next button is hidden here because no next parameter was given. The same pattern adds a Skip button, in which case both the skip widget and the showSkipButton flag have to be present:
IntroductionScreen(
pages: listPagesViewModel,
showSkipButton: true,
showNextButton: false,
skip: const Text("Skip"),
done: const Text("Done"),
onDone: () {
// On button pressed
},
)A back button works the same way, with showBackButton and a back widget, and the documented behaviour is that it appears on every page except the first one. The Skip button, by contrast, is shown on all pages except the last one. So on a four-page walkthrough the user sees Skip, then Next, then a Done button that you style yourself.
Showing the screen once is left to shared_preferences
This is the limitation most likely to surprise a new user. The README is direct about it: if you want IntroductionScreen to appear only on the first launch, you need shared_preferences or a similar strategy to store whether it has already been displayed, and handling that is not the responsibility of this package. The widget is a view, not a state machine, and it keeps no record of previous runs.
That boundary is a deliberate one rather than an oversight, and it has a cost worth measuring. If you skip persistence entirely, every app start routes through the onboarding screen, which is usually wrong. If you add shared_preferences, your app gains a dependency and a write on first launch, and you must decide what happens on the very first run when the preference key does not exist yet. A typical flow is to check the key at startup, show the intro screen when it is absent, and write the key from the done or skip callback.
The same reasoning applies to analytics. Because the callbacks are plain closures, you can fire your own events from onDone and onSkip, but the package offers no built-in hooks for tracking which page a user abandoned on, and a user who swipes past the last page without pressing Done leaves no trace beyond your own callback wiring.
A small dependency with a fast release line and an MIT licence
IntroductionScreen sits in the category of small, single-purpose Flutter packages, and its maintenance record reflects that. The last push was on 2026-09-16, and that same day saw two releases: v5.0.0 and then v5.0.1 as a follow-up patch. Before that, v4.0.0 was published on 2025-08-27. There is a gap of about a year between the 4.x major and the 5.x major, which suggests work concentrated around the breaking material_ui change rather than a steady drip of patches.
The repository contains a demo directory, an example directory, a test directory, an analysis_options.yaml and CI workflows for building the example app and running the project tests, so the package does carry automated checks. The licence is MIT, which is permissive and is the standard choice for a package of this size. As always, the MIT grant covers the package code only, and it says nothing about the content you show on the onboarding pages.
The comparison to draw is with writing the carousel yourself. A bare PageView with a dot row and a Done button is a hundred lines or so of your own code, which you get for free and which you also have to maintain. IntroductionScreen earns its place when you want per-page decoration, footers, and title or body widgets without maintaining that layer, and it loses when you need a first-run flag, a different animation, or a design system that Flutter material widgets do not express.
Editorial conclusion
IntroductionScreen fits Flutter apps that want a guided first-run walkthrough with per-page images, footers and styled text, and it fits badly if you need the widget to remember that it has already been shown, since persistence is explicitly left to shared_preferences. Before upgrading from a 4.x release, confirm that your app also depends on material_ui or on the deprecated MaterialUiCompatibilityBridge, and check that your Flutter version is at least 3.44.0 and your Dart version is at least 3.12.0, because v5.0.0 changed the underlying material package.
Frequently asked questions
How do I install IntroductionScreen in a Flutter app?
Add it as a dependency in pubspec.yaml. The README gives the dependency block as introduction_screen: ^5.0.1.
What Flutter and Dart versions does IntroductionScreen 5 require?
Version 5.0.0 requires Flutter >=3.44.0 and Dart ^3.12.0, because the package switched from package:flutter/material.dart to the standalone material_ui package. Apps may also keep the deprecated MaterialUiCompatibilityBridge.
How can I show IntroductionScreen only on the first app launch?
Use shared_preferences or a similar approach to record whether the screen has already been displayed. The README states this is not the responsibility of the package, so the widget itself keeps no memory of past runs.
Why is the Next button missing in IntroductionScreen?
The Next button is not displayed if the next parameter is not provided, and showNextButton must then be set to false. The Skip button needs both a skip widget and showSkipButton set to true, and the done parameter is only required when showDoneButton is true.
Can I put a button under a page in IntroductionScreen?
Yes. Each PageViewModel has a footer parameter that accepts any widget, such as an ElevatedButton with your own onPressed handler, and the body of a page can also be a widget through bodyWidget instead of a string.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pyozer-introduction-screen)Was this useful?