Created
February 23, 2022 12:20
-
-
Save riyoua/704edfd9daa86be81cdb5669df12c5b3 to your computer and use it in GitHub Desktop.
my_snippets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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