Skip to content

Instantly share code, notes, and snippets.

@graphicbeacon
Created February 28, 2020 23:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save graphicbeacon/8463ce2ab4cedb87f5659cf260134ab9 to your computer and use it in GitHub Desktop.
Save graphicbeacon/8463ce2ab4cedb87f5659cf260134ab9 to your computer and use it in GitHub Desktop.
Flippable card effect in Flutter
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:math';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: Center(
child: MyAppView()
)
),
);
}
}
class MyAppView extends StatefulWidget {
@override
_MyAppViewState createState() => _MyAppViewState();
}
class _MyAppViewState extends State<MyAppView> {
bool isFlipped;
@override
void initState() {
isFlipped = false;
super.initState();
}
@override
Widget build(BuildContext context) {
return Center(
child: GestureDetector(
onTap: () {
setState(() {
isFlipped = !isFlipped;
});
},
child: FlippableBox(
isFlipped: isFlipped,
front: Card(
child: SizedBox(width: 250, height: 250, child: Text('FRONT'))
),
back: Card(
child: SizedBox(width: 250, height: 250, child: Text('BACK'))
)
)
)
);
}
}
class FlippableBox extends StatelessWidget {
final Widget front;
final Widget back;
final bool isFlipped;
const FlippableBox({Key key, this.isFlipped = false, this.front, this.back}) : super(key: key);
@override
Widget build(BuildContext context) {
return TweenAnimationBuilder(
duration: Duration(milliseconds: 700),
curve: Curves.easeOut,
tween: Tween<double>(begin: 0, end: isFlipped ? 180 : 0),
builder: (context, value, child) {
var content = value >= 90 ? back : front;
return RotationY(
rotationY: value,
child: RotationY(
rotationY: value >= 90 ? 180 : 0,
child: content
)
);
}
);
}
}
class RotationY extends StatelessWidget {
// Degrees to rads constant
static const double degrees2Radians = pi / 180;
final Widget child;
final double rotationY;
const RotationY({Key key, @required this.child, this.rotationY = 0}): super(key: key);
@override
Widget build(BuildContext context) {
return Transform(
alignment: FractionalOffset.center,
transform: Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateY(rotationY * degrees2Radians),
child: child,
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment