flutterdartflutter-dependenciesflutter-sharedpreference

Flutter Onboarding Screen Only Once With Splash Screen


I was working in Flutter to make an app and I only want the onboarding screen to be seen once by users. I have watched several videos showing how to do this, but the problem is my home screen will always be the Splash Screen. I am not sure how to use Shared Preferences to have the onboarding screen shown once but to still have the splash screen show every time. I could really use some assistance :).

My code for main.dart:

int? isViewed;
Future <void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final prefs = await SharedPreferences.getInstance();
  final showLogin = prefs.getBool('showLogin') ?? false;
  Paint.enableDithering = true;
  await Firebase.initializeApp();

// This is for our onboarding screen
isViewed = prefs.getInt('onboard');

  runApp(MyApp(showLogin: showLogin));
}

class MyApp extends StatelessWidget {
  final bool showLogin;
  
  const MyApp({Key? key,
  required this.showLogin}) : super(key: key);


  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Strength',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        appBarTheme: const AppBarTheme(color: Colors.white,
        elevation: 0,
        brightness: Brightness.light,
        iconTheme: IconThemeData(color: Colors.black),
        textTheme: TextTheme(headline6: TextStyle(color: Color(0xff888888), fontSize: 18),
        )
      ),),
      home: const SplashScreen(),
    );
  }
}

Chunks of code for my onboarding screen:

class OnboardingScreen extends StatefulWidget {
  const OnboardingScreen({Key? key}) : super(key: key);

  @override
  _OnboardingScreenState createState() => _OnboardingScreenState();
}

class _OnboardingScreenState extends State<OnboardingScreen> {
  final controller = PageController();
  bool isLastPage = false;

  @override
  void dispose() {
    controller.dispose();

    super.dispose();
  }

  _storeOnboardingInfo() async {
    int isViewed = 0;
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setInt('onBoard', isViewed);
  }
  
  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
.
.
.
TextButton(
          style: TextButton.styleFrom(
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(0),
            ),
            primary: Colors.white,
            backgroundColor: const Color(0xff31708c),
            minimumSize: const Size.fromHeight(60)
          ),
          child: Text(
            'Get Started',
            style: GoogleFonts.montserrat(
              fontSize: 24,
              fontWeight: FontWeight.w600),
          ),
          onPressed: () async {
            final prefs = await SharedPreferences.getInstance();
            prefs.setBool('showLogin', true);
            await _storeOnboardingInfo();

            Navigator.of(context).pushReplacement(
              PageTransition(
                type: PageTransitionType.fade,
                duration: const Duration(milliseconds: 500),
                child: LandingScreen()
              )
            );
          }
        )

Code for my Splash screen:

class SplashScreen extends StatefulWidget {
  const SplashScreen ({Key? key}) : super(key: key);

  @override
  _SplashScreenState createState() => _SplashScreenState();

}

class _SplashScreenState extends State<SplashScreen> with TickerProviderStateMixin{
  late AnimationController _screenController;

  @override
  void initState() {
    super.initState();
    _screenController = AnimationController(vsync: this);

  }

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Container(
      height: double.infinity,
      width: double.infinity,
      child: Lottie.asset('assets/lottie/splashScreen.lottie.json',
      fit: BoxFit.fill,
      controller: _screenController,
      onLoaded: (composition) {
        _screenController
        ..duration = composition.duration
        ..forward().whenComplete(() => 
        Navigator.of(context).pushReplacement(
          PageTransition(
            type: PageTransitionType.fade,
            duration: const Duration(milliseconds: 1800),
            child: const OnboardingScreen()
          )
        ));
      }
      )
    )
  );
}
}

Solution

  • You can check the shared preference value in the Splash Screen and redirect the user to the OnBoardingScreen or LandingScreen.

    import 'package:custom_form_field/src/form_screen.dart';
    import 'package:flutter/material.dart';
    import 'package:lottie/lottie.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    
    class SplashScreen extends StatefulWidget {
      const SplashScreen({Key? key}) : super(key: key);
    
      @override
      _SplashScreenState createState() => _SplashScreenState();
    }
    
    class _SplashScreenState extends State<SplashScreen>
        with TickerProviderStateMixin {
      late AnimationController _screenController;
    
      @override
      void initState() {
        super.initState();
        _screenController = AnimationController(vsync: this);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            body: Container(
                height: double.infinity,
                width: double.infinity,
                child: Lottie.asset('assets/lottie/splashScreen.lottie.json',
                    fit: BoxFit.fill,
                    controller: _screenController, onLoaded: (composition) {
                  _screenController
                    ..duration = composition.duration
                    ..forward().whenComplete(() async {
                          SharedPreferences prefs = await SharedPreferences.getInstance();
                      // check shared preference and show particular screen
                     
                    });
                })));
      }
    }
    

    You can check the shared preference value at initState and do the logic after animation complete as well. Also you can check login state from shared preference here and show login page if needed.