How to Implement a Loading Screen in Flutter

Flutter Spinkit Loaders and Spinners Widgets

Today I am going to add a loading screen to my app that I have made. The loading or loading screens in Flutter are called Loaders and Spinners, and to do that, I am going to add a package to my existing Flutter app. Let’s go!

First, create a stateful widget in a new .dart file. I am going to name mine LoadingScreen. For now, it just displays text that says “Loading…” Don’t worry, I am going to replace it with a good loading animation later.

import 'package:flutter/material.dart';

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

  @override
  State<LoadingScreen> createState() => _LoadingScreenState();
}

class _LoadingScreenState extends State<LoadingScreen> {
  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text('Loading...'),
    );
  }
}

Then in my case, on my main.dart, make sure to import the loading.dart file first, then on my ButtonChange widget, I am going to add a functionality on the onPressed function right after the setState to change the screen to my LoadingScreen widget that I have created.  Refer to the code with comments below.

import 'package:flutter/material.dart';
import 'package:my_flutter_app/loading.dart'; //import this
import 'quote.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int currentIndex = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Center(child: Text("My Flutter App")),
          backgroundColor: const Color(0xFFfb8b04),
        ),
        body: Center(
          child: currentIndex == 0
              ? const BodyImageWidget()
              : currentIndex == 1
                  ? MyCards()
                  : currentIndex == 2
                      ? const MyTextBody()
                      : const ButtonChange(),
        ),
        bottomNavigationBar: BottomNavigationBar(
          type: BottomNavigationBarType.fixed,
          items: const [
            BottomNavigationBarItem(
              label: "Home",
              icon: Icon(Icons.home),
            ),
            BottomNavigationBarItem(
              label: "Quotes",
              icon: Icon(Icons.book),
            ),
            BottomNavigationBarItem(
              label: "Texts",
              icon: Icon(Icons.text_fields_sharp),
            ),
            BottomNavigationBarItem(
              label: "Button",
              icon: Icon(Icons.radio_button_checked),
            )
          ],
          currentIndex: currentIndex,
          onTap: (int index) {
            setState(() {
              currentIndex = index;
            });
          },
        ),
      ),
    );
  }
}

class MyCards extends StatelessWidget {
  MyCards({Key? key}) : super(key: key);

  final List<Quote> quotes = [
    Quote(
        author: 'Mother Teresa',
        text:
            'Spread love everywhere you go. Let no one ever come to you without leaving happier.'),
    Quote(
        author: 'Nelson Mandela',
        text:
            'The greatest glory in living lies not in never falling, but in rising every time we fall.'),
    Quote(
        author: 'Aristotle',
        text:
            'It is during our darkest moments that we must focus to see the light.')
  ];

  Widget quoteTemplate(quote) {
    return Card(
      margin: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0),
      child: Padding(
        padding: const EdgeInsets.all(12.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Text(
              quote.text,
              style: TextStyle(fontSize: 18.0, color: Colors.grey[600]),
            ),
            const SizedBox(height: 6.0),
            Text(
              quote.author,
              style: TextStyle(fontSize: 14.0, color: Colors.grey[800]),
            ),
          ],
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: quotes.map((quote) => quoteTemplate(quote)).toList(),
    );
  }
}

class MyTextBody extends StatelessWidget {
  const MyTextBody({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        const Text('This is a normal text.'),
        const Text(
          'This is a bold text.',
          style: TextStyle(fontWeight: FontWeight.bold),
        ),
        const Text(
          'This is a italic text.',
          style: TextStyle(fontStyle: FontStyle.italic),
        ),
        const Text(
          'This is a bold and italic text.',
          style: TextStyle(
              fontWeight: FontWeight.bold, fontStyle: FontStyle.italic),
        ),
        const Text(
          'This is a underlined wavy text.',
          style: TextStyle(
              decoration: TextDecoration.underline,
              decorationColor: Colors.red,
              decorationStyle: TextDecorationStyle.wavy),
        ),
        Text(
          "Nucleio Technologies",
          style: TextStyle(
            fontSize: 30.0,
            fontWeight: FontWeight.bold,
            foreground: Paint()
              ..shader = const LinearGradient(
                colors: <Color>[
                  Colors.pinkAccent,
                  Colors.deepPurpleAccent,
                  Colors.red
                  //add more color here.
                ],
              ).createShader(
                const Rect.fromLTWH(0.0, 0.0, 200.0, 100.0),
              ),
          ),
        ),
      ],
    );
  }
}

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

  @override
  State<ButtonChange> createState() => _ButtonChangeState();
}

class _ButtonChangeState extends State<ButtonChange> {
  Color btnColor = Colors.red;
  Text btnText = const Text('Click Me');
  Icon btnIcon = const Icon(
    Icons.android,
    color: Colors.green,
    size: 24.0,
  );

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton.icon(
        style: ElevatedButton.styleFrom(
          primary: btnColor,
          minimumSize: const Size(200, 50),
        ),
        onPressed: () {
          setState(() {
            btnColor = Colors.green;
            btnText = const Text('Click Success');
            btnIcon = const Icon(
              Icons.check,
              color: Colors.white,
              size: 24.0,
            );
          });
          // Added functionality here
          Navigator.of(context).push(
                          MaterialPageRoute(
                            builder: (BuildContext context) => const LoadingScreen(),
                          ),
                        );
        },
        label: btnText,
        icon: btnIcon,
      ),
    );
  }
}

class BodyImageWidget extends StatelessWidget {
  const BodyImageWidget({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Image.asset("images/WelcomeImage.png"),
    );
  }
}

Flutter Spinkit

Now I am going to edit my loading screen widget, but first I am going to need a package that gives us free loaders and spinners that we can use. It’s called the flutter_spinkit, and to install it, open the terminal and type flutter pub add flutter_spinkit then enter.

Flutter_Spinkit installation on Visual Studio Code

Don’t forget to flutter pub get because the dependencies that you just added are not yet applied and when you try to import the spinkit it won’t show.

Usage

Now that we have added the spinkit package to our dependencies to use it, I am going to import it and then use the FoldingCube widget. You can use any of their widgets. Maybe in the future there will be changes, so please refer to the link below.

https://pub.dev/packages/flutter_spinkit

Updated LoadingScreen widget source code:

import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';

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

  @override
  State<LoadingScreen> createState() => _LoadingScreenState();
}

class _LoadingScreenState extends State<LoadingScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.orange[400],
      body: const Center(
        child: SpinKitFoldingCube(
        color: Colors.white,
        size: 50.0),
      ),
    );
  }
}

Conclusion

I mostly added a loading screen to my existing app using the flutter_spinkit where I also covered how to definitely install and use it.
Thank you for reading and farewell once again!

Leave a Comment

Your email address will not be published. Required fields are marked *