mirror of
https://github.com/Iconica-Development/flutter_introduction.git
synced 2025-05-19 12:03:44 +02:00
Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
|
b5a1ce263c |
33 changed files with 221 additions and 709 deletions
3
.fvmrc
Normal file
3
.fvmrc
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"flutter": "3.22.1"
|
||||||
|
}
|
14
.github/workflows/component-documentation.yml
vendored
14
.github/workflows/component-documentation.yml
vendored
|
@ -1,14 +0,0 @@
|
||||||
name: Iconica Standard Component Documentation Workflow
|
|
||||||
# Workflow Caller version: 1.0.0
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
call-iconica-component-documentation-workflow:
|
|
||||||
uses: Iconica-Development/.github/.github/workflows/component-documentation.yml@master
|
|
||||||
secrets: inherit
|
|
||||||
permissions: write-all
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -43,4 +43,3 @@ example/macos
|
||||||
|
|
||||||
# FVM Version Cache
|
# FVM Version Cache
|
||||||
.fvm/
|
.fvm/
|
||||||
.fvmrc
|
|
||||||
|
|
26
CHANGELOG.md
26
CHANGELOG.md
|
@ -1,28 +1,6 @@
|
||||||
## 5.0.0
|
## 2.0.1
|
||||||
|
|
||||||
* Changed color of indicators
|
* Ready for publishing
|
||||||
* 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
|
|
||||||
* Add default introduction
|
|
||||||
|
|
||||||
## 2.1.0
|
|
||||||
|
|
||||||
* Upgrade dependencies
|
|
||||||
* Add introductionButtonTextstyles option to IntroductionOptions for styling the introduction button text
|
|
||||||
|
|
||||||
## 2.0.0
|
## 2.0.0
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ Please file any issues, bugs or feature request as an issue on our [GitHub](http
|
||||||
|
|
||||||
## Want to contribute
|
## Want to contribute
|
||||||
|
|
||||||
If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](./CONTRIBUTING.md) and send us your [pull request](https://github.com/Iconica-Development/flutter_introduction/pulls).
|
If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Iconica-Development/flutter_introduction/pulls).
|
||||||
|
|
||||||
## Author
|
## Author
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,6 @@ scripts:
|
||||||
upgrade:
|
upgrade:
|
||||||
run: melos exec -c 1 -- "flutter pub upgrade"
|
run: melos exec -c 1 -- "flutter pub upgrade"
|
||||||
|
|
||||||
upgrade-major:
|
|
||||||
run: melos exec -c 1 -- "flutter pub upgrade --major-versions"
|
|
||||||
|
|
||||||
create:
|
create:
|
||||||
# run create in the example folder of flutter_introduction, flutter_introduction_firebase
|
# run create in the example folder of flutter_introduction, flutter_introduction_firebase
|
||||||
run: melos exec --scope="*example*" -c 1 -- "flutter create ."
|
run: melos exec --scope="*example*" -c 1 -- "flutter create ."
|
||||||
|
|
|
@ -38,21 +38,21 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
Widget build(BuildContext context) => Scaffold(
|
Widget build(BuildContext context) => Scaffold(
|
||||||
body: Introduction(
|
body: Introduction(
|
||||||
options: IntroductionOptions(
|
options: IntroductionOptions(
|
||||||
pages: (context) => [
|
pages: [
|
||||||
const IntroductionPage(
|
IntroductionPage(
|
||||||
title: Text('First page'),
|
title: const Text('First page'),
|
||||||
text: Text('Wow a page'),
|
text: const Text('Wow a page'),
|
||||||
graphic: FlutterLogo(),
|
graphic: const FlutterLogo(),
|
||||||
),
|
),
|
||||||
const IntroductionPage(
|
IntroductionPage(
|
||||||
title: Text('Second page'),
|
title: const Text('Second page'),
|
||||||
text: Text('Another page'),
|
text: const Text('Another page'),
|
||||||
graphic: FlutterLogo(),
|
graphic: const FlutterLogo(),
|
||||||
),
|
),
|
||||||
const IntroductionPage(
|
IntroductionPage(
|
||||||
title: Text('Third page'),
|
title: const Text('Third page'),
|
||||||
text: Text('The final page of this app'),
|
text: const Text('The final page of this app'),
|
||||||
graphic: FlutterLogo(),
|
graphic: const FlutterLogo(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
introductionTranslations: const IntroductionTranslations(
|
introductionTranslations: const IntroductionTranslations(
|
||||||
|
|
|
@ -17,11 +17,15 @@ dependencies:
|
||||||
flutter_introduction:
|
flutter_introduction:
|
||||||
path: ../
|
path: ../
|
||||||
flutter_introduction_shared_preferences:
|
flutter_introduction_shared_preferences:
|
||||||
path: ../../flutter_introduction_shared_preferences
|
git:
|
||||||
|
url: https://github.com/Iconica-Development/flutter_introduction
|
||||||
|
ref: 2.0.0
|
||||||
|
path: packages/flutter_introduction_shared_preferences
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_lints: ^2.0.0
|
||||||
flutter_iconica_analysis:
|
flutter_iconica_analysis:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
|
|
|
@ -19,19 +19,10 @@ class Introduction extends StatefulWidget {
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Callback function to navigate to the next screen.
|
|
||||||
final VoidCallback navigateTo;
|
final VoidCallback navigateTo;
|
||||||
|
|
||||||
/// The introduction service to use.
|
|
||||||
final IntroductionService? service;
|
final IntroductionService? service;
|
||||||
|
|
||||||
/// Options for configuring the introduction screen.
|
|
||||||
final IntroductionOptions options;
|
final IntroductionOptions options;
|
||||||
|
|
||||||
/// The scrolling physics for the introduction screen.
|
|
||||||
final ScrollPhysics? physics;
|
final ScrollPhysics? physics;
|
||||||
|
|
||||||
/// Child widget to display.
|
|
||||||
final Widget? child;
|
final Widget? child;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -56,9 +47,7 @@ class _IntroductionState extends State<Introduction> {
|
||||||
// ignore: discarded_futures
|
// ignore: discarded_futures
|
||||||
future: _service.shouldShow(),
|
future: _service.shouldShow(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.data == null ||
|
if (snapshot.data == null || snapshot.data!) {
|
||||||
snapshot.data! ||
|
|
||||||
widget.options.mode == IntroductionScreenMode.showAlways) {
|
|
||||||
return IntroductionScreen(
|
return IntroductionScreen(
|
||||||
options: widget.options,
|
options: widget.options,
|
||||||
onComplete: () async {
|
onComplete: () async {
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
name: flutter_introduction
|
name: flutter_introduction
|
||||||
description: Combined Package of Flutter Introduction Widget and Flutter Introduction Service
|
description: Combined Package of Flutter Introduction Widget and Flutter Introduction Service
|
||||||
version: 5.0.0
|
version: 2.0.1
|
||||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.0.0 <4.0.0"
|
sdk: ">=3.0.0 <4.0.0"
|
||||||
flutter: ">=1.17.0"
|
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_introduction_widget:
|
flutter_introduction_widget:
|
||||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
version: "^5.0.0"
|
version: ^2.0.1
|
||||||
flutter_introduction_service:
|
flutter_introduction_service:
|
||||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
version: "^5.0.0"
|
version: ^2.0.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_lints: ^2.0.0
|
||||||
flutter_iconica_analysis:
|
flutter_iconica_analysis:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
|
|
|
@ -115,7 +115,7 @@ class _IntroductionState extends State<IntroductionFirebase> {
|
||||||
snapshot.data is List<IntroductionPageData>) {
|
snapshot.data is List<IntroductionPageData>) {
|
||||||
return IntroductionScreen(
|
return IntroductionScreen(
|
||||||
options: widget.options.copyWith(
|
options: widget.options.copyWith(
|
||||||
pages: (context) => snapshot.data!.map(
|
pages: snapshot.data?.map(
|
||||||
(e) {
|
(e) {
|
||||||
var title = e.title.isEmpty
|
var title = e.title.isEmpty
|
||||||
? ''
|
? ''
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: flutter_introduction_firebase
|
name: flutter_introduction_firebase
|
||||||
description: Flutter Introduction Page that uses firebase for the pages and some settings
|
description: Flutter Introduction Page that uses firebase for the pages and some settings
|
||||||
version: 5.0.0
|
version: 2.0.1
|
||||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
@ -9,15 +9,15 @@ environment:
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
cloud_firestore: "^4.12.2"
|
cloud_firestore: ^5.6.6
|
||||||
cached_network_image: "^3.3.0"
|
cached_network_image: ^3.3.0
|
||||||
|
|
||||||
flutter_introduction_widget:
|
flutter_introduction_widget:
|
||||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
version: "^5.0.0"
|
version: ^2.0.1
|
||||||
flutter_introduction_service:
|
flutter_introduction_service:
|
||||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
version: "^5.0.0"
|
version: ^2.0.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
|
@ -6,35 +6,20 @@ import 'package:flutter_data_interface/flutter_data_interface.dart';
|
||||||
import 'package:flutter_introduction_interface/src/local_introduction.dart';
|
import 'package:flutter_introduction_interface/src/local_introduction.dart';
|
||||||
|
|
||||||
abstract class IntroductionInterface extends DataInterface {
|
abstract class IntroductionInterface extends DataInterface {
|
||||||
/// Constructs an instance of [IntroductionInterface].
|
|
||||||
///
|
|
||||||
/// The [token] is used for verification purposes.
|
|
||||||
IntroductionInterface() : super(token: _token);
|
IntroductionInterface() : super(token: _token);
|
||||||
|
|
||||||
static final Object _token = Object();
|
static final Object _token = Object();
|
||||||
|
|
||||||
static IntroductionInterface _instance = LocalIntroductionDataProvider();
|
static IntroductionInterface _instance = LocalIntroductionDataProvider();
|
||||||
|
|
||||||
/// Retrieves the current instance of [IntroductionInterface].
|
|
||||||
static IntroductionInterface get instance => _instance;
|
static IntroductionInterface get instance => _instance;
|
||||||
|
|
||||||
/// Sets the current instance of [IntroductionInterface].
|
|
||||||
///
|
|
||||||
/// Throws an error if the provided instance does not match the token.
|
|
||||||
static set instance(IntroductionInterface instance) {
|
static set instance(IntroductionInterface instance) {
|
||||||
DataInterface.verify(instance, _token);
|
DataInterface.verify(instance, _token);
|
||||||
_instance = instance;
|
_instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets whether the introduction is completed or not.
|
|
||||||
///
|
|
||||||
/// The [value] parameter specifies whether the introduction is completed.
|
|
||||||
/// By default, it is set to `true`.
|
|
||||||
Future<void> setCompleted({bool value = true});
|
Future<void> setCompleted({bool value = true});
|
||||||
|
|
||||||
/// Checks if the introduction should be shown.
|
|
||||||
///
|
|
||||||
/// Returns `true` if the introduction should be shown;
|
|
||||||
/// otherwise, returns `false`.
|
|
||||||
Future<bool> shouldShow();
|
Future<bool> shouldShow();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,9 @@
|
||||||
|
|
||||||
import 'package:flutter_introduction_interface/src/introduction_interface.dart';
|
import 'package:flutter_introduction_interface/src/introduction_interface.dart';
|
||||||
|
|
||||||
/// Provides local data storage for managing introduction data.
|
|
||||||
///
|
|
||||||
/// This class extends [IntroductionInterface] and implements methods to manage
|
|
||||||
/// introduction data locally.
|
|
||||||
class LocalIntroductionDataProvider extends IntroductionInterface {
|
class LocalIntroductionDataProvider extends IntroductionInterface {
|
||||||
/// Constructs an instance of [LocalIntroductionDataProvider].
|
|
||||||
///
|
|
||||||
/// Initializes the [hasViewed] flag to `false`.
|
|
||||||
LocalIntroductionDataProvider();
|
LocalIntroductionDataProvider();
|
||||||
|
|
||||||
/// Flag indicating whether the introduction has been viewed or not.
|
|
||||||
bool hasViewed = false;
|
bool hasViewed = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
name: flutter_introduction_interface
|
name: flutter_introduction_interface
|
||||||
description: A new Flutter package project.
|
description: A new Flutter package project.
|
||||||
version: 5.0.0
|
version: 2.0.1
|
||||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.0.0 <4.0.0'
|
sdk: '>=3.0.0 <4.0.0'
|
||||||
flutter: ">=1.17.0"
|
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_data_interface:
|
flutter_data_interface:
|
||||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
version: "^1.0.0"
|
version: ^1.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_lints: ^2.0.0
|
||||||
flutter_iconica_analysis:
|
flutter_iconica_analysis:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
|
|
|
@ -4,36 +4,15 @@
|
||||||
|
|
||||||
import 'package:flutter_introduction_interface/flutter_introduction_interface.dart';
|
import 'package:flutter_introduction_interface/flutter_introduction_interface.dart';
|
||||||
|
|
||||||
/// A service for managing introduction-related operations.
|
|
||||||
///
|
|
||||||
/// This class provides methods for handling introduction-related actions
|
|
||||||
/// such as skipping, completing,
|
|
||||||
/// and determining whether to show the introduction.
|
|
||||||
class IntroductionService {
|
class IntroductionService {
|
||||||
/// Constructs an instance of [IntroductionService].
|
|
||||||
///
|
|
||||||
/// Optionally takes a [dataProvider] parameter,
|
|
||||||
/// which is an implementation of [IntroductionInterface].
|
|
||||||
/// If no data provider is provided,
|
|
||||||
/// it defaults to [LocalIntroductionDataProvider].
|
|
||||||
IntroductionService([IntroductionInterface? dataProvider])
|
IntroductionService([IntroductionInterface? dataProvider])
|
||||||
: _dataProvider = dataProvider ?? LocalIntroductionDataProvider();
|
: _dataProvider = dataProvider ?? LocalIntroductionDataProvider();
|
||||||
|
|
||||||
late final IntroductionInterface _dataProvider;
|
late final IntroductionInterface _dataProvider;
|
||||||
|
|
||||||
/// Marks the introduction as skipped.
|
|
||||||
///
|
|
||||||
/// Calls [_dataProvider.setCompleted] with the value `true`.
|
|
||||||
Future<void> onSkip() => _dataProvider.setCompleted(value: true);
|
Future<void> onSkip() => _dataProvider.setCompleted(value: true);
|
||||||
|
|
||||||
/// Marks the introduction as completed.
|
|
||||||
///
|
|
||||||
/// Calls [_dataProvider.setCompleted] with the value `true`.
|
|
||||||
Future<void> onComplete() => _dataProvider.setCompleted(value: true);
|
Future<void> onComplete() => _dataProvider.setCompleted(value: true);
|
||||||
|
|
||||||
/// Checks whether the introduction should be shown.
|
|
||||||
///
|
|
||||||
/// Returns a `Future<bool>` indicating whether the
|
|
||||||
/// introduction should be shown.
|
|
||||||
Future<bool> shouldShow() => _dataProvider.shouldShow();
|
Future<bool> shouldShow() => _dataProvider.shouldShow();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
name: flutter_introduction_service
|
name: flutter_introduction_service
|
||||||
description: A new Flutter package project.
|
description: A new Flutter package project.
|
||||||
version: 5.0.0
|
version: 2.0.1
|
||||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.0.0 <4.0.0'
|
sdk: '>=3.0.0 <4.0.0'
|
||||||
flutter: ">=1.17.0"
|
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_introduction_interface:
|
flutter_introduction_interface:
|
||||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
version: "^5.0.0"
|
version: ^2.0.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_lints: ^2.0.0
|
||||||
flutter_iconica_analysis:
|
flutter_iconica_analysis:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
|
|
|
@ -5,27 +5,16 @@
|
||||||
import 'package:flutter_introduction_interface/flutter_introduction_interface.dart';
|
import 'package:flutter_introduction_interface/flutter_introduction_interface.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
/// Provides data storage using SharedPreferences for
|
|
||||||
/// managing introduction data.
|
|
||||||
///
|
|
||||||
/// This class extends [IntroductionInterface] and implements methods to manage
|
|
||||||
/// introduction data using SharedPreferences.
|
|
||||||
class SharedPreferencesIntroductionDataProvider extends IntroductionInterface {
|
class SharedPreferencesIntroductionDataProvider extends IntroductionInterface {
|
||||||
/// Constructs an instance of [SharedPreferencesIntroductionDataProvider].
|
|
||||||
SharedPreferencesIntroductionDataProvider();
|
SharedPreferencesIntroductionDataProvider();
|
||||||
|
|
||||||
SharedPreferences? _prefs;
|
SharedPreferences? _prefs;
|
||||||
String key = '_completedIntroduction';
|
String key = '_completedIntroduction';
|
||||||
|
|
||||||
/// Writes a key-value pair to SharedPreferences.
|
|
||||||
///
|
|
||||||
/// The [key] is the key under which to store the [value].
|
|
||||||
/// The [value] is the boolean value to be stored.
|
|
||||||
Future<void> _writeKeyValue(String key, bool value) async {
|
Future<void> _writeKeyValue(String key, bool value) async {
|
||||||
await _prefs!.setBool(key, value);
|
await _prefs!.setBool(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initializes the SharedPreferences instance.
|
|
||||||
Future<void> _init() async {
|
Future<void> _init() async {
|
||||||
_prefs ??= await SharedPreferences.getInstance();
|
_prefs ??= await SharedPreferences.getInstance();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
name: flutter_introduction_shared_preferences
|
name: flutter_introduction_shared_preferences
|
||||||
description: A new Flutter package project.
|
description: A new Flutter package project.
|
||||||
version: 5.0.0
|
version: 2.0.1
|
||||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.0.0 <4.0.0'
|
sdk: '>=3.0.0 <4.0.0'
|
||||||
flutter: ">=1.17.0"
|
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_introduction_interface:
|
flutter_introduction_interface:
|
||||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
version: "^5.0.0"
|
version: ^2.0.0
|
||||||
shared_preferences: "^2.2.0"
|
shared_preferences: ^2.2.3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_lints: ^2.0.0
|
||||||
flutter_iconica_analysis:
|
flutter_iconica_analysis:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 61 KiB |
Binary file not shown.
Before Width: | Height: | Size: 49 KiB |
Binary file not shown.
Before Width: | Height: | Size: 33 KiB |
|
@ -31,30 +31,30 @@ class MyApp extends StatelessWidget {
|
||||||
),
|
),
|
||||||
home: IntroductionScreen(
|
home: IntroductionScreen(
|
||||||
options: IntroductionOptions(
|
options: IntroductionOptions(
|
||||||
pages: (context) => [
|
pages: [
|
||||||
const IntroductionPage(
|
IntroductionPage(
|
||||||
title: Text('Basic Page'),
|
title: const Text('Basic Page'),
|
||||||
text: Text(
|
text: const Text(
|
||||||
'A page with some text and a widget in the middle.',
|
'A page with some text and a widget in the middle.',
|
||||||
),
|
),
|
||||||
graphic: FlutterLogo(size: 100),
|
graphic: const FlutterLogo(size: 100),
|
||||||
),
|
),
|
||||||
const IntroductionPage(
|
IntroductionPage(
|
||||||
title: Text('Layout Shift'),
|
title: const Text('Layout Shift'),
|
||||||
text: Text(
|
text: const Text(
|
||||||
'You can change the layout of a page to mix things up.',
|
'You can change the layout of a page to mix things up.',
|
||||||
),
|
),
|
||||||
graphic: FlutterLogo(size: 100),
|
graphic: const FlutterLogo(size: 100),
|
||||||
layoutStyle: IntroductionLayoutStyle.imageTop,
|
layoutStyle: IntroductionLayoutStyle.imageTop,
|
||||||
),
|
),
|
||||||
const IntroductionPage(
|
IntroductionPage(
|
||||||
title: Text(
|
title: const Text(
|
||||||
'Decoration',
|
'Decoration',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
begin: Alignment.topRight,
|
begin: Alignment.topRight,
|
||||||
end: Alignment.bottomLeft,
|
end: Alignment.bottomLeft,
|
||||||
|
@ -66,24 +66,24 @@ class MyApp extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
text: Text(
|
text: const Text(
|
||||||
'Add a Decoration to make a custom background, like a LinearGradient',
|
'Add a Decoration to make a custom background, like a LinearGradient',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
graphic: FlutterLogo(
|
graphic: const FlutterLogo(
|
||||||
size: 100,
|
size: 100,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const IntroductionPage(
|
IntroductionPage(
|
||||||
title: Text(
|
title: const Text(
|
||||||
'Background Image',
|
'Background Image',
|
||||||
),
|
),
|
||||||
text: Text(
|
text: const Text(
|
||||||
'Add a Decoration with a DecorationImage, to add an background image',
|
'Add a Decoration with a DecorationImage, to add an background image',
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
image: AssetImage(
|
image: AssetImage(
|
||||||
|
|
|
@ -18,7 +18,7 @@ dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
flutter_lints: ^3.0.1
|
flutter_lints: ^2.0.0
|
||||||
|
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_introduction_widget/flutter_introduction_widget.dart';
|
|
||||||
|
|
||||||
List<IntroductionPage> defaultIntroductionPages(BuildContext context) {
|
|
||||||
var theme = Theme.of(context);
|
|
||||||
return [
|
|
||||||
IntroductionPage(
|
|
||||||
title: Column(
|
|
||||||
children: [
|
|
||||||
const SizedBox(height: 50),
|
|
||||||
Text(
|
|
||||||
'welcome to iconinstagram',
|
|
||||||
style: theme.textTheme.headlineLarge,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
graphic: const Image(
|
|
||||||
image: AssetImage(
|
|
||||||
'assets/first.png',
|
|
||||||
package: 'flutter_introduction_widget',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
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(
|
|
||||||
title: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
const SizedBox(height: 50),
|
|
||||||
Text(
|
|
||||||
'discover iconinstagram',
|
|
||||||
style: theme.textTheme.headlineLarge,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
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.',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: theme.textTheme.bodyMedium,
|
|
||||||
),
|
|
||||||
graphic: const Image(
|
|
||||||
image: AssetImage(
|
|
||||||
'assets/second.png',
|
|
||||||
package: 'flutter_introduction_widget',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
IntroductionPage(
|
|
||||||
title: Column(
|
|
||||||
children: [
|
|
||||||
const SizedBox(height: 50),
|
|
||||||
Text(
|
|
||||||
'elevate your experience',
|
|
||||||
style: theme.textTheme.headlineLarge,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
graphic: const Image(
|
|
||||||
image: AssetImage(
|
|
||||||
'assets/third.png',
|
|
||||||
package: 'flutter_introduction_widget',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
|
@ -3,7 +3,6 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_introduction_widget/src/config/default_introduction_pages.dart';
|
|
||||||
|
|
||||||
enum IntroductionScreenMode { showNever, showAlways, showOnce }
|
enum IntroductionScreenMode { showNever, showAlways, showOnce }
|
||||||
|
|
||||||
|
@ -43,7 +42,7 @@ class IntroductionPage {
|
||||||
///
|
///
|
||||||
/// The [background] is fully optional and if not provided will show the
|
/// The [background] is fully optional and if not provided will show the
|
||||||
/// [ThemeData.colorScheme.background] as default.
|
/// [ThemeData.colorScheme.background] as default.
|
||||||
const IntroductionPage({
|
IntroductionPage({
|
||||||
this.title,
|
this.title,
|
||||||
this.text,
|
this.text,
|
||||||
this.graphic,
|
this.graphic,
|
||||||
|
@ -60,12 +59,11 @@ class IntroductionPage {
|
||||||
class IntroductionOptions {
|
class IntroductionOptions {
|
||||||
const IntroductionOptions({
|
const IntroductionOptions({
|
||||||
this.introductionTranslations = const IntroductionTranslations(),
|
this.introductionTranslations = const IntroductionTranslations(),
|
||||||
this.introductionButtonTextstyles = const IntroductionButtonTextstyles(),
|
this.indicatorMode = IndicatorMode.dash,
|
||||||
this.indicatorMode = IndicatorMode.dot,
|
|
||||||
this.indicatorBuilder,
|
this.indicatorBuilder,
|
||||||
this.layoutStyle = IntroductionLayoutStyle.imageBottom,
|
this.layoutStyle = IntroductionLayoutStyle.imageCenter,
|
||||||
this.pages = defaultIntroductionPages,
|
this.pages = const [],
|
||||||
this.buttonMode = IntroductionScreenButtonMode.text,
|
this.buttonMode = IntroductionScreenButtonMode.disabled,
|
||||||
this.tapEnabled = false,
|
this.tapEnabled = false,
|
||||||
this.mode = IntroductionScreenMode.showNever,
|
this.mode = IntroductionScreenMode.showNever,
|
||||||
this.textAlign = TextAlign.center,
|
this.textAlign = TextAlign.center,
|
||||||
|
@ -73,9 +71,6 @@ class IntroductionOptions {
|
||||||
this.skippable = false,
|
this.skippable = false,
|
||||||
this.buttonBuilder,
|
this.buttonBuilder,
|
||||||
this.controlMode = IntroductionControlMode.previousNextButton,
|
this.controlMode = IntroductionControlMode.previousNextButton,
|
||||||
this.dotSize = 12,
|
|
||||||
this.dotSpacing = 24,
|
|
||||||
this.dotColor,
|
|
||||||
}) : assert(
|
}) : assert(
|
||||||
!(identical(indicatorMode, IndicatorMode.custom) &&
|
!(identical(indicatorMode, IndicatorMode.custom) &&
|
||||||
indicatorBuilder == null),
|
indicatorBuilder == null),
|
||||||
|
@ -96,7 +91,7 @@ class IntroductionOptions {
|
||||||
|
|
||||||
/// List of introduction pages to set the text, icons or images for the
|
/// List of introduction pages to set the text, icons or images for the
|
||||||
/// introduction screens.
|
/// introduction screens.
|
||||||
final List<IntroductionPage> Function(BuildContext context) pages;
|
final List<IntroductionPage> pages;
|
||||||
|
|
||||||
/// Determines whether the user can tap the screen to go to the next
|
/// Determines whether the user can tap the screen to go to the next
|
||||||
/// introduction screen.
|
/// introduction screen.
|
||||||
|
@ -197,29 +192,9 @@ class IntroductionOptions {
|
||||||
/// - Finish
|
/// - Finish
|
||||||
final IntroductionTranslations introductionTranslations;
|
final IntroductionTranslations introductionTranslations;
|
||||||
|
|
||||||
/// The textstyles for all buttons on the introductionpages
|
|
||||||
///
|
|
||||||
/// See [IntroductionButtonTextstyles] for more information
|
|
||||||
/// The following buttons have a textstyle:
|
|
||||||
/// - Skip
|
|
||||||
/// - Next
|
|
||||||
/// - Previous
|
|
||||||
/// - 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({
|
IntroductionOptions copyWith({
|
||||||
IntroductionScreenMode? mode,
|
IntroductionScreenMode? mode,
|
||||||
List<IntroductionPage> Function(BuildContext context)? pages,
|
List<IntroductionPage>? pages,
|
||||||
bool? tapEnabled,
|
bool? tapEnabled,
|
||||||
IntroductionScreenButtonMode? buttonMode,
|
IntroductionScreenButtonMode? buttonMode,
|
||||||
IntroductionLayoutStyle? layoutStyle,
|
IntroductionLayoutStyle? layoutStyle,
|
||||||
|
@ -237,7 +212,6 @@ class IntroductionOptions {
|
||||||
Widget Function(BuildContext, VoidCallback, Widget, IntroductionButtonType)?
|
Widget Function(BuildContext, VoidCallback, Widget, IntroductionButtonType)?
|
||||||
buttonBuilder,
|
buttonBuilder,
|
||||||
IntroductionTranslations? introductionTranslations,
|
IntroductionTranslations? introductionTranslations,
|
||||||
IntroductionButtonTextstyles? introductionButtonTextstyles,
|
|
||||||
}) =>
|
}) =>
|
||||||
IntroductionOptions(
|
IntroductionOptions(
|
||||||
mode: mode ?? this.mode,
|
mode: mode ?? this.mode,
|
||||||
|
@ -254,33 +228,19 @@ class IntroductionOptions {
|
||||||
buttonBuilder: buttonBuilder ?? this.buttonBuilder,
|
buttonBuilder: buttonBuilder ?? this.buttonBuilder,
|
||||||
introductionTranslations:
|
introductionTranslations:
|
||||||
introductionTranslations ?? this.introductionTranslations,
|
introductionTranslations ?? this.introductionTranslations,
|
||||||
introductionButtonTextstyles:
|
|
||||||
introductionButtonTextstyles ?? this.introductionButtonTextstyles,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
class IntroductionTranslations {
|
class IntroductionTranslations {
|
||||||
const IntroductionTranslations({
|
const IntroductionTranslations({
|
||||||
this.skipButton = 'Skip',
|
this.skipButton = 'skip',
|
||||||
this.nextButton = 'Next',
|
this.nextButton = 'next',
|
||||||
this.previousButton = 'Previous',
|
this.previousButton = 'previous',
|
||||||
this.finishButton = 'Get started',
|
this.finishButton = 'finish',
|
||||||
});
|
});
|
||||||
final String skipButton;
|
final String skipButton;
|
||||||
final String nextButton;
|
final String nextButton;
|
||||||
final String previousButton;
|
final String previousButton;
|
||||||
final String finishButton;
|
final String finishButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
class IntroductionButtonTextstyles {
|
|
||||||
const IntroductionButtonTextstyles({
|
|
||||||
this.skipButtonStyle,
|
|
||||||
this.nextButtonStyle,
|
|
||||||
this.previousButtonStyle,
|
|
||||||
this.finishButtonStyle,
|
|
||||||
});
|
|
||||||
final TextStyle? skipButtonStyle;
|
|
||||||
final TextStyle? nextButtonStyle;
|
|
||||||
final TextStyle? previousButtonStyle;
|
|
||||||
final TextStyle? finishButtonStyle;
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,12 +11,7 @@ import 'package:flutter_introduction_widget/src/widgets/background.dart';
|
||||||
import 'package:flutter_introduction_widget/src/widgets/indicator.dart';
|
import 'package:flutter_introduction_widget/src/widgets/indicator.dart';
|
||||||
import 'package:flutter_introduction_widget/src/widgets/page_content.dart';
|
import 'package:flutter_introduction_widget/src/widgets/page_content.dart';
|
||||||
|
|
||||||
/// A screen widget for displaying a multi-page introduction.
|
|
||||||
///
|
|
||||||
/// This widget provides a multi-page introduction experience with options
|
|
||||||
/// for handling navigation and completion callbacks.
|
|
||||||
class MultiPageIntroductionScreen extends StatefulWidget {
|
class MultiPageIntroductionScreen extends StatefulWidget {
|
||||||
/// Creates a new instance of [MultiPageIntroductionScreen].
|
|
||||||
const MultiPageIntroductionScreen({
|
const MultiPageIntroductionScreen({
|
||||||
required this.options,
|
required this.options,
|
||||||
required this.onComplete,
|
required this.onComplete,
|
||||||
|
@ -27,22 +22,12 @@ class MultiPageIntroductionScreen extends StatefulWidget {
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Callback function triggered when the introduction is completed.
|
|
||||||
final VoidCallback onComplete;
|
final VoidCallback onComplete;
|
||||||
|
|
||||||
/// Callback function triggered when the "Next" button is pressed.
|
|
||||||
final void Function(IntroductionPage)? onNext;
|
|
||||||
|
|
||||||
/// Callback function triggered when the "Previous" button is pressed.
|
|
||||||
final void Function(IntroductionPage)? onPrevious;
|
|
||||||
|
|
||||||
/// Callback function triggered when the "Skip" button is pressed.
|
|
||||||
final VoidCallback? onSkip;
|
final VoidCallback? onSkip;
|
||||||
|
final void Function(IntroductionPage)? onNext;
|
||||||
/// Physics for the scrolling behavior.
|
final void Function(IntroductionPage)? onPrevious;
|
||||||
final ScrollPhysics? physics;
|
final ScrollPhysics? physics;
|
||||||
|
|
||||||
/// Introduction options specifying the configuration of the introduction.
|
|
||||||
final IntroductionOptions options;
|
final IntroductionOptions options;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -50,9 +35,6 @@ class MultiPageIntroductionScreen extends StatefulWidget {
|
||||||
_MultiPageIntroductionScreenState();
|
_MultiPageIntroductionScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// State class for [MultiPageIntroductionScreen].
|
|
||||||
///
|
|
||||||
/// Manages the state and behavior of the [MultiPageIntroductionScreen] widget.
|
|
||||||
class _MultiPageIntroductionScreenState
|
class _MultiPageIntroductionScreenState
|
||||||
extends State<MultiPageIntroductionScreen> {
|
extends State<MultiPageIntroductionScreen> {
|
||||||
final PageController _controller = PageController();
|
final PageController _controller = PageController();
|
||||||
|
@ -77,7 +59,7 @@ class _MultiPageIntroductionScreenState
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var pages = widget.options.pages.call(context);
|
var pages = widget.options.pages;
|
||||||
var translations = widget.options.introductionTranslations;
|
var translations = widget.options.introductionTranslations;
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
|
@ -150,21 +132,15 @@ class _MultiPageIntroductionScreenState
|
||||||
AnimatedBuilder(
|
AnimatedBuilder(
|
||||||
animation: _currentPage,
|
animation: _currentPage,
|
||||||
builder: (context, _) => Indicator(
|
builder: (context, _) => Indicator(
|
||||||
options: widget.options,
|
|
||||||
indicatorBuilder: widget.options.indicatorBuilder,
|
indicatorBuilder: widget.options.indicatorBuilder,
|
||||||
mode: widget.options.indicatorMode,
|
mode: widget.options.indicatorMode,
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
count: pages.length,
|
count: pages.length,
|
||||||
index: _currentPage.value,
|
index: _currentPage.value,
|
||||||
dotSize: widget.options.dotSize,
|
|
||||||
dotSpacing: widget.options.dotSpacing,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.all(32),
|
||||||
vertical: 40,
|
|
||||||
horizontal: 20,
|
|
||||||
),
|
|
||||||
child: AnimatedBuilder(
|
child: AnimatedBuilder(
|
||||||
animation: _controller,
|
animation: _controller,
|
||||||
builder: (context, _) {
|
builder: (context, _) {
|
||||||
|
@ -276,14 +252,14 @@ class ExplainerPage extends StatelessWidget {
|
||||||
title: Padding(
|
title: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||||
child: DefaultTextStyle(
|
child: DefaultTextStyle(
|
||||||
style: theme.textTheme.titleMedium!,
|
style: theme.textTheme.displayMedium!,
|
||||||
child: page.title ?? Text('introduction.$index.title'),
|
child: page.title ?? Text('introduction.$index.title'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
text: Padding(
|
text: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||||
child: DefaultTextStyle(
|
child: DefaultTextStyle(
|
||||||
style: theme.textTheme.bodyMedium!,
|
style: theme.textTheme.bodyLarge!,
|
||||||
child: page.text ?? Text('introduction.$index.description'),
|
child: page.text ?? Text('introduction.$index.description'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -342,159 +318,49 @@ class IntroductionTwoButtons extends StatelessWidget {
|
||||||
var translations = options.introductionTranslations;
|
var translations = options.introductionTranslations;
|
||||||
var showFinishButton =
|
var showFinishButton =
|
||||||
options.buttonMode == IntroductionScreenButtonMode.singleFinish;
|
options.buttonMode == IntroductionScreenButtonMode.singleFinish;
|
||||||
var theme = Theme.of(context);
|
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
if (options.buttonMode == IntroductionScreenButtonMode.text) ...[
|
if (options.buttonMode == IntroductionScreenButtonMode.text) ...[
|
||||||
Flexible(
|
if (previous) ...[
|
||||||
child: Padding(
|
options.buttonBuilder?.call(
|
||||||
padding: const EdgeInsets.only(right: 6),
|
context,
|
||||||
child: ConstrainedBox(
|
_previous,
|
||||||
constraints: const BoxConstraints(
|
Text(translations.previousButton),
|
||||||
maxWidth: 180,
|
IntroductionButtonType.previous,
|
||||||
|
) ??
|
||||||
|
TextButton(
|
||||||
|
onPressed: _previous,
|
||||||
|
child: Text(translations.previousButton),
|
||||||
),
|
),
|
||||||
child: Opacity(
|
] else
|
||||||
opacity: previous ? 1 : 0,
|
const SizedBox.shrink(),
|
||||||
child: IgnorePointer(
|
|
||||||
ignoring: !previous,
|
|
||||||
child: options.buttonBuilder?.call(
|
|
||||||
context,
|
|
||||||
_previous,
|
|
||||||
Text(
|
|
||||||
translations.previousButton,
|
|
||||||
style: options.introductionButtonTextstyles
|
|
||||||
.previousButtonStyle ??
|
|
||||||
theme.textTheme.bodyMedium,
|
|
||||||
),
|
|
||||||
IntroductionButtonType.previous,
|
|
||||||
) ??
|
|
||||||
InkWell(
|
|
||||||
onTap: _previous,
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
border: Border.all(
|
|
||||||
color: const Color(
|
|
||||||
0xff979797,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Center(
|
|
||||||
child: Padding(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.symmetric(vertical: 4),
|
|
||||||
child: Text(
|
|
||||||
translations.previousButton,
|
|
||||||
style: options.introductionButtonTextstyles
|
|
||||||
.previousButtonStyle ??
|
|
||||||
theme.textTheme.bodyMedium,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (next) ...[
|
if (next) ...[
|
||||||
Flexible(
|
options.buttonBuilder?.call(
|
||||||
child: Padding(
|
context,
|
||||||
padding: const EdgeInsets.only(left: 6),
|
_next,
|
||||||
child: ConstrainedBox(
|
Text(translations.nextButton),
|
||||||
constraints: const BoxConstraints(
|
IntroductionButtonType.next,
|
||||||
maxWidth: 180,
|
) ??
|
||||||
),
|
TextButton(
|
||||||
child: options.buttonBuilder?.call(
|
onPressed: _next,
|
||||||
context,
|
child: Text(translations.nextButton),
|
||||||
_next,
|
|
||||||
Text(
|
|
||||||
translations.nextButton,
|
|
||||||
style: options.introductionButtonTextstyles
|
|
||||||
.nextButtonStyle ??
|
|
||||||
theme.textTheme.bodyMedium,
|
|
||||||
),
|
|
||||||
IntroductionButtonType.next,
|
|
||||||
) ??
|
|
||||||
InkWell(
|
|
||||||
onTap: _next,
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
border: Border.all(
|
|
||||||
color: const Color(
|
|
||||||
0xff979797,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
|
||||||
child: Text(
|
|
||||||
translations.nextButton,
|
|
||||||
style: options.introductionButtonTextstyles
|
|
||||||
.nextButtonStyle ??
|
|
||||||
theme.textTheme.bodyMedium,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
] else if (last) ...[
|
] else if (last) ...[
|
||||||
Flexible(
|
options.buttonBuilder?.call(
|
||||||
child: Padding(
|
context,
|
||||||
padding: const EdgeInsets.only(left: 6),
|
() {
|
||||||
child: ConstrainedBox(
|
onFinish?.call();
|
||||||
constraints: const BoxConstraints(
|
},
|
||||||
maxWidth: 180,
|
Text(translations.finishButton),
|
||||||
),
|
IntroductionButtonType.finish,
|
||||||
child: options.buttonBuilder?.call(
|
) ??
|
||||||
context,
|
TextButton(
|
||||||
() {
|
onPressed: () {
|
||||||
onFinish?.call();
|
onFinish?.call();
|
||||||
},
|
},
|
||||||
Text(
|
child: Text(translations.finishButton),
|
||||||
translations.finishButton,
|
|
||||||
style: options.introductionButtonTextstyles
|
|
||||||
.finishButtonStyle ??
|
|
||||||
theme.textTheme.bodyMedium,
|
|
||||||
),
|
|
||||||
IntroductionButtonType.finish,
|
|
||||||
) ??
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
onFinish?.call();
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
border: Border.all(
|
|
||||||
color: const Color(
|
|
||||||
0xff979797,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
|
||||||
child: Text(
|
|
||||||
translations.finishButton,
|
|
||||||
style: options.introductionButtonTextstyles
|
|
||||||
.finishButtonStyle ??
|
|
||||||
theme.textTheme.bodyMedium,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
] else ...[
|
] else ...[
|
||||||
const SizedBox.shrink(),
|
const SizedBox.shrink(),
|
||||||
],
|
],
|
||||||
|
@ -508,53 +374,20 @@ class IntroductionTwoButtons extends StatelessWidget {
|
||||||
maintainState: true,
|
maintainState: true,
|
||||||
maintainInteractivity: false,
|
maintainInteractivity: false,
|
||||||
child: Align(
|
child: Align(
|
||||||
child: Flexible(
|
child: options.buttonBuilder?.call(
|
||||||
child: ConstrainedBox(
|
context,
|
||||||
constraints: const BoxConstraints(
|
() {
|
||||||
maxWidth: 180,
|
onFinish?.call();
|
||||||
|
},
|
||||||
|
Text(translations.finishButton),
|
||||||
|
IntroductionButtonType.finish,
|
||||||
|
) ??
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
onFinish?.call();
|
||||||
|
},
|
||||||
|
child: Text(translations.finishButton),
|
||||||
),
|
),
|
||||||
child: options.buttonBuilder?.call(
|
|
||||||
context,
|
|
||||||
() {
|
|
||||||
onFinish?.call();
|
|
||||||
},
|
|
||||||
Text(
|
|
||||||
translations.finishButton,
|
|
||||||
style: options.introductionButtonTextstyles
|
|
||||||
.finishButtonStyle ??
|
|
||||||
theme.textTheme.bodyMedium,
|
|
||||||
),
|
|
||||||
IntroductionButtonType.finish,
|
|
||||||
) ??
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
onFinish?.call();
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
border: Border.all(
|
|
||||||
color: const Color(
|
|
||||||
0xff979797,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Center(
|
|
||||||
child: Padding(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.symmetric(vertical: 4),
|
|
||||||
child: Text(
|
|
||||||
translations.finishButton,
|
|
||||||
style: options.introductionButtonTextstyles
|
|
||||||
.finishButtonStyle ??
|
|
||||||
theme.textTheme.bodyMedium,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -586,31 +419,16 @@ class IntroductionOneButton extends StatelessWidget {
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Options specifying the configuration of the introduction.
|
|
||||||
final IntroductionOptions options;
|
final IntroductionOptions options;
|
||||||
|
|
||||||
/// Controller for managing the pages of the introduction.
|
|
||||||
final PageController controller;
|
final PageController controller;
|
||||||
|
|
||||||
/// Callback function triggered when the introduction is completed.
|
|
||||||
final VoidCallback? onFinish;
|
final VoidCallback? onFinish;
|
||||||
|
|
||||||
/// Callback function triggered when the "Next" button is pressed.
|
|
||||||
final VoidCallback? onNext;
|
final VoidCallback? onNext;
|
||||||
|
|
||||||
/// Callback function triggered when the "Previous" button is pressed.
|
|
||||||
final VoidCallback? onPrevious;
|
final VoidCallback? onPrevious;
|
||||||
|
|
||||||
/// Indicates whether there are previous pages.
|
|
||||||
final bool previous;
|
final bool previous;
|
||||||
|
|
||||||
/// Indicates whether there are next pages.
|
|
||||||
final bool next;
|
final bool next;
|
||||||
|
|
||||||
/// Indicates whether this is the last page.
|
|
||||||
final bool last;
|
final bool last;
|
||||||
|
|
||||||
/// Handles the navigation to the previous page.
|
|
||||||
Future<void> _previous() async {
|
Future<void> _previous() async {
|
||||||
await controller.previousPage(
|
await controller.previousPage(
|
||||||
duration: kAnimationDuration,
|
duration: kAnimationDuration,
|
||||||
|
@ -632,59 +450,37 @@ class IntroductionOneButton extends StatelessWidget {
|
||||||
() {
|
() {
|
||||||
onFinish?.call();
|
onFinish?.call();
|
||||||
},
|
},
|
||||||
Text(
|
Text(translations.finishButton),
|
||||||
translations.finishButton,
|
|
||||||
style:
|
|
||||||
options.introductionButtonTextstyles.finishButtonStyle,
|
|
||||||
),
|
|
||||||
IntroductionButtonType.finish,
|
IntroductionButtonType.finish,
|
||||||
) ??
|
) ??
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
onFinish?.call();
|
onFinish?.call();
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(translations.finishButton),
|
||||||
translations.finishButton,
|
|
||||||
style:
|
|
||||||
options.introductionButtonTextstyles.finishButtonStyle,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
] else ...[
|
] else ...[
|
||||||
options.buttonBuilder?.call(
|
options.buttonBuilder?.call(
|
||||||
context,
|
context,
|
||||||
_next,
|
_next,
|
||||||
Text(
|
Text(translations.nextButton),
|
||||||
translations.nextButton,
|
|
||||||
style: options.introductionButtonTextstyles.nextButtonStyle,
|
|
||||||
),
|
|
||||||
IntroductionButtonType.next,
|
IntroductionButtonType.next,
|
||||||
) ??
|
) ??
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: _next,
|
onPressed: _next,
|
||||||
child: Text(
|
child: Text(translations.nextButton),
|
||||||
translations.nextButton,
|
|
||||||
style: options.introductionButtonTextstyles.nextButtonStyle,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
if (previous) ...[
|
if (previous) ...[
|
||||||
options.buttonBuilder?.call(
|
options.buttonBuilder?.call(
|
||||||
context,
|
context,
|
||||||
_previous,
|
_previous,
|
||||||
Text(
|
Text(translations.previousButton),
|
||||||
translations.previousButton,
|
|
||||||
style: options
|
|
||||||
.introductionButtonTextstyles.previousButtonStyle,
|
|
||||||
),
|
|
||||||
IntroductionButtonType.previous,
|
IntroductionButtonType.previous,
|
||||||
) ??
|
) ??
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: _previous,
|
onPressed: _previous,
|
||||||
child: Text(
|
child: Text(translations.previousButton),
|
||||||
translations.previousButton,
|
|
||||||
style: options
|
|
||||||
.introductionButtonTextstyles.previousButtonStyle,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
] else ...[
|
] else ...[
|
||||||
options.buttonBuilder?.call(
|
options.buttonBuilder?.call(
|
||||||
|
@ -692,22 +488,14 @@ class IntroductionOneButton extends StatelessWidget {
|
||||||
() {
|
() {
|
||||||
onFinish?.call();
|
onFinish?.call();
|
||||||
},
|
},
|
||||||
Text(
|
Text(translations.finishButton),
|
||||||
translations.finishButton,
|
|
||||||
style:
|
|
||||||
options.introductionButtonTextstyles.finishButtonStyle,
|
|
||||||
),
|
|
||||||
IntroductionButtonType.skip,
|
IntroductionButtonType.skip,
|
||||||
) ??
|
) ??
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
onFinish?.call();
|
onFinish?.call();
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(translations.finishButton),
|
||||||
translations.finishButton,
|
|
||||||
style:
|
|
||||||
options.introductionButtonTextstyles.finishButtonStyle,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
@ -737,31 +525,16 @@ class IntroductionIconButtons extends StatelessWidget {
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Options specifying the configuration of the introduction.
|
|
||||||
final IntroductionOptions options;
|
final IntroductionOptions options;
|
||||||
|
|
||||||
/// Controller for managing the pages of the introduction.
|
|
||||||
final PageController controller;
|
final PageController controller;
|
||||||
|
|
||||||
/// Callback function triggered when the introduction is completed.
|
|
||||||
final VoidCallback? onFinish;
|
final VoidCallback? onFinish;
|
||||||
|
|
||||||
/// Callback function triggered when the "Next" button is pressed.
|
|
||||||
final VoidCallback? onNext;
|
final VoidCallback? onNext;
|
||||||
|
|
||||||
/// Callback function triggered when the "Previous" button is pressed.
|
|
||||||
final VoidCallback? onPrevious;
|
final VoidCallback? onPrevious;
|
||||||
|
|
||||||
/// Indicates whether there are previous pages.
|
|
||||||
final bool previous;
|
final bool previous;
|
||||||
|
|
||||||
/// Indicates whether there are next pages.
|
|
||||||
final bool next;
|
final bool next;
|
||||||
|
|
||||||
/// Indicates whether this is the last page.
|
|
||||||
final bool last;
|
final bool last;
|
||||||
|
|
||||||
/// Handles the navigation to the previous page.
|
|
||||||
Future<void> _previous() async {
|
Future<void> _previous() async {
|
||||||
await controller.previousPage(
|
await controller.previousPage(
|
||||||
duration: kAnimationDuration,
|
duration: kAnimationDuration,
|
||||||
|
|
|
@ -6,15 +6,12 @@ import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
import 'package:flutter_introduction_widget/src/config/introduction.dart';
|
import 'package:flutter_introduction_widget/src/config/introduction.dart';
|
||||||
|
|
||||||
/// Widget representing a single introduction page.
|
|
||||||
class SingleIntroductionPage extends StatelessWidget {
|
class SingleIntroductionPage extends StatelessWidget {
|
||||||
/// Constructs a [SingleIntroductionPage] widget.
|
|
||||||
const SingleIntroductionPage({
|
const SingleIntroductionPage({
|
||||||
required this.options,
|
required this.options,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Options specifying the configuration of the introduction.
|
|
||||||
final IntroductionOptions options;
|
final IntroductionOptions options;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -4,28 +4,21 @@
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// Widget representing a background with optional decoration.
|
|
||||||
class Background extends StatelessWidget {
|
class Background extends StatelessWidget {
|
||||||
/// Constructs a Background widget.
|
|
||||||
const Background({
|
const Background({
|
||||||
required this.child,
|
required this.child,
|
||||||
this.background,
|
this.background,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Optional decoration for the background.
|
|
||||||
final BoxDecoration? background;
|
final BoxDecoration? background;
|
||||||
|
|
||||||
/// The widget to be placed on the background.
|
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
var background = this.background ??
|
var background =
|
||||||
BoxDecoration(
|
this.background ?? BoxDecoration(color: theme.colorScheme.surface);
|
||||||
color: theme.colorScheme.surface,
|
|
||||||
);
|
|
||||||
var size = MediaQuery.of(context).size;
|
var size = MediaQuery.of(context).size;
|
||||||
return Container(
|
return Container(
|
||||||
width: size.width,
|
width: size.width,
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_introduction_widget/src/config/introduction.dart';
|
import 'package:flutter_introduction_widget/src/config/introduction.dart';
|
||||||
|
@ -15,9 +16,6 @@ class Indicator extends StatelessWidget {
|
||||||
required this.count,
|
required this.count,
|
||||||
required this.index,
|
required this.index,
|
||||||
required this.indicatorBuilder,
|
required this.indicatorBuilder,
|
||||||
required this.dotSize,
|
|
||||||
required this.dotSpacing,
|
|
||||||
required this.options,
|
|
||||||
super.key,
|
super.key,
|
||||||
}) : assert(
|
}) : assert(
|
||||||
!(mode == IndicatorMode.custom && indicatorBuilder == null),
|
!(mode == IndicatorMode.custom && indicatorBuilder == null),
|
||||||
|
@ -25,29 +23,16 @@ class Indicator extends StatelessWidget {
|
||||||
'must be provided',
|
'must be provided',
|
||||||
);
|
);
|
||||||
|
|
||||||
/// The mode of the indicator.
|
|
||||||
final IndicatorMode mode;
|
final IndicatorMode mode;
|
||||||
|
|
||||||
/// The PageController for which the indicator is displayed.
|
|
||||||
final PageController controller;
|
final PageController controller;
|
||||||
|
final Widget Function(
|
||||||
/// The total number of items managed by the PageController.
|
BuildContext,
|
||||||
final int count;
|
PageController,
|
||||||
|
int,
|
||||||
/// The index of the current item in the PageController.
|
int,
|
||||||
|
)? indicatorBuilder;
|
||||||
final int index;
|
final int index;
|
||||||
|
final int count;
|
||||||
/// Builder function for a custom indicator.
|
|
||||||
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -57,10 +42,9 @@ class Indicator extends StatelessWidget {
|
||||||
return indicatorBuilder!.call(context, controller, index, count);
|
return indicatorBuilder!.call(context, controller, index, count);
|
||||||
case IndicatorMode.dot:
|
case IndicatorMode.dot:
|
||||||
return DotsIndicator(
|
return DotsIndicator(
|
||||||
dotSize: dotSize,
|
|
||||||
dotSpacing: dotSpacing,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
color: options.dotColor ?? theme.colorScheme.primary,
|
color: theme.colorScheme.primary,
|
||||||
|
dotcolor: theme.colorScheme.secondary,
|
||||||
itemCount: count,
|
itemCount: count,
|
||||||
onPageSelected: (int page) {
|
onPageSelected: (int page) {
|
||||||
unawaited(
|
unawaited(
|
||||||
|
@ -74,9 +58,8 @@ class Indicator extends StatelessWidget {
|
||||||
);
|
);
|
||||||
case IndicatorMode.dash:
|
case IndicatorMode.dash:
|
||||||
return DashIndicator(
|
return DashIndicator(
|
||||||
color: theme.colorScheme.primary,
|
|
||||||
controller: controller,
|
controller: controller,
|
||||||
selectedColor: options.dotColor ?? theme.colorScheme.primary,
|
selectedColor: theme.colorScheme.primary,
|
||||||
itemCount: count,
|
itemCount: count,
|
||||||
onPageSelected: (int page) {
|
onPageSelected: (int page) {
|
||||||
unawaited(
|
unawaited(
|
||||||
|
@ -101,20 +84,10 @@ class DashIndicator extends AnimatedWidget {
|
||||||
this.color = Colors.white,
|
this.color = Colors.white,
|
||||||
super.key,
|
super.key,
|
||||||
}) : super(listenable: controller);
|
}) : super(listenable: controller);
|
||||||
|
|
||||||
/// The PageController for which the indicator is displayed.
|
|
||||||
final PageController controller;
|
final PageController controller;
|
||||||
|
|
||||||
/// The color of the dashes.
|
|
||||||
final Color color;
|
final Color color;
|
||||||
|
|
||||||
/// The color of the selected dash.
|
|
||||||
final Color selectedColor;
|
final Color selectedColor;
|
||||||
|
|
||||||
/// The total number of items managed by the PageController.
|
|
||||||
final int itemCount;
|
final int itemCount;
|
||||||
|
|
||||||
/// Callback function called when a dash is selected.
|
|
||||||
final Function(int) onPageSelected;
|
final Function(int) onPageSelected;
|
||||||
|
|
||||||
int _getPage() {
|
int _getPage() {
|
||||||
|
@ -164,15 +137,16 @@ class DotsIndicator extends AnimatedWidget {
|
||||||
const DotsIndicator({
|
const DotsIndicator({
|
||||||
required this.controller,
|
required this.controller,
|
||||||
this.color = Colors.white,
|
this.color = Colors.white,
|
||||||
|
this.dotcolor = Colors.green,
|
||||||
this.itemCount,
|
this.itemCount,
|
||||||
this.onPageSelected,
|
this.onPageSelected,
|
||||||
this.dotSize = 8.0,
|
|
||||||
this.dotSpacing = 24.0,
|
|
||||||
super.key,
|
super.key,
|
||||||
}) : super(
|
}) : super(
|
||||||
listenable: controller,
|
listenable: controller,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// The PageController that this DotsIndicator is representing.
|
||||||
|
final Color? dotcolor;
|
||||||
final PageController controller;
|
final PageController controller;
|
||||||
|
|
||||||
/// The number of items managed by the PageController
|
/// The number of items managed by the PageController
|
||||||
|
@ -187,31 +161,47 @@ class DotsIndicator extends AnimatedWidget {
|
||||||
final Color color;
|
final Color color;
|
||||||
|
|
||||||
// The base size of the dots
|
// The base size of the dots
|
||||||
final double dotSize;
|
static const double _kDotSize = 4.0;
|
||||||
final double dotSpacing;
|
|
||||||
|
|
||||||
Widget _buildDot(int index) => SizedBox(
|
// The increase in the size of the selected dot
|
||||||
width: dotSpacing,
|
static const double _kMaxZoom = 2.0;
|
||||||
child: Center(
|
|
||||||
child: Material(
|
// The distance between the center of each dot
|
||||||
color:
|
static const double _kDotSpacing = 12.0;
|
||||||
(((controller.page ?? controller.initialPage).round()) == index
|
|
||||||
? color
|
Widget _buildDot(int index) {
|
||||||
: color.withAlpha(62)),
|
var selectedness = Curves.easeOut.transform(
|
||||||
type: MaterialType.circle,
|
max(
|
||||||
child: Container(
|
0.0,
|
||||||
decoration: const BoxDecoration(
|
1.0 -
|
||||||
shape: BoxShape.circle,
|
((controller.page ?? controller.initialPage).round() - index).abs(),
|
||||||
),
|
),
|
||||||
width: dotSize,
|
);
|
||||||
height: dotSize,
|
var zoom = 1.0 + (_kMaxZoom - 1.0) * selectedness;
|
||||||
child: InkWell(
|
|
||||||
onTap: () => onPageSelected!.call(index),
|
return SizedBox(
|
||||||
),
|
width: _kDotSpacing,
|
||||||
|
child: Center(
|
||||||
|
child: Material(
|
||||||
|
color: (((controller.page ?? controller.initialPage).round()) == index
|
||||||
|
? color
|
||||||
|
: color.withAlpha(125)),
|
||||||
|
type: MaterialType.circle,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
border: Border.all(width: 2, color: dotcolor!),
|
||||||
|
),
|
||||||
|
width: _kDotSize * 2 * zoom,
|
||||||
|
height: _kDotSize * 2 * zoom,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () => onPageSelected!.call(index),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => Row(
|
Widget build(BuildContext context) => Row(
|
||||||
|
|
|
@ -6,9 +6,7 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:flutter_introduction_widget/src/config/introduction.dart';
|
import 'package:flutter_introduction_widget/src/config/introduction.dart';
|
||||||
|
|
||||||
/// Widget representing the content of an introduction page.
|
|
||||||
class IntroductionPageContent extends StatelessWidget {
|
class IntroductionPageContent extends StatelessWidget {
|
||||||
/// Constructs an IntroductionPageContent widget.
|
|
||||||
const IntroductionPageContent({
|
const IntroductionPageContent({
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.text,
|
required this.text,
|
||||||
|
@ -18,19 +16,10 @@ class IntroductionPageContent extends StatelessWidget {
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The title widget.
|
|
||||||
final Widget? title;
|
final Widget? title;
|
||||||
|
|
||||||
/// The text widget.
|
|
||||||
final Widget? text;
|
final Widget? text;
|
||||||
|
|
||||||
/// The graphic widget.
|
|
||||||
final Widget? graphic;
|
final Widget? graphic;
|
||||||
|
|
||||||
/// The layout style of the content.
|
|
||||||
final IntroductionLayoutStyle layoutStyle;
|
final IntroductionLayoutStyle layoutStyle;
|
||||||
|
|
||||||
/// Callback function called when the content is tapped.
|
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
name: flutter_introduction_widget
|
name: flutter_introduction_widget
|
||||||
description: Flutter Introduction Widget for showing a list of introduction pages on a single scrollable page or horizontal pageview
|
description: Flutter Introduction Widget for showing a list of introduction pages on a single scrollable page or horizontal pageview
|
||||||
version: 5.0.0
|
version: 2.0.1
|
||||||
homepage: https://github.com/Iconica-Development/flutter_introduction_widget
|
homepage: https://github.com/Iconica-Development/flutter_introduction_widget
|
||||||
|
|
||||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.0.0 <4.0.0"
|
sdk: ">=3.0.0 <4.0.0"
|
||||||
flutter: ">=1.17.0"
|
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
|
@ -16,11 +14,10 @@ dependencies:
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_lints: ^2.0.0
|
||||||
flutter_iconica_analysis:
|
flutter_iconica_analysis:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
ref: 6.0.0
|
ref: 6.0.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
assets:
|
|
||||||
- assets/
|
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
name: flutter_introduction_workspace
|
name: flutter_introduction_workspace
|
||||||
description: The use case level package using both the flutter_introduction_widget and the flutter_introduction_service combined
|
version: 2.0.0
|
||||||
version: 5.0.0
|
|
||||||
|
|
||||||
publish_to: None
|
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.1.0 <4.0.0'
|
sdk: '>=3.1.0 <4.0.0'
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
melos: ">=3.0.1 <7.0.0"
|
melos: ^3.0.1
|
||||||
|
|
Loading…
Reference in a new issue