Animate a splash screen in Flutter without using third-party plugins

Animate a splash screen in Flutter without using any third-party plugins by creating custom widgets and using built-in animation libraries such as the AnimationController and Tween classes. Start by creating a StatefulWidget for the splash screen, then use the AnimationController to control the animation timeline. Use Tween to define the animation's starting and ending values, and use AnimatedBuilder to build the splash screen with the animated values. Finally, use the addStatusListener method on the AnimationController to listen for the animation's status updates and navigate to the next screen when the animation is complete.

Animated Splash Screen


Below provided code is a Flutter widget that implements a splash screen. It's a simple StatefulWidget that creates a _SplashScreenState object in its createState method. The _SplashScreenState class extends the State class and uses the SingleTickerProviderStateMixin mixin.

The SingleTickerProviderStateMixin provides a single Ticker that can be used to drive an animation. In this case, it's used to control the animation of an image.

class _SplashScreenState extends State<SplashScreen>
    with SingleTickerProviderStateMixin {

In the initState method, the code creates an AnimationController object, which is used to control the animation. The AnimationController is initialized with a Duration of 3 seconds and a vsync argument that is set to this. This vsync argument ensures that the animation is only updated when the widget is visible on the screen.

Next, the code creates an Animation object using the Tween widget. The Tween widget creates an animation between two values. In this case, it creates an animation between 0 and 1. The CurvedAnimation widget is used to apply a curve to the animation. The curve used in this case is the Curves.bounceOut curve, which creates a bouncy effect.

void initState() {
    super.initState();
    _controller =
        AnimationController(duration: const Duration(seconds: 3), vsync: this);
    _animation = Tween<double>(begin: 0, end: 1).animate(
      CurvedAnimation(parent: _controller, curve: Curves.bounceOut),
    );
   );
  }

Once the animation is set up, the code calls the forward method on the AnimationController to start the animation. The forward method returns a Future that completes when the animation is finished. The code listens to this Future using the then method, and when the animation is completed, it pushes a new IntroScreen using the Navigator.push method.

 _controller.forward().then((value) {
      Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => IntroScreen(),
        ),
      );
    }

In the build method, the code creates a Scaffold widget with a single child, which is a Column widget. The Column widget has two children: an AnimatedBuilder widget and a Text widget.

Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            AnimatedBuilder(
              animation: _animation,
              builder: (context, child) => Container(
                height: 200,
                width: 200,
                transform:
                    Matrix4.translationValues(0, -_animation.value * 100, 0),
                child: Image.asset(
                  'assets/images/logo.png',
                  fit: BoxFit.fitHeight,
                ),
              ),
            ),
            //SizedBox(height: 20),
            const Text(
              'PradeeptheDeveloper',
              style: TextStyle(
                  fontSize: 20,
                  fontWeight: FontWeight.bold,
                  color: Colors.orange),
            ),
          ],
        ),

The AnimatedBuilder widget takes an Animation object and a Builder function. The Builder function takes a BuildContext and a Widget as arguments, and returns a new Widget. In this case, the Builder function creates a Container widget that has an image as its child. The image's position is animated using the transform property. The animation is applied to the transform property by multiplying the animation value with -100 and applying it to the Y-axis of the Matrix4.

AnimatedBuilder(
              animation: _animation,
              builder: (context, child) => Container(
                height: 200,
                width: 200,
                transform:
                    Matrix4.translationValues(0, -_animation.value * 100, 0),
                child: Image.asset(
                  'assets/images/logo.png',
                  fit: BoxFit.fitHeight,
                ),
              ),
            ),

The Text widget simply displays a message.

Text(
              'PradeeptheDeveloper',
              style: TextStyle(
                  fontSize: 20,
                  fontWeight: FontWeight.bold,
                  color: Colors.orange),
            ),

In the dispose method, the code calls the dispose method on the AnimationController to release its resources.

 void dispose() {
    _controller.dispose();
    super.dispose();
  }

Full source code:

import 'package:flutter/material.dart';

import 'intro_screen.dart';

class SplashScreen extends StatefulWidget {
  const SplashScreen({super.key});

  @override
  State<SplashScreen> createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation _animation;

  @override
  void initState() {
    super.initState();
    _controller =
        AnimationController(duration: const Duration(seconds: 3), vsync: this);
    _animation = Tween<double>(begin: 0, end: 1).animate(
      CurvedAnimation(parent: _controller, curve: Curves.bounceOut),
    );
    _controller.forward().then((value) {
      Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => IntroScreen(),
        ),
      );
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            AnimatedBuilder(
              animation: _animation,
              builder: (context, child) => Container(
                height: 200,
                width: 200,
                transform:
                    Matrix4.translationValues(0, -_animation.value * 100, 0),
                child: Image.asset(
                  'assets/images/logo.png',
                  fit: BoxFit.fitHeight,
                ),
              ),
            ),
            //SizedBox(height: 20),
            const Text(
              'PradeeptheDeveloper',
              style: TextStyle(
                  fontSize: 20,
                  fontWeight: FontWeight.bold,
                  color: Colors.orange),
            ),
          ],
        ),
      ),
    );
  }
}


Comments

Popular posts from this blog

Error Handling in Flutter - Gradle issue

How to Make a Dynamic and Trending ListView with Flutter Widgets?

Understanding API integration with Getx State management