Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/pyozer/introduction_screen

Add easily to your app an introduction screen to provide informations to new users
https://github.com/pyozer/introduction_screen

android dart dart2 flutter introduction ios ui

Last synced: 2 days ago
JSON representation

Add easily to your app an introduction screen to provide informations to new users

Awesome Lists containing this project

README

        

# IntroductionScreen [![pub package](https://img.shields.io/pub/v/introduction_screen.svg)](https://pub.dartlang.org/packages/introduction_screen)

[![Build Example App](https://github.com/Pyozer/introduction_screen/actions/workflows/example_app.yml/badge.svg)](https://github.com/Pyozer/introduction_screen/actions/workflows/example_app.yml)
[![Run Project Tests](https://github.com/Pyozer/introduction_screen/actions/workflows/main.yml/badge.svg)](https://github.com/Pyozer/introduction_screen/actions/workflows/main.yml)

Introduction Screen allows you to have a screen on an app's first launch to, for example, explain your app.
This widget is very customizable with a great design.

`introduction_screen` uses another package, [dots_indicator](https://github.com/Pyozer/dots_indicator), that I also created.

## Installation

You just need to add `introduction_screen` as a [dependency in your pubspec.yaml file](https://flutter.io/using-packages/).

```yaml
dependencies:
introduction_screen: ^3.1.14
```

## Examples

Not all of the many parameters in each class are used in these examples.
See [Parameter Lists](#parameter-lists) for the complete documentation for each class.

*Note: if you want to display `IntroductionScreen` only once, like on the first start of your app, use
[shared_preferences](https://pub.dev/packages/shared_preferences) (or a similar strategy)
to save the status of whether it has been already displayed or not.
It's not responsibility of this package to handle this.*

### PageViewModel

A list of `PageViewModel`s is used for `IntroductionScreen`'s `pages` parameter.

#### Simple page

This example only defines the `title`, `body`, and `image` parameters.
(You can define `image` as any widget.)

```dart
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),
),
)
```

#### Page with custom colors

This example defines the color of the page using the `decoration` parameter.
The image link does not exist and is only for example.

```dart
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,
),
)
```

#### Page with custom text style

This example defines custom TextStyles in the `decoration` parameter for the title and body.

```dart
PageViewModel(
title: "Title of orange text and bold page",
body: "This is a description on a page with an orange title and bold, big body.",
image: const Center(
child: Text("👋", style: TextStyle(fontSize: 100.0)),
),
decoration: const PageDecoration(
titleTextStyle: TextStyle(color: Colors.orange),
bodyTextStyle: TextStyle(fontWeight: FontWeight.w700, fontSize: 20.0),
),
)
```

#### Page with a footer (button)

This example defines a `footer` for the page with a button.
The image does not exist and is only for example.

```dart
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!"),
),
)
```

#### Page with widget body

This example defines the page body using `bodyWidget` and a Widget, rather than with `body` and a String.
Only use `body` **or** `bodyWidget`.
The `titleWidget` parameter does the same thing for the title.

```dart
PageViewModel(
title: "Title of custom body page",
bodyWidget: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text("Click on "),
Icon(Icons.edit),
Text(" to edit a post"),
],
),
image: const Center(child: Icon(Icons.android)),
)
```

### IntroductionScreen

The `IntroductionScreen` Widget is the single object that holds all `pages` and related navigation and settings.
In these examples, `listPagesViewModel` is a **list of pages**.
A page is a `PageViewModel` object, like the examples in the previous section.

**Note:**

* If you not provide the `next` parameter, the "Next" button will be not displayed. The parameter `showNextButton` must then be set to `false`.
* If you want to display the "Skip" button, you must add a `skip` parameter **and** set `showSkipButton` to `true`.
* The `done` parameter is only required if `showDoneButton` is `true`.

#### Simple intro screen

This example only defines the `pages`, `showNextButton`, `done`, and `onDone` parameters.

```dart
IntroductionScreen(
pages: listPagesViewModel,
showNextButton: false,
done: const Text("Done"),
onDone: () {
// On button pressed
},
)
```

#### Intro screen with skip button

This example defines `showSkipButton` and `skip` to show the "Skip" button on all pages *except the last one*.

```dart
IntroductionScreen(
pages: listPagesViewModel,
showSkipButton: true,
showNextButton: false,
skip: const Text("Skip"),
done: const Text("Done"),
onDone: () {
// On button pressed
},
)
```

#### Intro screen with back button

This example defines `showBackButton` and `back` to show the "Back" button on all pages *except the first one*.

```dart
IntroductionScreen(
pages: listPagesViewModel,
showBackButton: true,
showNextButton: false,
back: const Icon(Icons.arrow_back),
done: const Text("Done"),
onDone: () {
// On button pressed
},
)
```

#### Intro screen with custom button text and dots indicators

This example defines `dotsDecorator` to show a custom implementation of the page progress dots.
This example also uses a custom style for the "Done" button, bolding it.

```dart
IntroductionScreen(
pages: listPagesViewModel,
showSkipButton: true,
skip: const Icon(Icons.skip_next),
next: const Text("Next"),
done: const Text("Done", style: TextStyle(fontWeight: FontWeight.w700)),
onDone: () {
// On Done button pressed
},
onSkip: () {
// On Skip button pressed
},
dotsDecorator: DotsDecorator(
size: const Size.square(10.0),
activeSize: const Size(20.0, 10.0),
activeColor: Theme.of(context).colorScheme.secondary,
color: Colors.black26,
spacing: const EdgeInsets.symmetric(horizontal: 3.0),
activeShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)
),
),
)
```

#### Intro screen with custom button style

A custom style will be applied to all buttons using the `baseBtnStyle` parameter ("Back", "Skip", "Next", "Done").
Specific button style parameters may also be used: `backStyle`, `skipStyle`, `nextStyle`, `doneStyle`.

If both `baseBtnStyle` and a specific button style are defined, the `baseBtnStyle` will be merge with specific style.

The following is the default button style:

```dart
TextButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
)
```

This example will override the default in the following ways:

- All buttons have a light grey background
- The "Skip" button is red
- The "Done" button is green
- The "Next" button is blue

```dart
IntroductionScreen(
pages: listPagesViewModel,
showSkipButton: true,
skip: const Text("Skip"),
next: const Text("Next"),
done: const Text("Done"),
onDone: () {
// When done button is press
},
baseBtnStyle: TextButton.styleFrom(
backgroundColor: Colors.grey.shade200,
),
skipStyle: TextButton.styleFrom(primary: Colors.red),
doneStyle: TextButton.styleFrom(primary: Colors.green),
nextStyle: TextButton.styleFrom(primary: Colors.blue),
)
```

#### Intro screen with `key` param to change page manually

To change page manually / programatically, in response to user input or another event:

1. Define a `GlobalKey` as part of the parent widget's state
1. Pass that key to the `IntroductionScreen` `key` param
1. Use the `currentState` member to access functions defined in `IntroductionScreenState` e.g.
1. `next()`
1. `previous()`
1. `skipToEnd()`
1. `animateScroll()`

This example moves to the next page after a delay:

```dart
class IntroScreenDemo extends StatefulWidget {
@override
State createState() => _IntroScreenDemoState();
}

class _IntroScreenDemoState extends State {
// 1. Define a `GlobalKey` as part of the parent widget's state
final _introKey = GlobalKey();
String _status = 'Waiting...';

@override
Widget build(BuildContext context) {
return IntroductionScreen(
// 2. Pass that key to the `IntroductionScreen` `key` param
key: _introKey,
pages: [
PageViewModel(
title: 'Page One',
bodyWidget: Column(
children: [
Text(_status),
ElevatedButton(
onPressed: () {
setState(() => _status = 'Going to the next page...');

// 3. Use the `currentState` member to access functions defined in `IntroductionScreenState`
Future.delayed(const Duration(seconds: 3),
() => _introKey.currentState?.next());
},
child: const Text('Start'))
],
)),
PageViewModel(
title: 'Page Two', bodyWidget: const Text('That\'s all folks'))
],
showNextButton: false,
showDoneButton: false,
);
}
}
```

## Parameter Lists

### IntroductionScreen parameters

Many parameters can be used to customize your app introduction like you want!
This is the full list:

#### Pages

- Page that will be display (`PageViewModel`), by adding `pages: [..]` parameter.
- Use your own pages (Widget) without using those predefined, by adding `rawPages: [..]` parameter.
- If you provide both `rawPages` and `pages` parameter, `pages` will be used.

#### Callbacks

- Set a custom callback when done button is pressed, by adding `onDone: () {}` parameter.
- This param is required if you define `done` param, EXCEPT if you set `showDoneButton: false`
- If you set `overrideDone` param, it will be ignored.
- Set a custom callback when skip button is pressed, by adding `onSkip: () {}` parameter.
- By default, it will go to the last page
- If you set `overrideSkip` param, it will be ignored.
- Add callback to listen page changes, by adding `onChange: (page) {}` parameter.

#### Use pre-made buttons

- Define pre-made Done button child (Widget), by adding `done: Text('Done')`
- This param or `overrideDone` are required, EXCEPT if you set `showDoneButton: false`
- By providing `done`, the parameter `onDone` is also required.
- Define pre-made Next button child (Widget), by adding `next: Text('Next')`
- This param is required, EXCEPT if you set `showNextButton: false`
- Define pre-made Skip button child (Widget), by adding `skip: Text('Skip')`
- This param is required if you set `showSkipButton: true`
Define pre-made Back button child (Widget), by adding `back: Text('Back')`
- This param is required if you set `showBackButton: true`

#### Use custom buttons

*If you want to control pages, you can use `key` param. Search this repo's Issues for more detailed information.*

- Define your custom Done button (Widget), by using `overrideDone`
- This param or `done` are required, EXCEPT if you set `showDoneButton: false`
- This parameter has priority over the `done` parameter.
- Define your custom Next button (Widget), by using `overrideNext`
- This param or `next` are required, EXCEPT if you set `showNextButton: false`
- This parameter has priority over the `next` parameter.
- Define your custom Skip button (Widget), by using `overrideSkip`
- This param or `skip` are required if you set `showSkipButton: true`
- This parameter has priority over the `skip` parameter.
- Define your custom Back button (Widget), by using `overrideBack`
- This param or `back` are required if you set `showBackButton: true`
- This parameter has priority over the `skip` parameter.
- Define your custom dots widget (or the widget that you want on that position), by using `customProgress`

#### Manage display of pre-made or custom buttons

- Hide/show Skip button, by adding `showSkipButton: false` parameter.
- Default `false`
- Hide/show Next button, by adding `showNextButton: false` parameter.
- Default `true`
- Hide/show Done button, by adding `showDoneButton: false` parameter.
- Default `true`
- Hide/show Back button, by adding `showBackButton: false` parameter.
- Default `false`

#### Controls

- Display or not the progress dots, by adding `isProgress: false` parameter.
- Default `true`
- Enable or disable dots progress tap, by adding `isProgressTap: false` parameter.
- Default `true`

#### Page

- Freeze the scroll, by adding `freeze: true` parameter.
- Default `false`
- Duration of scrolling animation, by adding `animationDuration: 400` parameter.
- Default `350`
- Initial page, by adding `initialPage: 2` parameter.
- Default `0`
- You can provide a ScrollController for each page by adding `scrollControllers: [..]` parameter.
- If you have 5 pages, you can provide 5 differents ScrollController.
- If you want to have only one ScrollController for page **1**, you can provide: `scrollControllers: [controller1]`
- If you want to have only one ScrollController for page **3**, you can provide: `scrollControllers: [null, null, controller1]`
- Will be ignored for page(s) if `useScrollView` is set to `false` in PageViewModel(s)

#### Pages style

- Global background color, by adding `globalBackgroundColor: Colors.blue` parameter.
- Tips: use `Colors.transparent` to display an image as background (using Stack with IntroductionScreen inside for example)
- Customize dots (progression) by adding `dotsDecorator: DotsDecorator(...)`
- You can customize dots size, shape, colors, spacing.
- Customize dots container by adding `dotsContainerDecorator: BoxDecorator(...)`
- You can customize container that contain controls.
- Skip/Back button flex, by adding `skipOrBackFlex: 1` parameter.
- Set 0 to disable Expanded behaviour, default `1`
- Dots indicator flex, by adding `dotsFlex: 1` parameter.
- Set 0 to disable Expanded behaviour, default `1`
- Next/Done button flex, by adding `nextFlex: 1` parameter.
- Set 0 to disable Expanded behaviour, default `1`
- Animation curve between pages, by adding `curve: Curves.elasticIn` parameter.
- Default `Curves.easeIn`

#### Buttons style

- Change global style of buttons (for skip, next, done, back), by adding `baseBtnStyle` parameter.
- Change skip button style, by adding `skipStyle: TextButton.styleFrom(alignment: Alignment.centerLeft)` parameter.
- Change next button style, by adding `nextStyle: TextButton.styleFrom(alignment: Alignment.centerRight)` parameter.
- Change done button style, by adding `doneStyle: TextButton.styleFrom(splashFactory: NoSplash.splashFactory)` parameter.
- Change back button style, by adding `backStyle: TextButton.styleFrom(primary: Colors.red)` parameter.

#### Semantic

- Change skip button semantic label, by adding `skipSemantic: 'Skip introduction'` parameter.
- Change next button semantic label, by adding `nextSemantic: 'Go to next page'` parameter.
- Change done button semantic label, by adding `doneSemantic: 'Exit introduction'` parameter.
- Change back button semantic label, by adding `backSemantic: 'Go to previous page'` parameter.

#### Layout

- Show the bottom part of the page, that include skip, next, done buttons by setting `showBottomPart: true` parameter.
- Hide the bottom part of the page when the keyboard is open with `hideBottomOnKeyboard` parameter.
- Customize controls position on screen, by adding `controlsPosition: const Position(left: 0, right: 0, bottom: 100)` parameter.
- Default `const Position(left: 0, right: 0, bottom: 0)`
- Customize margin of controls's container, by adding `controlsMargin: EdgeInsets.all(16.0)` parameter.
- Default `EdgeInsets.zero`
- Customize padding of controls's container, by adding `controlsPadding: EdgeInsets.all(8.0)` parameter.
- Default `EdgeInsets.all(16.0)`
- Add global header (top), static and displayed above pages, by adding `globalHeader: Image.asset(...)` parameter.
- Add global footer below controls/dots, by adding `globalFooter: ElevatedButton(...)` parameter.
- Change axis of scroll by adding `pagesAxis: Axis.vertical`.
- Default `Axis.horizontal`
- Change default scroll physics of PageView by adding `scrollPhysics: ClampingScrollPhysics()`.
- Default `BouncingScrollPhysics()`
- You can also enable right-to-left behavior by adding `rtl: true`.
- Default `false`
- Change default implicit scrolling behavior by adding `allowImplicitScrolling: true`
- Default `false`
- Reference: [PageView's `allowImplicitScrolling` parameter](https://api.flutter.dev/flutter/widgets/PageView/PageView.html)
- Activate the SafeArea by setting `safeAreaList: [true,true,true,true]` parameter.

### PageViewModel parameters

You can provide many parameters to customize each pages:

- `title: "Title of the page"` or `titleWidget: Text("Custom widget for title")`
- `body: "Body of the page"` or `bodyWidget: Text("Custom widget for body")`
- `image: Image.asset(...)` image of the page.
- It's expecting a Widget, so if you want to pass a Video, Text, or anything else, you can.
- `footer: ElevatedButton(...)`, display a widget below body
- Like image param, it's expecting a Widget, you can pass what you want.
- `decoration: PageDecoration(...)`, page decoration to customize page
- See next section for all parameters you can pass
- `reverse: true`, reverse order of image and content (title/body). (Default: `false`)
- `useScrollView: false`, by default pages use a Scrollview to handle small screen or long body text. You can remove ScrollView by setting to false.
- `scrollViewKeyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.manual`, by default the keyboard dismiss behavious is manual, you can change it.
- Only used if useScrollView not set to false.

### PageDecoration parameters

- `pageColor: Colors.white`, background color of the page
- You cannot use both pageColor and boxDecoration params
- `titleTextStyle: TextStyle(...)`, TextStyle of the title
- `bodyTextStyle: TextStyle(...)`, TextStyle of the body
- `boxDecoration: BoxDecoration(...)`, BoxDecoration of page container
- You cannot use both pageColor and boxDecoration params
- `imageFlex: 2`, flex ratio of the image
- `bodyFlex: 3`, flex ratio of the content (title/body)
- `footerFlex: 1`, flex ratio of the content (title/body)
- `footerFit: FlexFit.loose`, flex ratio of the content (title/body)
- `imagePadding: EdgeInsets.only(bottom: 12.0)`, padding of the image Widget. (Default `EdgeInsets.only(bottom: 24.0)`)
- `contentPadding: EdgeInsets.only(all: 24.0)`, padding of the content (title/body/footer) Widget. (Default `EdgeInsets.all(16)`)
- `titlePadding: EdgeInsets.only(bottom: 24.0)`, padding of the title text/Widget. (Default `EdgeInsets.only(top: 16.0, bottom: 24.0)`)
- `descriptionPadding: EdgeInsets.only(bottom: 24.0)`, padding of the body text/Widget. (Default `EdgeInsets.zero`)
- `footerPadding: EdgeInsets.only(top: 24.0)`, padding of the footer text/Widget. (Default `EdgeInsets.symmetric(vertical: 24.0)`)
- `bodyAlignment: Align.center`, content (title, body, footer) alignment. (Default `Align.topCenter`)
- `imageAlignment: Align.center`, image alignment. (Default `Align.bottomCenter`)
- `fullScreen: true`, Set image as fullscreen (background). (Default `false`)