Last active
June 15, 2023 20:00
-
-
Save CoderNamedHendrick/60aa71afcf34149e7acd21f67de151e6 to your computer and use it in GitHub Desktop.
A splash screen with some animations going on.
This file contains hidden or 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
void main() { | |
runApp(const MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
const MyApp({super.key}); | |
// This widget is the root of your application. | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Flutter Demo', | |
theme: ThemeData( | |
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), | |
useMaterial3: true, | |
), | |
home: const AnimatingSplashScreen(), | |
); | |
} | |
} | |
class AnimatingSplashScreen extends StatefulWidget { | |
const AnimatingSplashScreen({Key? key}) : super(key: key); | |
@override | |
State<AnimatingSplashScreen> createState() => _AnimatingSplashScreenState(); | |
} | |
class _AnimatingSplashScreenState extends State<AnimatingSplashScreen> | |
with SingleTickerProviderStateMixin { | |
late final AnimationController _controller; | |
late final Animation<double> _scaleAnim; | |
late final Animation<int> _rotationAngleAnim; | |
final _navNextPage = ValueNotifier(false); | |
@override | |
void initState() { | |
super.initState(); | |
_controller = AnimationController( | |
vsync: this, | |
duration: const Duration(milliseconds: 1800), | |
); | |
_scaleAnim = Tween<double>(begin: 8, end: 1) | |
.animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut)); | |
_rotationAngleAnim = IntTween(begin: -45, end: 0).animate( | |
CurvedAnimation( | |
parent: _controller, | |
curve: const Interval(0.5, 1, curve: Curves.easeInOutQuad)), | |
); | |
_controller.addStatusListener((status) { | |
if (status == AnimationStatus.completed) { | |
Timer( | |
const Duration(milliseconds: 900), | |
() async { | |
_navNextPage.value = true; | |
await Future.delayed(const Duration(milliseconds: 50)); | |
if (!mounted) return; | |
Navigator.of(context) | |
.push(AxisPageRoute(builder: (_) => const NextScreen())); | |
}, | |
); | |
} | |
}); | |
_controller.forward(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
// timeDilation = 5; | |
const size = 200.0; | |
return Scaffold( | |
backgroundColor: Colors.red, | |
body: AnimatedBuilder( | |
animation: _controller, | |
child: Container( | |
height: size, | |
width: size, | |
decoration: const ShapeDecoration( | |
color: Colors.white, | |
shape: RoundedRectangleBorder( | |
borderRadius: BorderRadius.all(Radius.circular(12)), | |
), | |
), | |
), | |
builder: (context, child) { | |
return ValueListenableBuilder<bool>( | |
valueListenable: _navNextPage, | |
builder: (_, isNavigating, __) { | |
if (isNavigating) { | |
return TweenAnimationBuilder( | |
tween: Tween<double>( | |
begin: MediaQuery.of(context).size.height / 2 - (size / 2), | |
end: 100, | |
), | |
curve: Curves.easeInOut, | |
duration: const Duration(milliseconds: 200), | |
builder: (_, progress, __) { | |
return Transform( | |
alignment: Alignment.center, | |
transform: Matrix4.identity() | |
..setTranslationRaw( | |
MediaQuery.of(context).size.width / 2 - (size / 2), | |
progress, | |
0, | |
) | |
..scale(_scaleAnim.value, _scaleAnim.value, 1.0) | |
..rotateZ(_rotationAngleAnim.value * (pi / 180)), | |
child: child!, | |
); | |
}, | |
); | |
} | |
return Transform( | |
alignment: Alignment.center, | |
transform: Matrix4.identity() | |
..setTranslationRaw( | |
MediaQuery.of(context).size.width / 2 - (size / 2), | |
MediaQuery.of(context).size.height / 2 - (size / 2), | |
0, | |
) | |
..scale(_scaleAnim.value, _scaleAnim.value, 1.0) | |
..rotateZ(_rotationAngleAnim.value * (pi / 180)), | |
child: child!, | |
); | |
}, | |
); | |
}, | |
), | |
); | |
} | |
} | |
class NextScreen extends StatelessWidget { | |
const NextScreen({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
body: Center( | |
child: Text( | |
'Next Screen', | |
style: Theme.of(context).textTheme.displaySmall?.copyWith( | |
color: Theme.of(context).colorScheme.primary, | |
), | |
), | |
), | |
); | |
} | |
} | |
/// This Page Route allows you to transition in 4 different axis directions | |
/// Up, Down, Left, Right. | |
class AxisPageRoute<T> extends PageRouteBuilder<T> { | |
final WidgetBuilder builder; | |
final AxisDirection axis; | |
AxisPageRoute({required this.builder, this.axis = AxisDirection.down}) | |
: super( | |
pageBuilder: (context, animation, secondaryAnimation) => | |
builder(context), | |
transitionDuration: const Duration(milliseconds: 500), | |
transitionsBuilder: (context, animation, secondaryAnimation, child) { | |
final begin = switch (axis) { | |
AxisDirection.up => const Offset(0, -1), | |
AxisDirection.down => const Offset(0, 0.8), | |
AxisDirection.left => const Offset(-1, 0), | |
AxisDirection.right => const Offset(1, 0), | |
}; | |
const end = Offset.zero; | |
final tween = Tween(begin: begin, end: end) | |
.chain(CurveTween(curve: Curves.fastEaseInToSlowEaseOut)); | |
final offsetAnimation = animation.drive(tween); | |
return SlideTransition( | |
position: offsetAnimation, | |
child: child, | |
); | |
}, | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment