skip to Main Content

I’m not good at animation but want to add animation which is like , there are 4 alphabets letters "B", "C" , "D" and "E" which should animate from their 4 axis towards to the center and make a logo at center then when animation get complete, social buttons should animtate from the bottom that’s all I want to implements.

I’m going to add screens which make my concept more clear, what I’m trying to say :

First view

enter image description here

second view

enter image description here

Code for simple for showing Splash image

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

  @override
  State<StatefulWidget> createState() {
    return _SplashScreenState();
  }
}

class _SplashScreenState extends State<SplashScreen> {
  Timer? timer;

  @override
  void initState() {
    super.initState();
    navigatePage();
  }

  void navigatePage() async {
    timer = Timer(const Duration(seconds: 2), () async {
      isLoggedIn
          ? Navigator.pushReplacementNamed(context, "home")
          : Navigator.pushReplacementNamed(context, "login");
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: const Color(0xffF7F8F8),
        body: Image.asset(
          'assets/images/splash.png',
          fit: BoxFit.cover,
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height,
        ));
  }

  @override
  void dispose() {
    timer?.cancel();
    super.dispose();
  }
}


2

Answers


  1. You can play with AnimatedPositioned and AnimatedRotation:

    class HomePage extends StatefulWidget {
      const HomePage({super.key});
    
      @override
      State<HomePage> createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      bool animated = false;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              setState(() {
                animated = !animated;
              });
            },
          ),
          body: Stack(
            children: [
              AnimatedPositioned(
                top: animated
                    ? MediaQuery.of(context).size.height * .50
                    : MediaQuery.of(context).size.height * .75,
                right: animated
                    ? MediaQuery.of(context).size.width * .100
                    : MediaQuery.of(context).size.width * .50,
                duration: const Duration(seconds: 3),
                child: AnimatedRotation(
                  duration: const Duration(seconds: 3),
                  turns: animated ? 0.3 : 0.45,
                  child: container(color: Colors.green),
                ),
              ),
              AnimatedPositioned(
                top: animated
                    ? MediaQuery.of(context).size.height * .25
                    : MediaQuery.of(context).size.height * .50,
                right: animated
                    ? MediaQuery.of(context).size.width * .25
                    : MediaQuery.of(context).size.width * .50,
                duration: const Duration(seconds: 3),
                child: AnimatedRotation(
                  duration: const Duration(seconds: 3),
                  turns: animated ? 0.3 : 0.1,
                  child: container(color: Colors.blue),
                ),
              ),
              AnimatedPositioned(
                top: animated
                    ? MediaQuery.of(context).size.height * .75
                    : MediaQuery.of(context).size.height * .15,
                right: animated
                    ? MediaQuery.of(context).size.width * .50
                    : MediaQuery.of(context).size.width * .25,
                duration: const Duration(seconds: 3),
                child: AnimatedRotation(
                  duration: const Duration(seconds: 3),
                  turns: animated ? -0.3 : 0.13,
                  child: container(color: Colors.yellow),
                ),
              ),
            ],
          ),
        );
      }
    
      Widget container({Color color = Colors.grey}) {
        return Container(
          height: 50,
          width: 50,
          color: color,
        );
      }
    }
    

    demo

    Login or Signup to reply.
  2. I created the animation simply using Hero, focused on the animation is BETWEEN PAGES.

    Please refer to the example for not wearing fancy colours or designs.

    import 'package:flutter/material.dart';
    
    class SplashScreen extends StatefulWidget {
      const SplashScreen({super.key});
    
      @override
      State<StatefulWidget> createState() {
        return _SplashScreenState();
      }
    }
    
    class _SplashScreenState extends State<SplashScreen> {
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          onTap: () {
            Navigator.push(
              context,
              PageRouteBuilder(
                transitionDuration: const Duration(seconds: 1),
                pageBuilder: (context, animation, secondaryAnimation) => const LoginPage(),
              ),
            );
          },
          child: const Scaffold(
            backgroundColor: Color(0xffF7F8F8),
            body: Stack(
              children: [
                Align(child: MainLogoItem()),
                Positioned(
                  top: 150,
                  child: LogoItem('B'),
                ),
                Positioned(
                  bottom: 50,
                  left: 30,
                  child: LogoItem('C'),
                ),
                Positioned(
                  right: 20,
                  bottom: 130,
                  child: LogoItem('D'),
                ),
                Positioned(
                  top: 30,
                  right: 70,
                  child: LogoItem('E'),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    class LoginPage extends StatelessWidget {
      const LoginPage({super.key});
    
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          onTap: () {
            Navigator.pop(context);
          },
          child: const Scaffold(
            backgroundColor: Color(0xffF7F8F8),
            body: Center(child: Logo()),
          ),
        );
      }
    }
    
    class Logo extends StatelessWidget {
      const Logo({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Container(
          width: 100,
          height: 100,
          clipBehavior: Clip.hardEdge,
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(20),
            boxShadow: const [
              BoxShadow(
                color: Colors.grey,
                blurRadius: 5,
                spreadRadius: 1,
              ),
            ],
          ),
          child: const Stack(
            children: [
              Align(child: MainLogoItem()),
              Positioned(
                left: 20,
                top: 10,
                child: LogoItem('B'),
              ),
              Positioned(
                bottom: 10,
                left: 15,
                child: LogoItem('C'),
              ),
              Positioned(
                right: 10,
                bottom: 10,
                child: LogoItem('D'),
              ),
              Positioned(
                top: -10,
                right: 30,
                child: LogoItem('E'),
              ),
            ],
          ),
        );
      }
    }
    
    class MainLogoItem extends StatelessWidget {
      const MainLogoItem({
        super.key,
      });
    
      @override
      Widget build(BuildContext context) {
        return const LogoItem('A', fontSize: 50);
      }
    }
    
    class LogoItem extends StatelessWidget {
      final String alphabet;
      final double? fontSize;
    
      const LogoItem(
        this.alphabet, {
        super.key,
        this.fontSize,
      });
    
      @override
      Widget build(BuildContext context) {
        return Hero(
          tag: 'LogoItem $alphabet',
          child: Text(
            alphabet,
            style: TextStyle(
              color: Colors.black,
              decoration: TextDecoration.none,
              fontSize: fontSize ?? 30,
              fontWeight: FontWeight.bold,
              height: 0,
            ),
          ),
        );
      }
    }
    

    How to test

    1. Paste & copy the codes.
    2. Add SplashScreen to your app.
    3. Tap screen then it navigate you to LoginPage with animation.
    4. Tap again to get back to SpalshScreen.

    I did my best but I am pretty sure there must be a better solution.

    I hope you get some hints from my code though.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search