Skip to content

Instantly share code, notes, and snippets.

@CoderNamedHendrick
Last active June 15, 2023 20:00
Show Gist options
  • Save CoderNamedHendrick/60aa71afcf34149e7acd21f67de151e6 to your computer and use it in GitHub Desktop.
Save CoderNamedHendrick/60aa71afcf34149e7acd21f67de151e6 to your computer and use it in GitHub Desktop.
A splash screen with some animations going on.
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