Skip to content

Instantly share code, notes, and snippets.

@riyoua
Created February 23, 2022 12:20
Show Gist options
  • Save riyoua/704edfd9daa86be81cdb5669df12c5b3 to your computer and use it in GitHub Desktop.
Save riyoua/704edfd9daa86be81cdb5669df12c5b3 to your computer and use it in GitHub Desktop.
my_snippets
import 'dart:math';
import 'package:flutter/material.dart';
class PageFlipBuilder extends StatefulWidget {
const PageFlipBuilder(
{Key? key, required this.frontBuilder, required this.backBuilder})
: super(key: key);
final WidgetBuilder frontBuilder;
final WidgetBuilder backBuilder;
@override
PageFlipBuilderState createState() => PageFlipBuilderState();
}
class PageFlipBuilderState extends State<PageFlipBuilder>
with SingleTickerProviderStateMixin {
late final _controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1000),
);
@override
void initState() {
super.initState();
_controller.addStatusListener(_updateStatus);
}
@override
void dispose() {
_controller.removeStatusListener(_updateStatus);
_controller.dispose();
super.dispose();
}
bool _showFrontSide = true;
void _updateStatus(AnimationStatus status) {
if (status == AnimationStatus.completed ||
status == AnimationStatus.dismissed) {
setState(() => _showFrontSide = !_showFrontSide);
}
}
void flip() {
//TODO: update state
if (_showFrontSide) {
_controller.forward();
} else {
_controller.reverse();
}
}
@override
Widget build(BuildContext context) {
return AnimatedPageFlipBuilder(
animation: _controller,
showFrontSide: _showFrontSide,
frontBuilder: widget.frontBuilder,
backBuilder: widget.backBuilder);
}
}
class AnimatedPageFlipBuilder extends AnimatedWidget {
const AnimatedPageFlipBuilder(
{Key? key,
required Animation<double> animation,
required this.showFrontSide,
required this.frontBuilder,
required this.backBuilder})
: super(key: key, listenable: animation);
final bool showFrontSide;
final WidgetBuilder frontBuilder;
final WidgetBuilder backBuilder;
Animation<double> get animation => listenable as Animation<double>;
@override
Widget build(BuildContext context) {
//TODO: add rotation code
// animation values [0,1] -> rotation values [0,pi]
//show the front side for animation values between 0.0 and 0.5
//show the back side animation values between 0.5 and 1.0
final isAnimationFirstHalf = animation.value < 0.5;
// decide which page we need to show
final child =
isAnimationFirstHalf ? frontBuilder(context) : backBuilder(context);
// map values between [0,1] to values between [0,pi]
final rotationValue = animation.value * pi;
final rotationAngel =
animation.value > 0.5 ? pi - rotationValue : rotationValue;
// calculate tilt value
var tilt = (animation.value - 0.5).abs() - 0.5;
tilt *= isAnimationFirstHalf ? -0.003 : 0.003;
return Transform(
transform: Matrix4.rotationY(rotationAngel)..setEntry(3, 0, tilt),
child: child,
alignment: Alignment.center,
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment