Button and Dashboard Animation In Flutter

Button and Dashboard Animation In Flutter :

Screenshot 1 :

Button and Dashboard Animation  In Flutter

Screenshot 2 :

Button and Dashboard Animation  In Flutter

Screenshot 3 :

Button and Dashboard Animation  In Flutter

Helper Package :

math_helper.dart

import 'dart:math';

class MathHelper {
  static double toRadian(double degree) => degree * pi / 180;

  static double lerp(double start, double end, double percent) {
    return (start + percent * (end - start));
  }
}

matrix.dart

import 'package:flutter/rendering.dart';

class Matrix {
  static Matrix4 perspective([double weight = .001]) =>
      Matrix4.identity()..setEntry(3, 2, weight);
}

widget_helper.dart

import 'package:flushbar/flushbar.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

Size getWidgetSize(GlobalKey key) {
  final RenderBox renderBox = key.currentContext?.findRenderObject();
  return renderBox?.size;
}

Flushbar showSuccessToast(BuildContext context, String message) {
  return Flushbar(
    title: 'Success',
    message: message,
    icon: Icon(
      Icons.check,
      size: 28.0,
      color: Colors.white,
    ),
    duration: const Duration(seconds: 4),
    backgroundGradient: LinearGradient(
      colors: [Colors.green[600], Colors.green[400]],
    ),
    onTap: (flushbar) => flushbar.dismiss(),
  )..show(context);
}

Flushbar showErrorToast(BuildContext context, String message) {
  return Flushbar(
    title: 'Error',
    message: message,
    icon: Icon(
      Icons.error,
      size: 28.0,
      color: Colors.white,
    ),
    duration: const Duration(seconds: 4),
    backgroundGradient: LinearGradient(
      colors: [Colors.red[600], Colors.red[400]],
    ),
    onTap: (flushbar) => flushbar.dismiss(),
  )..show(context);
}

Widget Package :

animated_button.dart

import 'package:flutter/material.dart';
import 'animated_text.dart';
import 'ring.dart';

class AnimatedButton extends StatefulWidget {
  AnimatedButton({
    Key key,
    @required this.text,
    @required this.onPressed,
    @required this.controller,
    this.loadingColor,
    this.color,
  }) : super(key: key);

  final String text;
  final Color color;
  final Color loadingColor;
  final Function onPressed;
  final AnimationController controller;

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

class _AnimatedButtonState extends State<AnimatedButton>
    with SingleTickerProviderStateMixin {
  Animation<double> _sizeAnimation;
  Animation<double> _textOpacityAnimation;
  Animation<double> _buttonOpacityAnimation;
  Animation<double> _ringThicknessAnimation;
  Animation<double> _ringOpacityAnimation;
  Animation<Color> _colorAnimation;
  var _isLoading = false;
  var _hover = false;

  Color _color;
  Color _loadingColor;

  static const _width = 120.0;
  static const _height = 40.0;
  static const _loadingCircleRadius = _height / 2;
  static const _loadingCircleThickness = 4.0;

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

    _textOpacityAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(
      CurvedAnimation(
        parent: widget.controller,
        curve: Interval(0.0, .25),
      ),
    );

    _sizeAnimation = Tween<double>(begin: 1.0, end: _height / _width)
        .animate(CurvedAnimation(
      parent: widget.controller,
      curve: Interval(0.0, .65, curve: Curves.fastOutSlowIn),
    ));

    // _colorAnimation

    _buttonOpacityAnimation =
        Tween<double>(begin: 1.0, end: 0.0).animate(CurvedAnimation(
      parent: widget.controller,
      curve: Threshold(.65),
    ));

    _ringThicknessAnimation =
        Tween<double>(begin: _loadingCircleRadius, end: _loadingCircleThickness)
            .animate(CurvedAnimation(
      parent: widget.controller,
      curve: Interval(.65, .85),
    ));
    _ringOpacityAnimation =
        Tween<double>(begin: 1.0, end: 0.0).animate(CurvedAnimation(
      parent: widget.controller,
      curve: Interval(.85, 1.0),
    ));

    widget.controller.addStatusListener(handleStatusChanged);
  }

  @override
  void didChangeDependencies() {
    _updateColorAnimation();
    super.didChangeDependencies();
  }

  void _updateColorAnimation() {
    final theme = Theme.of(context);
    final buttonTheme = theme.floatingActionButtonTheme;

    _color = widget.color ?? buttonTheme.backgroundColor;
    _loadingColor = widget.loadingColor ?? theme.accentColor;

    _colorAnimation = ColorTween(
      begin: _color,
      end: _loadingColor,
    ).animate(
      CurvedAnimation(
        parent: widget.controller,
        curve: const Interval(0.0, .65, curve: Curves.fastOutSlowIn),
      ),
    );
  }

  @override
  void didUpdateWidget(AnimatedButton oldWidget) {
    super.didUpdateWidget(oldWidget);

    if (oldWidget.color != widget.color ||
        oldWidget.loadingColor != widget.loadingColor) {
      _updateColorAnimation();
    }
  }

  @override
  void dispose() {
    super.dispose();
    widget.controller.removeStatusListener(handleStatusChanged);
  }

  void handleStatusChanged(status) {
    if (status == AnimationStatus.forward) {
      setState(() => _isLoading = true);
    }
    if (status == AnimationStatus.dismissed) {
      setState(() => _isLoading = false);
    }
  }

  Widget _buildButtonText(ThemeData theme) {
    return FadeTransition(
      opacity: _textOpacityAnimation,
      child: AnimatedText(
        text: widget.text,
        style: TextStyle(color: Colors.white, fontSize: 15),
      ),
    );
  }

  Widget _buildButton(ThemeData theme) {
    final buttonTheme = theme.floatingActionButtonTheme;

    return FadeTransition(
        opacity: _buttonOpacityAnimation,
        child: AnimatedContainer(
            duration: Duration(milliseconds: 300),
            child: AnimatedBuilder(
                animation: _colorAnimation,
                builder: (context, child) => Material(
                      shape: buttonTheme.shape,
                      color: Colors.deepPurple,
                      child: child,
                    ),
                child: InkWell(
                    onTap: !_isLoading ? widget.onPressed : null,
                    splashColor: buttonTheme.splashColor,
                    customBorder: buttonTheme.shape,
                    onHighlightChanged: (value) =>
                        setState(() => _hover = value),
                    child: SizeTransition(
                        sizeFactor: _sizeAnimation,
                        axis: Axis.horizontal,
                        child: Container(
                          width: _width,
                          height: _height,
                          alignment: Alignment.center,
                          child: _buildButtonText(theme),
                        ))))));
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);

    return Stack(alignment: Alignment.center, children: <Widget>[
      FadeTransition(
          opacity: _ringOpacityAnimation,
          child: AnimatedBuilder(
              animation: _ringThicknessAnimation,
              builder: (context, child) => Ring(
                    color: Colors.deepPurple,
                    size: _height,
                    thickness: _ringThicknessAnimation.value,
                  ))),
      if (_isLoading)
        SizedBox(
            width: _height - _loadingCircleThickness,
            height: _height - _loadingCircleThickness,
            child: CircularProgressIndicator(
              valueColor: AlwaysStoppedAnimation<Color>(Colors.deepPurple),
              // backgroundColor: Colors.red,
              strokeWidth: _loadingCircleThickness,
            )),
      _buildButton(theme),
    ]);
  }
}

animated_numeric_text.dart

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

class AnimatedNumericText extends StatelessWidget {
  AnimatedNumericText({
    Key key,
    @required this.initialValue,
    @required this.targetValue,
    @required this.controller,
    this.curve = Curves.linear,
    this.formatter = '#,##0.00',
    this.style,
  })  : numberFormat = NumberFormat(formatter),
        numberAnimation = Tween<double>(
          begin: initialValue,
          end: targetValue,
        ).animate(CurvedAnimation(
          parent: controller,
          curve: curve,
        )),
        super(key: key);

  final double initialValue;
  final double targetValue;
  final AnimationController controller;
  final Curve curve;
  final String formatter;
  final TextStyle style;
  final numberFormat;
  final Animation<double> numberAnimation;

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
        animation: numberAnimation,
        builder: (context, child) => Text(
              '${numberFormat.format(numberAnimation.value)}',
              style: style,
            ));
  }
}

animated_text.dart

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_world/helper/math_helper.dart';
import 'package:flutter_world/helper/matrix.dart';
import 'package:flutter_world/helper/widget_helper.dart';

enum AnimatedTextRotation { up, down }

class AnimatedText extends StatefulWidget {
  AnimatedText({
    Key key,
    @required this.text,
    this.style,
    this.textRotation = AnimatedTextRotation.up,
  }) : super(key: key);

  final String text;
  final TextStyle style;
  final AnimatedTextRotation textRotation;

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

class _AnimatedTextState extends State<AnimatedText>
    with SingleTickerProviderStateMixin {
  var _newText = '';
  var _oldText = '';
  var _layoutHeight = 0.0;
  final _textKey = GlobalKey();

  Animation<double> _animation;
  AnimationController _controller;

  double get radius => _layoutHeight / 2;

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

    _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
    );

    _animation = Tween<double>(begin: 0.0, end: pi / 2).animate(CurvedAnimation(
      parent: _controller,
      curve: Curves.easeOutBack,
    ));

    _oldText = widget.text;

    WidgetsBinding.instance.addPostFrameCallback((_) {
      setState(() => _layoutHeight = getWidgetSize(_textKey)?.height);
    });
  }

  @override
  void didUpdateWidget(AnimatedText oldWidget) {
    super.didUpdateWidget(oldWidget);

    if (widget.text != oldWidget.text) {
      _oldText = oldWidget.text;
      _newText = widget.text;
      _controller.forward().then((_) {
        setState(() {
          final t = _oldText;
          _oldText = _newText;
          _newText = t;
        });
        _controller.reset();
      });
    }
  }

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

  Matrix4 _getFrontSideUp(double value) {
    return Matrix.perspective(.006)
      ..translate(
        0.0,
        -radius * sin(_animation.value),
        -radius * cos(_animation.value),
      )
      ..rotateX(-_animation.value); // 0 -> -pi/2
  }

  Matrix4 _getBackSideUp(double value) {
    return Matrix.perspective(.006)
      ..translate(
        0.0,
        radius * cos(_animation.value),
        -radius * sin(_animation.value),
      )
      ..rotateX((pi / 2) - _animation.value); // pi/2 -> 0
  }

  Matrix4 _getFrontSideDown(double value) {
    return Matrix.perspective(.006)
      ..translate(
        0.0,
        radius * sin(_animation.value),
        -radius * cos(_animation.value),
      )
      ..rotateX(_animation.value); // 0 -> pi/2
  }

  Matrix4 _getBackSideDown(double value) {
    return Matrix.perspective(.006)
      ..translate(
        0.0,
        -radius * cos(_animation.value),
        -radius * sin(_animation.value),
      )
      ..rotateX(_animation.value - pi / 2); // -pi/2 -> 0
  }

  @override
  Widget build(BuildContext context) {
    final rollUp = widget.textRotation == AnimatedTextRotation.up;
    final oldText = Text(
      _oldText,
      key: _textKey,
      style: widget.style,
      overflow: TextOverflow.visible,
      softWrap: false,
    );
    final newText = Text(
      _newText,
      style: widget.style,
      overflow: TextOverflow.visible,
      softWrap: false,
    );

    return AnimatedBuilder(
        animation: _animation,
        builder: (context, child) =>
            Stack(alignment: Alignment.center, children: <Widget>[
              if (_animation.value <= MathHelper.toRadian(85))
                Transform(
                  alignment: Alignment.center,
                  transform: rollUp
                      ? _getFrontSideUp(_animation.value)
                      : _getFrontSideDown(_animation.value),
                  child: oldText,
                ),
              if (_animation.value >= MathHelper.toRadian(5))
                Transform(
                  alignment: Alignment.center,
                  transform: rollUp
                      ? _getBackSideUp(_animation.value)
                      : _getBackSideDown(_animation.value),
                  child: newText,
                )
            ]));
  }
}

expandable_container.dart

import 'package:flutter/material.dart';

enum ExpandableContainerState {
  expanded,
  shrunk,
}

class ExpandableContainer extends StatefulWidget {
  ExpandableContainer({
    Key key,
    @required this.child,
    @required this.controller,
    this.onExpandCompleted,
    this.alignment,
    this.backgroundColor,
    this.color,
    this.width,
    this.height,
    this.padding,
    this.initialState = ExpandableContainerState.shrunk,
  }) : super(key: key);

  final AnimationController controller;
  final Function onExpandCompleted;
  final Widget child;
  final Alignment alignment;
  final Color backgroundColor;
  final Color color;
  final double width;
  final double height;
  final EdgeInsetsGeometry padding;
  final ExpandableContainerState initialState;

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

class _ExpandableContainerState extends State<ExpandableContainer> {
  Animation<double> _sizeAnimation;
  Animation<Offset> _slideAnimation;
  AnimationController _controller;

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

    if (widget.initialState == ExpandableContainerState.expanded) {
      _controller = widget.controller..value = 1;
    } else {
      _controller = widget.controller..value = 0;
    }

    _sizeAnimation = Tween<double>(
      begin: 0.0,
      end: 1.0,
    ).animate(CurvedAnimation(
      parent: _controller,
      curve: const Interval(0.0, .6875, curve: Curves.bounceOut),
      reverseCurve: const Interval(0.0, .6875, curve: Curves.bounceIn),
    ));
    _slideAnimation = Tween<Offset>(
      begin: const Offset(-1, 0),
      end: const Offset(0, 0),
    ).animate(CurvedAnimation(
      parent: _controller,
      curve: const Interval(.6875, 1.0, curve: Curves.fastOutSlowIn),
    ))
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          widget?.onExpandCompleted();
        }
      });
  }

  @override
  Widget build(BuildContext context) {
    return SizeTransition(
        sizeFactor: _sizeAnimation,
        child: Stack(children: <Widget>[
          Positioned.fill(
            child: DecoratedBox(
              decoration: BoxDecoration(color: widget.backgroundColor),
            ),
          ),
          SlideTransition(
              position: _slideAnimation,
              child: Container(
                alignment: widget.alignment,
                color: widget.color,
                width: widget.width,
                height: widget.height,
                padding: widget.padding,
                child: widget.child,
              ))
        ]));
  }
}

fade_in.dart

import 'package:flutter/material.dart';

enum FadeDirection {
  startToEnd,
  endToStart,
  topToBottom,
  bottomToTop,
}

class FadeIn extends StatefulWidget {
  FadeIn({
    Key key,
    this.fadeDirection = FadeDirection.startToEnd,
    this.offset = 1.0,
    this.controller,
    this.duration,
    this.curve = Curves.easeOut,
    @required this.child,
  })  : assert(controller == null && duration != null ||
            controller != null && duration == null),
        assert(offset > 0),
        super(key: key);

  final AnimationController controller;
  final FadeDirection fadeDirection;
  final double offset;
  final Widget child;
  final Duration duration;
  final Curve curve;

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

class _FadeInState extends State<FadeIn> with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<Offset> _slideAnimation;
  Animation<double> _opacityAnimation;

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

    if (widget.controller == null) {
      _controller = AnimationController(
        vsync: this,
        duration: widget.duration,
      );
    }

    _updateAnimations();
    _controller?.forward();
  }

  void _updateAnimations() {
    Offset begin;
    Offset end;
    final offset = widget.offset;

    switch (widget.fadeDirection) {
      case FadeDirection.startToEnd:
        begin = Offset(-offset, 0);
        end = Offset(0, 0);
        break;
      case FadeDirection.endToStart:
        begin = Offset(offset, 0);
        end = Offset(0, 0);
        break;
      case FadeDirection.topToBottom:
        begin = Offset(0, -offset);
        end = Offset(0, 0);
        break;
      case FadeDirection.bottomToTop:
        begin = Offset(0, offset);
        end = Offset(0, 0);
        break;
    }

    _slideAnimation = Tween<Offset>(
      begin: begin,
      end: end,
    ).animate(CurvedAnimation(
      parent: _effectiveController,
      curve: widget.curve,
    ));
    _opacityAnimation = Tween<double>(
      begin: 0.0,
      end: 1.0,
    ).animate(CurvedAnimation(
      parent: _effectiveController,
      curve: widget.curve,
    ));
  }

  AnimationController get _effectiveController =>
      widget.controller ?? _controller;

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

  @override
  Widget build(BuildContext context) {
    return SlideTransition(
        position: _slideAnimation,
        child: FadeTransition(
          opacity: _opacityAnimation,
          child: widget.child,
        ));
  }
}

ring.dart

import 'package:flutter/material.dart';

class Ring extends StatelessWidget {
  Ring({
    Key key,
    this.color,
    this.size = 40.0,
    this.thickness = 2.0,
    this.value = 1.0,
  })  : assert(size - thickness > 0),
        assert(thickness >= 0),
        super(key: key);

  final Color color;
  final double size;
  final double thickness;
  final double value;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: size - thickness,
      height: size - thickness,
      child: thickness == 0
          ? null
          : CircularProgressIndicator(
              valueColor: AlwaysStoppedAnimation<Color>(color),
              strokeWidth: thickness,
              value: value,
            ),
    );
  }
}

round_button.dart

import 'package:flutter/material.dart';

class RoundButton extends StatefulWidget {
  RoundButton({
    Key key,
    @required this.icon,
    @required this.onPressed,
    @required this.label,
    @required this.loadingController,
    this.interval = const Interval(0, 1, curve: Curves.ease),
    this.size = 60,
  }) : super(key: key);

  final Widget icon;
  final VoidCallback onPressed;
  final String label;
  final AnimationController loadingController;
  final Interval interval;
  final double size;

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

class _RoundButtonState extends State<RoundButton>
    with SingleTickerProviderStateMixin {
  AnimationController _pressController;
  Animation<double> _scaleLoadingAnimation;
  Animation<double> _scaleAnimation;

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

    _pressController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 100),
      reverseDuration: const Duration(milliseconds: 500),
    );
    _scaleLoadingAnimation = Tween<double>(begin: 0, end: 1).animate(
      CurvedAnimation(
        parent: widget.loadingController,
        curve: widget.interval,
      ),
    );
    _scaleAnimation = Tween<double>(begin: 1, end: .75).animate(CurvedAnimation(
      parent: _pressController,
      curve: Curves.easeOut,
      reverseCurve: ElasticInCurve(0.3),
    ));
  }

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

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final primaryColor =
        Colors.primaries.where((c) => c == theme.primaryColor).first;

    return Padding(
        padding: const EdgeInsets.all(8.0),
        child: ScaleTransition(
            scale: _scaleLoadingAnimation,
            child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  ScaleTransition(
                      scale: _scaleAnimation,
                      child: SizedBox(
                          width: widget.size,
                          height: widget.size,
                          child: FittedBox(
                              child: FloatingActionButton(
                            // allow more than 1 FAB in the same screen (hero tag cannot be duplicated)
                            heroTag: null,
                            backgroundColor: primaryColor.shade400,
                            child: widget.icon,
                            onPressed: () {
                              _pressController.forward().then((_) {
                                _pressController.reverse();
                              });
                              widget.onPressed();
                            },
                            foregroundColor: Colors.white,
                          )))),
                  SizedBox(height: 10),
                  Text(
                    widget.label,
                    style: theme.textTheme.caption
                        .copyWith(color: theme.primaryColor),
                    textAlign: TextAlign.center,
                  )
                ])));
  }
}

login_screen.dart

import 'dart:math';
import 'package:flutter/scheduler.dart' show timeDilation;
import 'package:flutter/material.dart';
import 'package:flutter_world/widget/animated_numeric_text.dart';
import 'widget/animated_button.dart';
import 'widget/expandable_container.dart';

class FlutterLogin extends StatefulWidget {
  @override
  LoginScreen createState() => LoginScreen();
}

class LoginScreen extends State<FlutterLogin> with TickerProviderStateMixin {
  Duration get loginTime => Duration(milliseconds: timeDilation.ceil() * 2250);
  AnimationController _submitController;
  AnimationController _switchAuthController;
  AnimationController _postSwitchAuthController;
  bool isLogin = true;

  @override
  void initState() {
    super.initState();
    _switchAuthController = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 800),
    );

    _postSwitchAuthController = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 150),
    );

    _submitController = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 1000),
    );

    _switchAuthController.reverse();
  }

  @override
  Widget build(BuildContext context) {
    final deviceSize = MediaQuery.of(context).size;

    return Scaffold(
        appBar: AppBar(
          title: Text('Button Animation'),
        ),
        body: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                  width: min(deviceSize.width, 360.0),
                  child: _buildSubmitButton()),
              ExpandableContainer(
                controller: _switchAuthController,
                initialState: isLogin
                    ? ExpandableContainerState.shrunk
                    : ExpandableContainerState.expanded,
                alignment: Alignment.topLeft,
                color: Colors.white,
                padding: EdgeInsets.symmetric(
                  horizontal: 12,
                  vertical: 10,
                ),
                onExpandCompleted: () => _postSwitchAuthController.forward(),
                child: Column(children: <Widget>[Text('Data is display')]),
              )
            ]));
  }

  Widget _buildSubmitButton() {
    return AnimatedButton(
        color: Colors.deepPurple,
        controller: _submitController,
        text: 'Login',
        onPressed: () async {
          _switchAuthController.reverse();
          _submitController.forward();
          await Future.delayed(Duration(seconds: 5));
          _submitController.reverse();
          _switchAuthController.forward();
        });
  }
}

dashboard_screen.dart

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

import 'widget/animated_numeric_text.dart';
import 'widget/fade_in.dart';
import 'widget/round_button.dart';

class DashboardScreen extends StatefulWidget {
  static const routeName = '/dashboard';

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

class _DashboardScreenState extends State<DashboardScreen>
    with SingleTickerProviderStateMixin {
  Future<bool> _goToLogin(BuildContext context) {
    return Navigator.of(context).pushReplacementNamed('/').then((_) => false);
  }

  static const headerAniInterval =
      const Interval(.1, .3, curve: Curves.easeOut);
  Animation<double> _headerScaleAnimation;
  AnimationController _loadingController;

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

    _loadingController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 1250),
    );

    _headerScaleAnimation =
        Tween<double>(begin: .6, end: 1).animate(CurvedAnimation(
      parent: _loadingController,
      curve: headerAniInterval,
    ));
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }

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

  @override
  void didPushAfterTransition() => _loadingController.forward();

  AppBar _buildAppBar(ThemeData theme) {
    final menuBtn = IconButton(
      color: theme.accentColor,
      icon: const Icon(FontAwesomeIcons.bars),
      onPressed: () {},
    );
    final signOutBtn = IconButton(
      icon: const Icon(FontAwesomeIcons.signOutAlt),
      color: theme.accentColor,
      onPressed: () => _goToLogin(context),
    );
    final title = Center(
        child:
            Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
      /* Padding(
            padding: const EdgeInsets.symmetric(vertical: 8.0),
            child: Hero(
              child: Image.asset(
                'assets/images/ecorp.png',
                filterQuality: FilterQuality.high,
              ),
            ),
          ),*/
      SizedBox(width: 20),
    ]));

    return AppBar(
      leading: FadeIn(
        child: menuBtn,
        controller: _loadingController,
        offset: .3,
        curve: headerAniInterval,
        fadeDirection: FadeDirection.startToEnd,
      ),
      actions: <Widget>[
        FadeIn(
          child: signOutBtn,
          controller: _loadingController,
          offset: .3,
          curve: headerAniInterval,
          fadeDirection: FadeDirection.endToStart,
        )
      ],
      title: title,
      backgroundColor: theme.primaryColor.withOpacity(.1),
      elevation: 0,
      textTheme: theme.accentTextTheme,
      iconTheme: theme.accentIconTheme,
    );
  }

  Widget _buildHeader(ThemeData theme) {
    final primaryColor =
        Colors.primaries.where((c) => c == theme.primaryColor).first;
    final accentColor =
        Colors.primaries.where((c) => c == theme.accentColor).first;
    final linearGradient = LinearGradient(colors: [
      primaryColor.shade800,
      primaryColor.shade200,
    ]).createShader(Rect.fromLTWH(0.0, 0.0, 418.0, 78.0));

    return ScaleTransition(
        scale: _headerScaleAnimation,
        child: FadeIn(
            controller: _loadingController,
            curve: headerAniInterval,
            fadeDirection: FadeDirection.bottomToTop,
            offset: .5,
            child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Text('\$',
                            style: theme.textTheme.display2.copyWith(
                              fontWeight: FontWeight.w300,
                              color: accentColor.shade400,
                            )),
                        SizedBox(width: 5),
                        AnimatedNumericText(
                            initialValue: 0,
                            targetValue: 3467.87,
                            curve: Interval(0, .5, curve: Curves.easeOut),
                            controller: _loadingController,
                            style: theme.textTheme.display2.copyWith(
                              foreground: Paint()..shader = linearGradient,
                            ))
                      ]),
                  Text('Account Balance', style: theme.textTheme.caption),
                ])));
  }

  Widget _buildButton({Widget icon, String label, Interval interval}) {
    return RoundButton(
      icon: icon,
      label: label,
      loadingController: _loadingController,
      interval: Interval(
        interval.begin,
        interval.end,
        curve: ElasticOutCurve(0.42),
      ),
      onPressed: () {},
    );
  }

  Widget _buildDashboardGrid() {
    const step = 0.04;
    const aniInterval = 0.75;

    return GridView.count(
      padding: const EdgeInsets.symmetric(
        horizontal: 32.0,
        vertical: 20,
      ),
      childAspectRatio: .9,
      // crossAxisSpacing: 5,
      crossAxisCount: 3,
      children: [
        _buildButton(
          icon: Icon(FontAwesomeIcons.user),
          label: 'Profile',
          interval: Interval(0, aniInterval),
        ),
        _buildButton(
          icon: Container(
            // fix icon is not centered like others for some reasons
            padding: const EdgeInsets.only(left: 16.0),
            alignment: Alignment.centerLeft,
            child: Icon(
              FontAwesomeIcons.moneyBillAlt,
              size: 20,
            ),
          ),
          label: 'Fund Transfer',
          interval: Interval(step, aniInterval + step),
        ),
        _buildButton(
          icon: Icon(FontAwesomeIcons.handHoldingUsd),
          label: 'Payment',
          interval: Interval(step * 2, aniInterval + step * 2),
        ),
        _buildButton(
          icon: Icon(FontAwesomeIcons.chartLine),
          label: 'Report',
          interval: Interval(0, aniInterval),
        ),
        _buildButton(
          icon: Icon(Icons.vpn_key),
          label: 'Register',
          interval: Interval(step, aniInterval + step),
        ),
        _buildButton(
          icon: Icon(FontAwesomeIcons.history),
          label: 'History',
          interval: Interval(step * 2, aniInterval + step * 2),
        ),
        _buildButton(
          icon: Icon(FontAwesomeIcons.ellipsisH),
          label: 'Other',
          interval: Interval(0, aniInterval),
        ),
        _buildButton(
          icon: Icon(FontAwesomeIcons.search, size: 20),
          label: 'Search',
          interval: Interval(step, aniInterval + step),
        ),
        _buildButton(
          icon: Icon(FontAwesomeIcons.slidersH, size: 20),
          label: 'Settings',
          interval: Interval(step * 2, aniInterval + step * 2),
        ),
      ],
    );
  }

  Widget _buildDebugButtons() {
    const textStyle = TextStyle(fontSize: 12, color: Colors.white);

    return Positioned(
        bottom: 0,
        right: 0,
        child: Row(children: <Widget>[
          RaisedButton(
            materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
            color: Colors.red,
            child: Text('loading', style: textStyle),
            onPressed: () => _loadingController.value == 0
                ? _loadingController.forward()
                : _loadingController.reverse(),
          )
        ]));
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);

    return WillPopScope(
        onWillPop: () => _goToLogin(context),
        child: SafeArea(
            child: Scaffold(
                appBar: _buildAppBar(theme),
                body: Container(
                    width: double.infinity,
                    height: double.infinity,
                    color: theme.primaryColor.withOpacity(.1),
                    child: Stack(children: <Widget>[
                      Column(children: <Widget>[
                        SizedBox(height: 40),
                        Expanded(
                          flex: 2,
                          child: _buildHeader(theme),
                        ),
                        Expanded(
                            flex: 8,
                            child: ShaderMask(
                              // blendMode: BlendMode.srcOver,
                              shaderCallback: (Rect bounds) {
                                return LinearGradient(
                                  begin: Alignment.topLeft,
                                  end: Alignment.bottomRight,
                                  tileMode: TileMode.clamp,
                                  colors: <Color>[
                                    Colors.deepPurpleAccent.shade100,
                                    Colors.deepPurple.shade100,
                                    Colors.deepPurple.shade100,
                                    Colors.deepPurple.shade100,
                                    // Colors.red,
                                    // Colors.yellow,
                                  ],
                                ).createShader(bounds);
                              },
                              child: _buildDashboardGrid(),
                            ))
                      ]),
                      if (!kReleaseMode) _buildDebugButtons(),
                    ])))));
  }
}

main.dart

import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:flutter_world/dashboard_screen.dart';
import 'login_screen.dart';

void main() {
  SystemChrome.setSystemUIOverlayStyle(
    SystemUiOverlayStyle(
      systemNavigationBarColor:
          SystemUiOverlayStyle.dark.systemNavigationBarColor,
    ),
  );
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Login Demo',
      theme: ThemeData(
        // brightness: Brightness.dark,
        primarySwatch: Colors.deepPurple,
        accentColor: Colors.orange,
        cursorColor: Colors.orange,
      ),
      home: DashboardScreen(),
    );
  }
}

pubspec.yaml

name: flutter_world
description: A new Flutter application.
version: 1.0.0+1

environment:
  sdk: ">=2.2.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.2
  flushbar:
  intl:
  font_awesome_flutter:

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true

The flutter tutorial  is a website that bring you the latest and amazing resources of code. All the languages codes are included in this website. The languages like flutter, android, java,kotlin etc.with the help of this languages any user can develop the beautiful application

For more information about Flutter. visit www.fluttertutorial.in