flutter_introduction/packages/flutter_introduction_widget/lib/src/config/introduction.dart
2024-06-04 16:46:28 +02:00

294 lines
9.4 KiB
Dart

// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter/material.dart';
import 'package:flutter_introduction_widget/src/config/default_introduction_pages.dart';
enum IntroductionScreenMode { showNever, showAlways, showOnce }
enum IntroductionScreenButtonMode { text, icon, disabled, singleFinish }
enum IntroductionLayoutStyle {
imageCenter,
imageTop,
imageBottom,
}
enum IndicatorMode { dot, dash, custom }
enum IntroductionDisplayMode {
singleScrollablePageVertical,
multiPageHorizontal
}
enum IntroductionControlMode {
previousNextButton,
singleButton,
}
enum IntroductionButtonType {
next,
previous,
finish,
skip,
}
class IntroductionPage {
/// Creates an introduction page with data used in the introduction screen for
/// each page.
///
/// The values for [title] and [text] are optional in this, but will use a
/// default translation key when built.
///
/// The [background] is fully optional and if not provided will show the
/// [ThemeData.colorScheme.background] as default.
const IntroductionPage({
this.title,
this.text,
this.graphic,
this.decoration,
this.layoutStyle,
});
final Widget? title;
final Widget? text;
final Widget? graphic;
final BoxDecoration? decoration;
final IntroductionLayoutStyle? layoutStyle;
}
class IntroductionOptions {
const IntroductionOptions({
this.introductionTranslations = const IntroductionTranslations(),
this.introductionButtonTextstyles = const IntroductionButtonTextstyles(),
this.indicatorMode = IndicatorMode.dot,
this.indicatorBuilder,
this.layoutStyle = IntroductionLayoutStyle.imageBottom,
this.pages = defaultIntroductionPages,
this.buttonMode = IntroductionScreenButtonMode.text,
this.tapEnabled = false,
this.mode = IntroductionScreenMode.showNever,
this.textAlign = TextAlign.center,
this.displayMode = IntroductionDisplayMode.multiPageHorizontal,
this.skippable = false,
this.buttonBuilder,
this.controlMode = IntroductionControlMode.previousNextButton,
this.dotSize = 12,
this.dotSpacing = 24,
}) : assert(
!(identical(indicatorMode, IndicatorMode.custom) &&
indicatorBuilder == null),
'When indicator mode is set to custom, '
'make sure to define indicatorBuilder',
);
/// Determine when the introduction screens needs to be shown.
///
/// [IntroductionScreenMode.showNever] To disable introduction screens.
///
/// [IntroductionScreenMode.showAlways] To always show the introduction
/// screens on startup.
///
/// [IntroductionScreenMode.showOnce] To only show the introduction screens
/// once on startup.
final IntroductionScreenMode mode;
/// List of introduction pages to set the text, icons or images for the
/// introduction screens.
final List<IntroductionPage> pages;
/// Determines whether the user can tap the screen to go to the next
/// introduction screen.
final bool tapEnabled;
/// Determines what kind of buttons are used to navigate to the next
/// introduction screen.
/// Introduction screens can always be navigated by swiping (or tapping if
/// [tapEnabled] is enabled).
///
/// [IntroductionScreenButtonMode.text] Use text buttons (text can be set by
/// setting the translation key or using the default appshell translations).
///
/// [IntroductionScreenButtonMode.icon] Use icon buttons (icons can be
/// changed by providing a icon library)
///
/// [IntroductionScreenButtonMode.disabled] Disable buttons.
final IntroductionScreenButtonMode buttonMode;
/// Determines the position of the provided images or icons that are set
/// using [pages].
/// Every introduction page provided with a image or icon will use the same
/// layout setting.
///
/// [IntroductionLayoutStyle.imageCenter] Image/icon will be at the center of the introduction page.
///
/// [IntroductionLayoutStyle.imageTop] Image/icon will be at the top of the introduction page.
///
/// [IntroductionLayoutStyle.imageBottom] Image/icon will be at the bottom of the introduction page.
final IntroductionLayoutStyle layoutStyle;
/// Determines the style of the page indicator shown at the bottom on the
/// introduction pages.
///
/// [IndicatorMode.dot] Shows a dot for each page.
///
/// [IndicatorMode.dash] Shows a dash for each page.
///
/// [IndicatorMode.custom] calls indicatorBuilder for the indicator
final IndicatorMode indicatorMode;
/// Builder that is called when [indicatorMode] is set
/// to [IndicatorMode.custom]
final Widget Function(
BuildContext,
PageController,
int,
int,
)? indicatorBuilder;
/// Determines whether the user can skip the introduction pages using a button
/// in the header
final bool skippable;
/// Determines whether the introduction screens should be shown in a single
final TextAlign textAlign;
/// [IntroductionDisplayMode.multiPageHorizontal] Configured introduction
/// pages will be shown on seperate screens and can be navigated using using
/// buttons (if enabled) or swiping.
///
/// !Unimplemented! [IntroductionDisplayMode.singleScrollablePageVertical]
/// All configured introduction pages will be shown on a single scrollable
/// page.
///
final IntroductionDisplayMode displayMode;
/// When [IntroductionDisplayMode.multiPageHorizontal] is selected multiple
/// controlMode can be selected.
///
/// [IntroductionControlMode.previousNextButton] shows two buttons at the
/// bottom of the screen to return or proceed. The skip button is placed at
/// the top left of the screen.
///
/// [IntroductionControlMode.singleButton] contains one button at the bottom
/// of the screen to proceed. Underneath is clickable text to skip if the
/// current page is the first page. If the current page is any different it
/// return to the previous screen.
///
final IntroductionControlMode controlMode;
/// A builder that can be used to replace the default text buttons when
/// [IntroductionScreenButtonMode.text] is provided to [buttonMode]
final Widget Function(
BuildContext,
VoidCallback,
Widget,
IntroductionButtonType,
)? buttonBuilder;
/// The translations for all buttons on the introductionpages
///
/// See [IntroductionTranslations] for more information
/// The following buttons have a translation:
/// - Skip
/// - Next
/// - Previous
/// - Finish
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;
IntroductionOptions copyWith({
IntroductionScreenMode? mode,
List<IntroductionPage>? pages,
bool? tapEnabled,
IntroductionScreenButtonMode? buttonMode,
IntroductionLayoutStyle? layoutStyle,
IndicatorMode? indicatorMode,
Widget Function(
BuildContext,
PageController,
int,
int,
)? indicatorBuilder,
bool? skippable,
TextAlign? textAlign,
IntroductionDisplayMode? displayMode,
IntroductionControlMode? controlMode,
Widget Function(BuildContext, VoidCallback, Widget, IntroductionButtonType)?
buttonBuilder,
IntroductionTranslations? introductionTranslations,
IntroductionButtonTextstyles? introductionButtonTextstyles,
}) =>
IntroductionOptions(
mode: mode ?? this.mode,
pages: pages ?? this.pages,
tapEnabled: tapEnabled ?? this.tapEnabled,
buttonMode: buttonMode ?? this.buttonMode,
layoutStyle: layoutStyle ?? this.layoutStyle,
indicatorMode: indicatorMode ?? this.indicatorMode,
indicatorBuilder: indicatorBuilder ?? this.indicatorBuilder,
skippable: skippable ?? this.skippable,
textAlign: textAlign ?? this.textAlign,
displayMode: displayMode ?? this.displayMode,
controlMode: controlMode ?? this.controlMode,
buttonBuilder: buttonBuilder ?? this.buttonBuilder,
introductionTranslations:
introductionTranslations ?? this.introductionTranslations,
introductionButtonTextstyles:
introductionButtonTextstyles ?? this.introductionButtonTextstyles,
);
}
class IntroductionTranslations {
const IntroductionTranslations({
this.skipButton = 'Skip',
this.nextButton = 'Next',
this.previousButton = 'Previous',
this.finishButton = 'Get Started',
});
final String skipButton;
final String nextButton;
final String previousButton;
final String finishButton;
}
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,
),
});
final TextStyle? skipButtonStyle;
final TextStyle? nextButtonStyle;
final TextStyle? previousButtonStyle;
final TextStyle? finishButtonStyle;
}