diff --git a/README.md b/README.md index 24c9cdf..b464039 100644 --- a/README.md +++ b/README.md @@ -465,6 +465,9 @@ You can provide many parameters to customize each pages: - `body: "Body of the page"` or `bodyWidget: Text("Custom widget for body")` - `image: Image.asset(...)` image of the page. - It's expecting a Widget, so if you want to pass a Video, Text, or anything else, you can. +- `backgroundImage: 'assets/fullscreen.jpg'` background image of the page (optional). + - It's expecting a String with a path to an image asset. Works just like the `image` parameter under the hood while making an asset span all over the screen. + - Doesn't affect the `image` nor `fullscreen` parameters: can be used together with them to build more complex layouts. - `footer: ElevatedButton(...)`, display a widget below body - Like image param, it's expecting a Widget, you can pass what you want. - `decoration: PageDecoration(...)`, page decoration to customize page diff --git a/example/lib/main.dart b/example/lib/main.dart index a41ae0b..0d8f1af 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -5,6 +5,8 @@ import 'package:introduction_screen/introduction_screen.dart'; void main() => runApp(const App()); +const backgroundImage = 'assets/fullscreen.jpg'; + class App extends StatelessWidget { const App({super.key}); @@ -39,16 +41,6 @@ class OnBoardingPageState extends State<OnBoardingPage> { ); } - Widget _buildFullscreenImage() { - return Image.asset( - 'assets/fullscreen.jpg', - fit: BoxFit.cover, - height: double.infinity, - width: double.infinity, - alignment: Alignment.center, - ); - } - Widget _buildImage(String assetName, [double width = 350]) { return Image.asset('assets/$assetName', width: width); } @@ -117,10 +109,9 @@ class OnBoardingPageState extends State<OnBoardingPage> { title: "Full Screen Page", body: "Pages can be full screen as well.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc id euismod lectus, non tempor felis. Nam rutrum rhoncus est ac venenatis.", - image: _buildFullscreenImage(), + backgroundImage: backgroundImage, decoration: pageDecoration.copyWith( contentMargin: const EdgeInsets.symmetric(horizontal: 16), - fullScreen: true, bodyFlex: 2, imageFlex: 3, safeArea: 100, diff --git a/lib/src/helper.dart b/lib/src/helper.dart index dee363a..a3f526c 100644 --- a/lib/src/helper.dart +++ b/lib/src/helper.dart @@ -10,3 +10,17 @@ extension CustomList<T> on List<T> { return null; } } + +bool isBackgroundImageAssetPathValid(String assetPath) { + const validExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']; + + bool hasValidExtension = validExtensions.any((extension) { + return assetPath.toLowerCase().endsWith('.$extension'); + }); + + if (!hasValidExtension) { + return false; + } + + return true; +} diff --git a/lib/src/model/page_view_model.dart b/lib/src/model/page_view_model.dart index 18f7d5f..afb4a72 100644 --- a/lib/src/model/page_view_model.dart +++ b/lib/src/model/page_view_model.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:introduction_screen/src/helper.dart'; + import '/src/model/page_decoration.dart'; class PageViewModel { @@ -18,6 +20,12 @@ class PageViewModel { /// Tips: Wrap your image with an alignment widget like Align or Center final Widget? image; + /// Background image of a page. + /// Spans all over the screen. + /// + /// Tips: can be used alone or as a background image together with the "image" parameter. + final String? backgroundImage; + /// Footer widget, you can add a button for example final Widget? footer; @@ -43,6 +51,7 @@ class PageViewModel { this.body, this.bodyWidget, this.image, + this.backgroundImage, this.footer, this.reverse = false, this.decoration = const PageDecoration(), @@ -65,5 +74,9 @@ class PageViewModel { assert( (body == null) != (bodyWidget == null), "You can not provide both body and bodyWidget.", - ); + ), + assert( + backgroundImage == null || + isBackgroundImageAssetPathValid(backgroundImage), + "You must provide a valid image asset path"); } diff --git a/lib/src/ui/intro_content.dart b/lib/src/ui/intro_content.dart index 5d49fa6..6a9e6b4 100644 --- a/lib/src/ui/intro_content.dart +++ b/lib/src/ui/intro_content.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; + import '/introduction_screen.dart'; class IntroContent extends StatelessWidget { diff --git a/lib/src/ui/intro_page.dart b/lib/src/ui/intro_page.dart index a4ed1bf..6b226e1 100644 --- a/lib/src/ui/intro_page.dart +++ b/lib/src/ui/intro_page.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; + import '/src/helper.dart'; import '/src/model/page_view_model.dart'; import '/src/ui/intro_content.dart'; @@ -28,6 +29,14 @@ class _IntroPageState extends State<IntroPage> return Stack( children: [ + if (page.backgroundImage != null) + Image.asset( + page.backgroundImage!, + fit: BoxFit.cover, + height: double.infinity, + width: double.infinity, + alignment: Alignment.center, + ), if (page.image != null) page.image!, Positioned.fill( child: Column( @@ -126,7 +135,8 @@ class _IntroPageState extends State<IntroPage> Widget build(BuildContext context) { super.build(context); - if (widget.page.decoration.fullScreen) { + if (widget.page.decoration.fullScreen || + widget.page.backgroundImage != null) { return _buildStack(); } return _buildFlex(context);