Skip to content

Instantly share code, notes, and snippets.

@johnmuchow
Created December 28, 2018 20:23
Show Gist options
  • Save johnmuchow/ace1d3ed0ee340bf85c86d35a3d936bd to your computer and use it in GitHub Desktop.
Save johnmuchow/ace1d3ed0ee340bf85c86d35a3d936bd to your computer and use it in GitHub Desktop.
Flutter Rotating Cell
import 'package:flutter/material.dart';
import 'dart:math' as math;
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Home(),
),
),
);
}
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.black,
alignment: Alignment.topCenter,
child: _buildRotatingCells(context),
);
}
}
Widget _buildRotatingCells(BuildContext context) {
return RotatingCell(
frontWidget: Container(
color: Colors.grey[200],
alignment: Alignment.center,
child: Text("Front",
style: TextStyle(color: Colors.black, fontSize: 20.0, fontWeight: FontWeight.bold))),
backWidget: Container(
color: Colors.blue[200],
alignment: Alignment.center,
child: Text("Back",
style: TextStyle(color: Colors.black, fontSize: 20.0, fontWeight: FontWeight.bold))),
cellSize: Size(MediaQuery.of(context).size.width, 250),
padding: EdgeInsets.all(25),
);
}
class RotatingCell extends StatefulWidget {
RotatingCell(
{Key key,
@required this.frontWidget,
@required this.backWidget,
this.cellSize,
this.padding});
final Widget frontWidget;
final Widget backWidget;
final Size cellSize;
final EdgeInsetsGeometry padding;
@override
_RotatingCellState createState() => _RotatingCellState();
}
class _RotatingCellState extends State<RotatingCell> with SingleTickerProviderStateMixin {
final ninetyDegrees = math.pi / 2;
bool _isRotated = false;
double _currentAnimationValue;
AnimationController _animationController;
@override
void initState() {
super.initState();
_currentAnimationValue = 0;
_animationController = AnimationController(vsync: this, duration: Duration(milliseconds: 500));
_animationController.addListener(() {
setState(() {
_currentAnimationValue = _animationController.value;
});
});
}
@override
void dispose() {
if (_animationController != null) _animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final angleInRadians = _currentAnimationValue * math.pi;
return GestureDetector(
onTap: _rotate,
child: Padding(
padding: widget.padding,
child: Container(
child: Stack(
children: <Widget>[
Transform(
alignment: FractionalOffset(0.5, 0.5),
transform: (Matrix4.identity()
..setEntry(3, 2, 0.001)
// For back widget, we want to go from the
// rotated to normal.
..rotateY(-(math.pi - angleInRadians))),
child: Container(
// If <= 90 degrees, set no height or width
height: angleInRadians <= ninetyDegrees ? 0.0 : widget.cellSize.height,
width: angleInRadians <= ninetyDegrees ? 0.0 : widget.cellSize.width,
child: widget.backWidget,
),
),
Transform(
alignment: FractionalOffset(0.5, 0.5),
transform: (Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateY(angleInRadians)),
child: Container(
// If >= 90 degrees, set no height or width
height: angleInRadians >= ninetyDegrees ? 0.0 : widget.cellSize.height,
width: angleInRadians >= ninetyDegrees ? 0.0 : widget.cellSize.width,
child: widget.frontWidget,
),
),
],
),
),
),
);
}
void _rotate() {
if (_isRotated)
_animationController.reverse();
else
_animationController.forward();
_isRotated = !_isRotated;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment