Will Prosser
Will Prosser

Reputation: 35

Card flip to hero/dialog in Flutter

Looking to achieve an animation going from a bunch of card-like widgets in a gridview to a simple dialog, using a hero-style transition. I've mocked something up in Unity to demonstrate the concept

Card flip animation mockup

I've played around a bit with a hero tranisition (trying various things like RotationTransition) and have also used a package called Flip Card (https://pub.dev/packages/flip_card), but I can't quite get the two concepts working together, wondering if someone had some ideas

Upvotes: 1

Views: 1912

Answers (1)

Jim
Jim

Reputation: 7601

It's quite fun actually, I've done it, try this code:

import 'package:flutter/material.dart';
import 'package:flip_card/flip_card.dart';
import 'package:after_layout/after_layout.dart';

class FlipCardHero extends StatefulWidget {
  @override
  _FlipCardHeroState createState() => _FlipCardHeroState();
}

class _FlipCardHeroState extends State<FlipCardHero> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: GridView.builder(
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 4,
          childAspectRatio: 1.0,
        ),
        itemCount: 12,
        itemBuilder: (context, index) {
          return GestureDetector(
            child: Hero(
              tag: 'flipcardHero$index',
              child: Container(
                color: Colors.yellow[50],
                height: 150,
                child: FlipCard(
                  flipOnTouch: false,
                  direction: FlipDirection.HORIZONTAL,
                  front: Container(
                    child: Text('Front'),
                  ),
                  back: Container(
                    child: Text('Back'),
                  ),
                ),
              ),
            ),
            onTap: () {
              Navigator.of(context).push(
                PageRouteBuilder(
                  opaque: false,
                  pageBuilder: (_, __, ___) =>
                      SingleFlipCard(id: 'flipcardHero$index'),
                ),
              );
            },
          );
        },
      ),
    );
  }
}

class SingleFlipCard extends StatefulWidget {
  final id;
  SingleFlipCard({@required this.id});

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

class SingleFlipCardState extends State<SingleFlipCard>
    with AfterLayoutMixin<SingleFlipCard> {
  final GlobalKey<FlipCardState> cardKey = GlobalKey<FlipCardState>();

  @override
  void afterFirstLayout(BuildContext context) {
    cardKey.currentState.toggleCard();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.transparent,
      body: GestureDetector(
        child: Center(
          child: Hero(
            tag: widget.id,
            child: Container(
              color: Colors.yellow[50],
              height: 150,
              child: FlipCard(
                key: cardKey,
                flipOnTouch: false,
                direction: FlipDirection.HORIZONTAL,
                front: Container(
                  width: 200,
                  height: 400,
                  child: Text('Front'),
                ),
                back: Container(
                  width: 200,
                  height: 400,
                  child: Text('Back'),
                ),
              ),
            ),
          ),
        ),
        onTap: () {
          Navigator.pop(context);
        },
      ),
    );
  }
}

Upvotes: 4

Related Questions