Flutter AnimatedSwitcher Widget Examples: Flip Card

AnimatedSwitcher widget replaces its previously set as child with a new widget using transition animation.

By default, fade animation is used to switch widgets. We can use AnimatedSwitcher’s transitionBuilder property to apply custom animation.

Flip Card

To create a flip card, we use AnimatedSwitcher to switch between 2 widgets which are front and rear ones. Rotation animation is set in transitionBuilder.

import 'dart:math';

import 'package:flutter/material.dart';

class FlipCardPage extends StatefulWidget {
  @override
  _FlipCardPageState createState() => _FlipCardPageState();
}

class _FlipCardPageState extends State<FlipCardPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flip Animation'),
      ),
      body: Container(
        width: double.infinity,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            FlipCard(),
          ],
        ),
      ),
    );
  }
}

class FlipCard extends StatefulWidget {
  @override
  _FlipCardState createState() => _FlipCardState();
}

class _FlipCardState extends State<FlipCard>
    with SingleTickerProviderStateMixin {
  bool _isFront = true;

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

  Widget _frontCard() {
    return Container(
      key: ValueKey(true),
      color: Colors.orangeAccent,
      width: 200,
      height: 200,
      child: Center(
          child: Text(
        'Front',
        style: TextStyle(color: Colors.white, fontSize: 48),
      )),
    );
  }

  Widget _rearCard() {
    return Container(
      key: ValueKey(false),
      color: Colors.orange,
      width: 200,
      height: 200,
      child: Center(
          child: Text(
        'Rear',
        style: TextStyle(color: Colors.white, fontSize: 48),
      )),
    );
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        setState(() {
          _isFront = !_isFront;
        });
      },
      child: AnimatedSwitcher(
        child: _isFront ? _frontCard() : _rearCard(),
        duration: Duration(seconds: 1),
        transitionBuilder: (Widget child, Animation<double> animation) {
          final rotate = Tween(begin: pi, end: 0.0).animate(animation);

          return AnimatedBuilder(
              animation: rotate,
              child: child,
              builder: (BuildContext context, Widget child) {
                final angle = (ValueKey(_isFront) != widget.key)
                    ? min(rotate.value, pi / 2)
                    : rotate.value;
                return Transform(
                  transform: Matrix4.rotationY(angle),
                  child: child,
                  alignment: Alignment.center,
                );
              });
        },
        switchInCurve: Curves.easeInCubic,
        switchOutCurve: Curves.easeOutCubic,
      ),
    );
  }
}

Leave a Comment

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