mirror of
https://github.com/Iconica-Development/flutter_introduction.git
synced 2025-05-19 03:53:45 +02:00
Compare commits
11 commits
Author | SHA1 | Date | |
---|---|---|---|
|
2333689471 | ||
|
9bb789c6da | ||
|
48a4ea0e66 | ||
|
21c2efa98a | ||
|
a5f9d76f79 | ||
|
b3fd9df897 | ||
|
4868f3c548 | ||
|
89bc007236 | ||
|
23569d0e05 | ||
|
6808ee972d | ||
|
43a56166c9 |
37 changed files with 406 additions and 358 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -31,7 +31,6 @@ build/
|
|||
|
||||
.metadata
|
||||
|
||||
|
||||
pubspec.lock
|
||||
|
||||
pubspec_overrides.yaml
|
||||
|
@ -41,3 +40,7 @@ example/web
|
|||
example/android
|
||||
example/linux
|
||||
example/macos
|
||||
|
||||
# FVM Version Cache
|
||||
.fvm/
|
||||
.fvmrc
|
||||
|
|
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -1,3 +1,19 @@
|
|||
## 5.0.0
|
||||
|
||||
* Changed color of indicators
|
||||
* Changed default button text
|
||||
|
||||
## 4.0.0
|
||||
|
||||
* Added Buildcontext to the pages parameter.
|
||||
* Added `dotColor` so the default can be changed.
|
||||
* Changed the default `pages` to include theme.
|
||||
|
||||
## 3.1.0
|
||||
|
||||
* Introduction now uses `IntroductionScreenMode` to determine how often the introductions should be shown
|
||||
* Added `dotSize` and `dotSpacing` to `IntroductionOptions` to allow for customization of the dots for the introduction
|
||||
|
||||
## 3.0.0
|
||||
|
||||
* Update default styling
|
||||
|
|
1
packages/flutter_introduction/CHANGELOG.md
Symbolic link
1
packages/flutter_introduction/CHANGELOG.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../CHANGELOG.md
|
1
packages/flutter_introduction/LICENSE
Symbolic link
1
packages/flutter_introduction/LICENSE
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../LICENSE
|
1
packages/flutter_introduction/README.md
Symbolic link
1
packages/flutter_introduction/README.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../README.md
|
|
@ -38,7 +38,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||
Widget build(BuildContext context) => Scaffold(
|
||||
body: Introduction(
|
||||
options: IntroductionOptions(
|
||||
pages: [
|
||||
pages: (context) => [
|
||||
const IntroductionPage(
|
||||
title: Text('First page'),
|
||||
text: Text('Wow a page'),
|
||||
|
|
|
@ -56,7 +56,9 @@ class _IntroductionState extends State<Introduction> {
|
|||
// ignore: discarded_futures
|
||||
future: _service.shouldShow(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.data == null || snapshot.data!) {
|
||||
if (snapshot.data == null ||
|
||||
snapshot.data! ||
|
||||
widget.options.mode == IntroductionScreenMode.showAlways) {
|
||||
return IntroductionScreen(
|
||||
options: widget.options,
|
||||
onComplete: () async {
|
||||
|
|
|
@ -1,25 +1,21 @@
|
|||
name: flutter_introduction
|
||||
description: Combined Package of Flutter Introduction Widget and Flutter Introduction Service
|
||||
version: 3.0.0
|
||||
publish_to: none
|
||||
version: 5.0.0
|
||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||
|
||||
environment:
|
||||
sdk: ">=2.18.0 <3.0.0"
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_introduction_widget:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_introduction
|
||||
ref: 3.0.0
|
||||
path: packages/flutter_introduction_widget
|
||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||
version: "^5.0.0"
|
||||
flutter_introduction_service:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_introduction
|
||||
ref: 3.0.0
|
||||
path: packages/flutter_introduction_service
|
||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||
version: "^5.0.0"
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
1
packages/flutter_introduction_firebase/CHANGELOG.md
Symbolic link
1
packages/flutter_introduction_firebase/CHANGELOG.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../CHANGELOG.md
|
1
packages/flutter_introduction_firebase/LICENSE
Symbolic link
1
packages/flutter_introduction_firebase/LICENSE
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../LICENSE
|
|
@ -115,7 +115,7 @@ class _IntroductionState extends State<IntroductionFirebase> {
|
|||
snapshot.data is List<IntroductionPageData>) {
|
||||
return IntroductionScreen(
|
||||
options: widget.options.copyWith(
|
||||
pages: snapshot.data?.map(
|
||||
pages: (context) => snapshot.data!.map(
|
||||
(e) {
|
||||
var title = e.title.isEmpty
|
||||
? ''
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: flutter_introduction_firebase
|
||||
description: Flutter Introduction Page that uses firebase for the pages and some settings
|
||||
version: 3.0.0
|
||||
publish_to: none
|
||||
version: 5.0.0
|
||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||
|
||||
environment:
|
||||
sdk: ">=3.1.5 <4.0.0"
|
||||
|
@ -9,19 +9,15 @@ environment:
|
|||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
cloud_firestore: ^4.12.2
|
||||
cached_network_image: ^3.3.0
|
||||
cloud_firestore: "^4.12.2"
|
||||
cached_network_image: "^3.3.0"
|
||||
|
||||
flutter_introduction_widget:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_introduction
|
||||
ref: 3.0.0
|
||||
path: packages/flutter_introduction_widget
|
||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||
version: "^5.0.0"
|
||||
flutter_introduction_service:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_introduction
|
||||
ref: 3.0.0
|
||||
path: packages/flutter_introduction_service
|
||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||
version: "^5.0.0"
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
1
packages/flutter_introduction_interface/CHANGELOG.md
Symbolic link
1
packages/flutter_introduction_interface/CHANGELOG.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../CHANGELOG.md
|
1
packages/flutter_introduction_interface/LICENSE
Symbolic link
1
packages/flutter_introduction_interface/LICENSE
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../LICENSE
|
1
packages/flutter_introduction_interface/README.md
Symbolic link
1
packages/flutter_introduction_interface/README.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../README.md
|
|
@ -1,19 +1,18 @@
|
|||
name: flutter_introduction_interface
|
||||
description: A new Flutter package project.
|
||||
version: 3.0.0
|
||||
publish_to: none
|
||||
version: 5.0.0
|
||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||
|
||||
environment:
|
||||
sdk: '>=2.18.0 <3.0.0'
|
||||
sdk: '>=3.0.0 <4.0.0'
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_data_interface:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_data_interface.git
|
||||
ref: 1.0.0
|
||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||
version: "^1.0.0"
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
1
packages/flutter_introduction_service/CHANGELOG.md
Symbolic link
1
packages/flutter_introduction_service/CHANGELOG.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../CHANGELOG.md
|
1
packages/flutter_introduction_service/LICENSE
Symbolic link
1
packages/flutter_introduction_service/LICENSE
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../LICENSE
|
1
packages/flutter_introduction_service/README.md
Symbolic link
1
packages/flutter_introduction_service/README.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../README.md
|
|
@ -1,20 +1,18 @@
|
|||
name: flutter_introduction_service
|
||||
description: A new Flutter package project.
|
||||
version: 3.0.0
|
||||
publish_to: none
|
||||
version: 5.0.0
|
||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||
|
||||
environment:
|
||||
sdk: '>=2.18.0 <3.0.0'
|
||||
sdk: '>=3.0.0 <4.0.0'
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_introduction_interface:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_introduction
|
||||
ref: 3.0.0
|
||||
path: packages/flutter_introduction_interface
|
||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||
version: "^5.0.0"
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
1
packages/flutter_introduction_shared_preferences/CHANGELOG.md
Symbolic link
1
packages/flutter_introduction_shared_preferences/CHANGELOG.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../CHANGELOG.md
|
1
packages/flutter_introduction_shared_preferences/LICENSE
Symbolic link
1
packages/flutter_introduction_shared_preferences/LICENSE
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../LICENSE
|
1
packages/flutter_introduction_shared_preferences/README.md
Symbolic link
1
packages/flutter_introduction_shared_preferences/README.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../README.md
|
|
@ -1,21 +1,19 @@
|
|||
name: flutter_introduction_shared_preferences
|
||||
description: A new Flutter package project.
|
||||
version: 3.0.0
|
||||
publish_to: none
|
||||
version: 5.0.0
|
||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||
|
||||
environment:
|
||||
sdk: '>=2.18.0 <3.0.0'
|
||||
sdk: '>=3.0.0 <4.0.0'
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_introduction_interface:
|
||||
git:
|
||||
url: https://github.com/Iconica-Development/flutter_introduction
|
||||
ref: 3.0.0
|
||||
path: packages/flutter_introduction_interface
|
||||
shared_preferences: any
|
||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||
version: "^5.0.0"
|
||||
shared_preferences: "^2.2.0"
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
1
packages/flutter_introduction_widget/CHANGELOG.md
Symbolic link
1
packages/flutter_introduction_widget/CHANGELOG.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../CHANGELOG.md
|
1
packages/flutter_introduction_widget/LICENSE
Symbolic link
1
packages/flutter_introduction_widget/LICENSE
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../LICENSE
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 61 KiB |
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 49 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 33 KiB |
|
@ -31,7 +31,7 @@ class MyApp extends StatelessWidget {
|
|||
),
|
||||
home: IntroductionScreen(
|
||||
options: IntroductionOptions(
|
||||
pages: [
|
||||
pages: (context) => [
|
||||
const IntroductionPage(
|
||||
title: Text('Basic Page'),
|
||||
text: Text(
|
||||
|
|
|
@ -1,115 +1,85 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_introduction_widget/flutter_introduction_widget.dart';
|
||||
|
||||
const List<IntroductionPage> defaultIntroductionPages = [
|
||||
List<IntroductionPage> defaultIntroductionPages(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
return [
|
||||
IntroductionPage(
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xffFAF9F6),
|
||||
),
|
||||
title: Column(
|
||||
children: [
|
||||
SizedBox(height: 100),
|
||||
const SizedBox(height: 50),
|
||||
Text(
|
||||
'welcome to iconinstagram',
|
||||
style: TextStyle(
|
||||
color: Color(0xff71C6D1),
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 6),
|
||||
Text(
|
||||
'Welcome to the world of Instagram, where creativity'
|
||||
' knows no bounds and connections are made'
|
||||
' through captivating visuals.',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.headlineLarge,
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
],
|
||||
),
|
||||
graphic: Image(
|
||||
graphic: const Image(
|
||||
image: AssetImage(
|
||||
'assets/first.png',
|
||||
package: 'flutter_introduction_widget',
|
||||
),
|
||||
),
|
||||
text: Text(''),
|
||||
text: Text(
|
||||
'Welcome to the world of Instagram, where creativity'
|
||||
' knows no bounds and connections are made'
|
||||
' through captivating visuals.',
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
IntroductionPage(
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xffFAF9F6),
|
||||
),
|
||||
title: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(height: 100),
|
||||
const SizedBox(height: 50),
|
||||
Text(
|
||||
'discover iconinstagram',
|
||||
style: TextStyle(
|
||||
color: Color(0xff71C6D1),
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w700,
|
||||
style: theme.textTheme.headlineLarge,
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 6),
|
||||
Text(
|
||||
text: Text(
|
||||
'Dive into the vibrant world of'
|
||||
' Instagram and discover endless possibilities.'
|
||||
' From stunning photography to engaging videos,'
|
||||
' Instagram offers a diverse range of content to explore and enjoy.',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
graphic: Image(
|
||||
graphic: const Image(
|
||||
image: AssetImage(
|
||||
'assets/second.png',
|
||||
package: 'flutter_introduction_widget',
|
||||
),
|
||||
),
|
||||
text: Text(''),
|
||||
),
|
||||
IntroductionPage(
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xffFAF9F6),
|
||||
),
|
||||
title: Column(
|
||||
children: [
|
||||
SizedBox(height: 100),
|
||||
const SizedBox(height: 50),
|
||||
Text(
|
||||
'elevate your experience',
|
||||
style: TextStyle(
|
||||
color: Color(0xff71C6D1),
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 6),
|
||||
Text(
|
||||
'Whether promoting your business, or connecting'
|
||||
' with friends and family, Instagram provides the'
|
||||
' tools and platform to make your voice heard.',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.headlineLarge,
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
],
|
||||
),
|
||||
graphic: Image(
|
||||
graphic: const Image(
|
||||
image: AssetImage(
|
||||
'assets/third.png',
|
||||
package: 'flutter_introduction_widget',
|
||||
),
|
||||
),
|
||||
text: Text(''),
|
||||
text: Text(
|
||||
'Whether promoting your business, or connecting'
|
||||
' with friends and family, Instagram provides the'
|
||||
' tools and platform to make your voice heard.',
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.bodyMedium,
|
||||
),
|
||||
];
|
||||
),
|
||||
];
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ class IntroductionOptions {
|
|||
this.introductionButtonTextstyles = const IntroductionButtonTextstyles(),
|
||||
this.indicatorMode = IndicatorMode.dot,
|
||||
this.indicatorBuilder,
|
||||
this.layoutStyle = IntroductionLayoutStyle.imageCenter,
|
||||
this.layoutStyle = IntroductionLayoutStyle.imageBottom,
|
||||
this.pages = defaultIntroductionPages,
|
||||
this.buttonMode = IntroductionScreenButtonMode.text,
|
||||
this.tapEnabled = false,
|
||||
|
@ -73,6 +73,9 @@ class IntroductionOptions {
|
|||
this.skippable = false,
|
||||
this.buttonBuilder,
|
||||
this.controlMode = IntroductionControlMode.previousNextButton,
|
||||
this.dotSize = 12,
|
||||
this.dotSpacing = 24,
|
||||
this.dotColor,
|
||||
}) : assert(
|
||||
!(identical(indicatorMode, IndicatorMode.custom) &&
|
||||
indicatorBuilder == null),
|
||||
|
@ -93,7 +96,7 @@ class IntroductionOptions {
|
|||
|
||||
/// List of introduction pages to set the text, icons or images for the
|
||||
/// introduction screens.
|
||||
final List<IntroductionPage> pages;
|
||||
final List<IntroductionPage> Function(BuildContext context) pages;
|
||||
|
||||
/// Determines whether the user can tap the screen to go to the next
|
||||
/// introduction screen.
|
||||
|
@ -204,9 +207,19 @@ class IntroductionOptions {
|
|||
/// - Finish
|
||||
final IntroductionButtonTextstyles introductionButtonTextstyles;
|
||||
|
||||
/// The size of the dots in the indicator. Default is 12
|
||||
final double dotSize;
|
||||
|
||||
/// The distance between the center of each dot. Default is 24
|
||||
final double dotSpacing;
|
||||
|
||||
/// The color of the dots in the indicator. Default is the primary color of
|
||||
/// the theme
|
||||
final Color? dotColor;
|
||||
|
||||
IntroductionOptions copyWith({
|
||||
IntroductionScreenMode? mode,
|
||||
List<IntroductionPage>? pages,
|
||||
List<IntroductionPage> Function(BuildContext context)? pages,
|
||||
bool? tapEnabled,
|
||||
IntroductionScreenButtonMode? buttonMode,
|
||||
IntroductionLayoutStyle? layoutStyle,
|
||||
|
@ -248,10 +261,10 @@ class IntroductionOptions {
|
|||
|
||||
class IntroductionTranslations {
|
||||
const IntroductionTranslations({
|
||||
this.skipButton = 'skip',
|
||||
this.skipButton = 'Skip',
|
||||
this.nextButton = 'Next',
|
||||
this.previousButton = 'Previous',
|
||||
this.finishButton = 'Get Started',
|
||||
this.finishButton = 'Get started',
|
||||
});
|
||||
final String skipButton;
|
||||
final String nextButton;
|
||||
|
@ -261,22 +274,10 @@ class IntroductionTranslations {
|
|||
|
||||
class IntroductionButtonTextstyles {
|
||||
const IntroductionButtonTextstyles({
|
||||
this.skipButtonStyle = const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
this.nextButtonStyle = const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
this.previousButtonStyle = const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
this.finishButtonStyle = const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
this.skipButtonStyle,
|
||||
this.nextButtonStyle,
|
||||
this.previousButtonStyle,
|
||||
this.finishButtonStyle,
|
||||
});
|
||||
final TextStyle? skipButtonStyle;
|
||||
final TextStyle? nextButtonStyle;
|
||||
|
|
|
@ -77,7 +77,7 @@ class _MultiPageIntroductionScreenState
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var pages = widget.options.pages;
|
||||
var pages = widget.options.pages.call(context);
|
||||
var translations = widget.options.introductionTranslations;
|
||||
return Stack(
|
||||
children: [
|
||||
|
@ -150,15 +150,21 @@ class _MultiPageIntroductionScreenState
|
|||
AnimatedBuilder(
|
||||
animation: _currentPage,
|
||||
builder: (context, _) => Indicator(
|
||||
options: widget.options,
|
||||
indicatorBuilder: widget.options.indicatorBuilder,
|
||||
mode: widget.options.indicatorMode,
|
||||
controller: _controller,
|
||||
count: pages.length,
|
||||
index: _currentPage.value,
|
||||
dotSize: widget.options.dotSize,
|
||||
dotSpacing: widget.options.dotSpacing,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 40,
|
||||
horizontal: 20,
|
||||
),
|
||||
child: AnimatedBuilder(
|
||||
animation: _controller,
|
||||
builder: (context, _) {
|
||||
|
@ -270,14 +276,14 @@ class ExplainerPage extends StatelessWidget {
|
|||
title: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
child: DefaultTextStyle(
|
||||
style: theme.textTheme.displayMedium!,
|
||||
style: theme.textTheme.titleMedium!,
|
||||
child: page.title ?? Text('introduction.$index.title'),
|
||||
),
|
||||
),
|
||||
text: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
child: DefaultTextStyle(
|
||||
style: theme.textTheme.bodyLarge!,
|
||||
style: theme.textTheme.bodyMedium!,
|
||||
child: page.text ?? Text('introduction.$index.description'),
|
||||
),
|
||||
),
|
||||
|
@ -336,25 +342,36 @@ class IntroductionTwoButtons extends StatelessWidget {
|
|||
var translations = options.introductionTranslations;
|
||||
var showFinishButton =
|
||||
options.buttonMode == IntroductionScreenButtonMode.singleFinish;
|
||||
var theme = Theme.of(context);
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (options.buttonMode == IntroductionScreenButtonMode.text) ...[
|
||||
if (previous) ...[
|
||||
options.buttonBuilder?.call(
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 6),
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 180,
|
||||
),
|
||||
child: Opacity(
|
||||
opacity: previous ? 1 : 0,
|
||||
child: IgnorePointer(
|
||||
ignoring: !previous,
|
||||
child: options.buttonBuilder?.call(
|
||||
context,
|
||||
_previous,
|
||||
Text(
|
||||
translations.previousButton,
|
||||
style: options
|
||||
.introductionButtonTextstyles.previousButtonStyle,
|
||||
style: options.introductionButtonTextstyles
|
||||
.previousButtonStyle ??
|
||||
theme.textTheme.bodyMedium,
|
||||
),
|
||||
IntroductionButtonType.previous,
|
||||
) ??
|
||||
InkWell(
|
||||
onTap: _previous,
|
||||
child: Container(
|
||||
width: 180,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(
|
||||
|
@ -365,32 +382,45 @@ class IntroductionTwoButtons extends StatelessWidget {
|
|||
),
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 4),
|
||||
child: Text(
|
||||
translations.previousButton,
|
||||
style: options
|
||||
.introductionButtonTextstyles.previousButtonStyle,
|
||||
style: options.introductionButtonTextstyles
|
||||
.previousButtonStyle ??
|
||||
theme.textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
] else
|
||||
const SizedBox.shrink(),
|
||||
if (next) ...[
|
||||
options.buttonBuilder?.call(
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 6),
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 180,
|
||||
),
|
||||
child: options.buttonBuilder?.call(
|
||||
context,
|
||||
_next,
|
||||
Text(
|
||||
translations.nextButton,
|
||||
style: options.introductionButtonTextstyles.nextButtonStyle,
|
||||
style: options.introductionButtonTextstyles
|
||||
.nextButtonStyle ??
|
||||
theme.textTheme.bodyMedium,
|
||||
),
|
||||
IntroductionButtonType.next,
|
||||
) ??
|
||||
InkWell(
|
||||
onTap: _next,
|
||||
child: Container(
|
||||
width: 180,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(
|
||||
|
@ -401,26 +431,38 @@ class IntroductionTwoButtons extends StatelessWidget {
|
|||
),
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: Text(
|
||||
translations.nextButton,
|
||||
style: options
|
||||
.introductionButtonTextstyles.nextButtonStyle,
|
||||
style: options.introductionButtonTextstyles
|
||||
.nextButtonStyle ??
|
||||
theme.textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
] else if (last) ...[
|
||||
options.buttonBuilder?.call(
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 6),
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 180,
|
||||
),
|
||||
child: options.buttonBuilder?.call(
|
||||
context,
|
||||
() {
|
||||
onFinish?.call();
|
||||
},
|
||||
Text(
|
||||
translations.finishButton,
|
||||
style:
|
||||
options.introductionButtonTextstyles.finishButtonStyle,
|
||||
style: options.introductionButtonTextstyles
|
||||
.finishButtonStyle ??
|
||||
theme.textTheme.bodyMedium,
|
||||
),
|
||||
IntroductionButtonType.finish,
|
||||
) ??
|
||||
|
@ -429,7 +471,6 @@ class IntroductionTwoButtons extends StatelessWidget {
|
|||
onFinish?.call();
|
||||
},
|
||||
child: Container(
|
||||
width: 180,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(
|
||||
|
@ -440,11 +481,15 @@ class IntroductionTwoButtons extends StatelessWidget {
|
|||
),
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: Text(
|
||||
translations.finishButton,
|
||||
style: options
|
||||
.introductionButtonTextstyles.finishButtonStyle,
|
||||
style: options.introductionButtonTextstyles
|
||||
.finishButtonStyle ??
|
||||
theme.textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -463,6 +508,11 @@ class IntroductionTwoButtons extends StatelessWidget {
|
|||
maintainState: true,
|
||||
maintainInteractivity: false,
|
||||
child: Align(
|
||||
child: Flexible(
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 180,
|
||||
),
|
||||
child: options.buttonBuilder?.call(
|
||||
context,
|
||||
() {
|
||||
|
@ -470,8 +520,9 @@ class IntroductionTwoButtons extends StatelessWidget {
|
|||
},
|
||||
Text(
|
||||
translations.finishButton,
|
||||
style: options
|
||||
.introductionButtonTextstyles.finishButtonStyle,
|
||||
style: options.introductionButtonTextstyles
|
||||
.finishButtonStyle ??
|
||||
theme.textTheme.bodyMedium,
|
||||
),
|
||||
IntroductionButtonType.finish,
|
||||
) ??
|
||||
|
@ -480,7 +531,6 @@ class IntroductionTwoButtons extends StatelessWidget {
|
|||
onFinish?.call();
|
||||
},
|
||||
child: Container(
|
||||
width: 180,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(
|
||||
|
@ -491,11 +541,15 @@ class IntroductionTwoButtons extends StatelessWidget {
|
|||
),
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 4),
|
||||
child: Text(
|
||||
translations.finishButton,
|
||||
style: options.introductionButtonTextstyles
|
||||
.finishButtonStyle,
|
||||
.finishButtonStyle ??
|
||||
theme.textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -24,7 +24,7 @@ class Background extends StatelessWidget {
|
|||
var theme = Theme.of(context);
|
||||
var background = this.background ??
|
||||
BoxDecoration(
|
||||
color: theme.colorScheme.background,
|
||||
color: theme.colorScheme.surface,
|
||||
);
|
||||
var size = MediaQuery.of(context).size;
|
||||
return Container(
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_introduction_widget/src/config/introduction.dart';
|
||||
|
@ -16,6 +15,9 @@ class Indicator extends StatelessWidget {
|
|||
required this.count,
|
||||
required this.index,
|
||||
required this.indicatorBuilder,
|
||||
required this.dotSize,
|
||||
required this.dotSpacing,
|
||||
required this.options,
|
||||
super.key,
|
||||
}) : assert(
|
||||
!(mode == IndicatorMode.custom && indicatorBuilder == null),
|
||||
|
@ -39,6 +41,14 @@ class Indicator extends StatelessWidget {
|
|||
final Widget Function(BuildContext, PageController, int, int)?
|
||||
indicatorBuilder;
|
||||
|
||||
/// The size of the dots.
|
||||
final double dotSize;
|
||||
|
||||
/// The distance between the center of each dot.
|
||||
final double dotSpacing;
|
||||
|
||||
final IntroductionOptions options;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
|
@ -47,9 +57,10 @@ class Indicator extends StatelessWidget {
|
|||
return indicatorBuilder!.call(context, controller, index, count);
|
||||
case IndicatorMode.dot:
|
||||
return DotsIndicator(
|
||||
dotSize: dotSize,
|
||||
dotSpacing: dotSpacing,
|
||||
controller: controller,
|
||||
color: theme.colorScheme.primary,
|
||||
dotcolor: theme.colorScheme.secondary,
|
||||
color: options.dotColor ?? theme.colorScheme.primary,
|
||||
itemCount: count,
|
||||
onPageSelected: (int page) {
|
||||
unawaited(
|
||||
|
@ -65,7 +76,7 @@ class Indicator extends StatelessWidget {
|
|||
return DashIndicator(
|
||||
color: theme.colorScheme.primary,
|
||||
controller: controller,
|
||||
selectedColor: theme.colorScheme.primary,
|
||||
selectedColor: options.dotColor ?? theme.colorScheme.primary,
|
||||
itemCount: count,
|
||||
onPageSelected: (int page) {
|
||||
unawaited(
|
||||
|
@ -153,16 +164,15 @@ class DotsIndicator extends AnimatedWidget {
|
|||
const DotsIndicator({
|
||||
required this.controller,
|
||||
this.color = Colors.white,
|
||||
this.dotcolor = Colors.green,
|
||||
this.itemCount,
|
||||
this.onPageSelected,
|
||||
this.dotSize = 8.0,
|
||||
this.dotSpacing = 24.0,
|
||||
super.key,
|
||||
}) : super(
|
||||
listenable: controller,
|
||||
);
|
||||
|
||||
/// The PageController that this DotsIndicator is representing.
|
||||
final Color? dotcolor;
|
||||
final PageController controller;
|
||||
|
||||
/// The number of items managed by the PageController
|
||||
|
@ -177,39 +187,24 @@ class DotsIndicator extends AnimatedWidget {
|
|||
final Color color;
|
||||
|
||||
// The base size of the dots
|
||||
static const double _kDotSize = 4.0;
|
||||
final double dotSize;
|
||||
final double dotSpacing;
|
||||
|
||||
// The increase in the size of the selected dot
|
||||
static const double _kMaxZoom = 2.0;
|
||||
|
||||
// The distance between the center of each dot
|
||||
static const double _kDotSpacing = 12.0;
|
||||
|
||||
Widget _buildDot(int index) {
|
||||
var selectedness = Curves.easeOut.transform(
|
||||
max(
|
||||
0.0,
|
||||
1.0 -
|
||||
((controller.page ?? controller.initialPage).round() - index).abs(),
|
||||
),
|
||||
);
|
||||
var zoom = 1.0 + (_kMaxZoom - 1.0) * selectedness;
|
||||
|
||||
return SizedBox(
|
||||
width: _kDotSpacing,
|
||||
Widget _buildDot(int index) => SizedBox(
|
||||
width: dotSpacing,
|
||||
child: Center(
|
||||
child: Material(
|
||||
color: (((controller.page ?? controller.initialPage).round()) == index
|
||||
color:
|
||||
(((controller.page ?? controller.initialPage).round()) == index
|
||||
? color
|
||||
: color.withAlpha(125)),
|
||||
: color.withAlpha(62)),
|
||||
type: MaterialType.circle,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
decoration: const BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(width: 2, color: dotcolor!),
|
||||
),
|
||||
width: _kDotSize * 2 * zoom,
|
||||
height: _kDotSize * 2 * zoom,
|
||||
width: dotSize,
|
||||
height: dotSize,
|
||||
child: InkWell(
|
||||
onTap: () => onPageSelected!.call(index),
|
||||
),
|
||||
|
@ -217,7 +212,6 @@ class DotsIndicator extends AnimatedWidget {
|
|||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Row(
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
name: flutter_introduction_widget
|
||||
description: Flutter Introduction Widget for showing a list of introduction pages on a single scrollable page or horizontal pageview
|
||||
version: 3.0.0
|
||||
version: 5.0.0
|
||||
homepage: https://github.com/Iconica-Development/flutter_introduction_widget
|
||||
|
||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||
|
||||
environment:
|
||||
sdk: ">=2.18.0 <3.0.0"
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
name: flutter_introduction_workspace
|
||||
version: 3.0.0
|
||||
description: The use case level package using both the flutter_introduction_widget and the flutter_introduction_service combined
|
||||
version: 5.0.0
|
||||
|
||||
publish_to: None
|
||||
|
||||
environment:
|
||||
sdk: '>=3.1.0 <4.0.0'
|
||||
dev_dependencies:
|
||||
melos: ">=3.0.1 <5.0.0"
|
||||
melos: ">=3.0.1 <7.0.0"
|
||||
|
|
Loading…
Reference in a new issue