OMER ADIL
OMER ADIL

Reputation: 21

How To Make Onboarding Screen Only One Time

I wanna make my onboarding screen shown only once when installing an application in the device

> import 'package:flutter/foundation.dart';
> import 'package:flutter/material.dart';
> import 'package:flutter/services.dart';
> import 'package:introduction_screen/introduction_screen.dart';
> 
> import 'widget_tree.dart';
> 
> class IntroScreen extends StatefulWidget {
>   @override
>   _IntroScreenState createState() => _IntroScreenState();
> }
> 
> class _IntroScreenState extends State<IntroScreen> {
>   final introKey = GlobalKey<IntroductionScreenState>();
>   late final bool isFirstRun;
>   get child => null;
> 
>   void _onIntroEnd(context) {
>     Navigator.of(context).push(
>       MaterialPageRoute(builder: (_) => WidgetTree()),
>     );
>   }
> 
>   Widget _buildFullscreenImage() {
>     return Image.asset(
>       'assets/images/intro1.png',
>       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);
>   }
> 
>   @override
>   Widget build(BuildContext context) {
>     const bodyStyle = TextStyle(fontSize: 19.0);
> 
>     const pageDecoration = PageDecoration(
>       titleTextStyle: TextStyle(
>           color: Color.fromARGB(255, 29, 116, 182),
>           fontSize: 30.0,
>           fontWeight: FontWeight.w700,
>           fontFamily: 'assets/fonts/Ubuntu-B.ttf'),
>       bodyTextStyle: bodyStyle,
>       bodyPadding: EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 16.0),
>       pageColor: Color.fromARGB(0, 255, 255, 255),
>       imagePadding: EdgeInsets.zero,
>     );
> 
>     return IntroductionScreen(
>       key: introKey,
>       globalBackgroundColor: Colors.white,
>       globalHeader: const Align(
>         alignment: Alignment.topRight,
>         child: SafeArea(
>           child: Padding(
>             padding: EdgeInsets.only(top: 16, right: 16),
>             // child: _buildImage('flutter.png', 100),
>           ),
>         ),
>       ),
>       /*globalFooter: SizedBox(
>         width: double.infinity,
>         height: 60,
>         child: ElevatedButton(
>           style:const ButtonStyle(alignment:Alignment(1, 1)),
>           child: const Text(
>             'Skip!',
>             style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold),
>           ),
>           onPressed: () => _onIntroEnd(context),
>         ),
>       ),*/
> 
>       pages: [
>         PageViewModel(
>           title: ('WELCOME'),
>           body:
>               'To the Mawed , which allows you to book a clinic easily . Choose the hospital that suits you and the doctor you want.',
>           image: Image.asset(
>             'assets/images/intro1.png',
>             width: 400,
>             height: 400,
>             fit: BoxFit.fitWidth,
>             alignment: AlignmentDirectional.bottomCenter,
>           ),
>           decoration: pageDecoration,
>         ),
>         PageViewModel(
>           title: "Book Now",
>           body: " From your home easly & Keep the ticket to show when asked",
>           image: Image.asset(
>             'assets/images/intro2.jpg',
>             width: 350,
>             height: 350,
>             fit: BoxFit.fitWidth,
>             alignment: AlignmentDirectional.center,
>           ),
>           decoration: pageDecoration,
>         ),
>         PageViewModel(
>           title: "Avoid",
>           body: "Crowding and wasting time, and go on time.",
>           image: Image.asset(
>             'assets/images/intro3.jpg',
>             width: 350,
>             height: 350,
>             fit: BoxFit.fitWidth,
>             alignment: AlignmentDirectional.center,
>           ),
>           decoration: pageDecoration,
>         ),
>         PageViewModel(
>           title: "Choose the hospital",
>           body: "That suits & the closest to you",
>           image: Image.asset(
>             'assets/images/intro4.jpg',
>             width: 350,
>             height: 350,
>             fit: BoxFit.fitWidth,
>             alignment: AlignmentDirectional.center,
>           ),
>           decoration: pageDecoration,
>         ),
>         PageViewModel(
>           title: "What do you feel ?",
>           body: "Choose the clinic or medical specialty carefully",
>           image: Image.asset('assets/images/intro5.png',
>               width: 350,
>               height: 350,
>               fit: BoxFit.fitWidth,
>               alignment: AlignmentDirectional.center),
>           decoration: pageDecoration,
>         ),
>         PageViewModel(
>           title: "Get to know ",
>           body: "Your doctor's appointments and choose the time you want.",
>           image: Image.asset('assets/images/intro6.png',
>               width: 400,
>               height: 400,
>               fit: BoxFit.fitWidth,
>               alignment: AlignmentDirectional.bottomCenter),
>           decoration: pageDecoration,
>         ),
>       ],
>       onDone: () => _onIntroEnd(context),
>       onSkip: () => _onIntroEnd(context), // You can override onSkip callback
>       showSkipButton: false,
>       skipOrBackFlex: 0,
>       nextFlex: 0,
>       showBackButton: true,
>       //rtl: true, // Display as right-to-left
>       back: const Icon(Icons.arrow_back),
>       skip: const Text('Skip', style: TextStyle(fontWeight: FontWeight.w600)),
>       next: const Icon(Icons.arrow_forward),
>       done:
>           const Text('Book Now', style: TextStyle(fontWeight: FontWeight.w600)),
>       curve: Curves.fastLinearToSlowEaseIn,
>       controlsMargin: const EdgeInsets.all(16),
>       controlsPadding: kIsWeb
>           ? const EdgeInsets.all(12.0)
>           : const EdgeInsets.fromLTRB(8.0, 4.0, 8.0, 4.0),
>       dotsDecorator: const DotsDecorator(
>         size: Size(10.0, 10.0),
>         color: Color(0xFFBDBDBD),
>         activeSize: Size(22.0, 10.0),
>         activeShape: RoundedRectangleBorder(
>           borderRadius: BorderRadius.all(Radius.circular(25.0)),
>         ),
>       ),
>       dotsContainerDecorator: const ShapeDecoration(
>         color: Colors.black87,
>         shape: RoundedRectangleBorder(
>           borderRadius: BorderRadius.all(Radius.circular(8.0)),
>         ),
>       ),
>     );
>   }
> }
> 

Upvotes: 2

Views: 1829

Answers (5)

Kamran Khan
Kamran Khan

Reputation: 11

SharedPreferences is used to store whether the onboarding process is complete persistently. When the app starts, it checks SharedPreferences to see if onboardingComplete is set to true; if not, it defaults to showing the OnboardingScreen; otherwise, it displays the MainScreen.

import 'package:shared_preferences/shared_preferences.dart';    

void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      final prefs = await SharedPreferences.getInstance();
      final bool onboardingComplete = prefs.getBool('onboardingComplete') ?? false;
    
      runApp(MaterialApp(
        home: onboardingComplete ? MainScreen() : OnboardingScreen(),
      ));
    }

When the button is pressed, SharedPreferences updates onboardingComplete to true, and the app switches to the MainScreen, replacing the OnboardingScreen.

class OnboardingScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            final prefs = await SharedPreferences.getInstance();
            await prefs.setBool('onboardingComplete', true);

            Navigator.pushReplacement(
              context,
              MaterialPageRoute(builder: (context) => MainScreen()),
            );
          },
          child: Text('Complete Onboarding'),
        ),
      ),
    );
  }
}

Once onboarding is marked complete (as stored in SharedPreferences), the MainScreen is shown

class MainScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Main Screen'),
      ),
      body: Center(
        child: Text('Welcome to the main screen!'),
      ),
    );
  }
}

Upvotes: 0

Komal
Komal

Reputation: 338

Using shared preference, you can show onboarding screen only one time.

static SharedPreferences? prefsInstance;
static void init() async {
    prefsInstance = await prefsFuture;
  }

set preference while completing onboarding screen Or last page's on click of button which move to dashboard or next screen after done onboarding.

prefsInstance!.setBool("IS_FIRST_INSTALLED", true);

Now get preference in splash and check if onboarding already seen or not.

 if (SharedPrefUtils.getSharedPreference(IS_FIRST_INSTALLED) == false) {
      /// move to onboarding screen 
      /// onboarding is not seen yet.
    } else {
      /// move to dashboard/home screen - onboarding is already seen
    }
static Future<dynamic> getSharedPreference(String key) async {
    dynamic value;
    if (prefsInstance == null) {
      var instance = await prefsFuture;
      value = instance!.get(key);
    } else {
      value = get(key);
    }
    return value;
  }

Upvotes: 1

Colin Lazarini
Colin Lazarini

Reputation: 957

As other answers are recommending the use of SharedPreferences or LocalSave, it works fine when you don't have any user account.

If you have user account and a database you should save this status in their profile so even if they install the application on a new device they don't have the onboarding again that could cause issues if you set some specific data that should only be accessed once by the user.

You basically have a bool hasCompletedOnboarding set to false when creating the user and you update it once he finishes the onboarding.

Then as FDuhen specified you show or not the Onboarding.

Upvotes: 5

Bruno Santos
Bruno Santos

Reputation: 35

You Can Use this Library

you will be able to save the data locally by configuring it only once

Upvotes: 2

FDuhen
FDuhen

Reputation: 4836

The common way to handle this is to use the SharedPreferences library

1- When displaying the onboarding, store a bool like hasSeenOnboarding in the SharedPreferences with the value true
2- Right before displaying the onboarding, fetch the bool hasSeenOnboarding from the preferences.
If it's false, you can display the onboarding, otherwise you should skip it

Upvotes: 12

Related Questions