feat: splash page
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../common/theme/theme.dart';
|
||||
import '../components/assets/assets.gen.dart';
|
||||
|
||||
@RoutePage()
|
||||
class SplashPage extends StatefulWidget {
|
||||
const SplashPage({super.key});
|
||||
@@ -9,12 +12,160 @@ class SplashPage extends StatefulWidget {
|
||||
State<SplashPage> createState() => _SplashPageState();
|
||||
}
|
||||
|
||||
class _SplashPageState extends State<SplashPage> {
|
||||
class _SplashPageState extends State<SplashPage> with TickerProviderStateMixin {
|
||||
late AnimationController _logoController;
|
||||
late AnimationController _versionController;
|
||||
late AnimationController _backgroundController;
|
||||
|
||||
late Animation<double> _logoAnimation;
|
||||
late Animation<double> _versionAnimation;
|
||||
late Animation<double> _backgroundAnimation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
// Initialize animation controllers
|
||||
_logoController = AnimationController(
|
||||
duration: const Duration(milliseconds: 1200),
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
_versionController = AnimationController(
|
||||
duration: const Duration(milliseconds: 800),
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
_backgroundController = AnimationController(
|
||||
duration: const Duration(milliseconds: 1500),
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
// Create animations
|
||||
_logoAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
||||
CurvedAnimation(parent: _logoController, curve: Curves.elasticOut),
|
||||
);
|
||||
|
||||
_versionAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
||||
CurvedAnimation(parent: _versionController, curve: Curves.easeInOut),
|
||||
);
|
||||
|
||||
_backgroundAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
||||
CurvedAnimation(parent: _backgroundController, curve: Curves.easeInOut),
|
||||
);
|
||||
|
||||
// Start animations
|
||||
_startAnimations();
|
||||
}
|
||||
|
||||
void _startAnimations() async {
|
||||
// Start background animation immediately
|
||||
_backgroundController.forward();
|
||||
|
||||
// Wait a bit, then start logo animation
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
if (mounted) _logoController.forward();
|
||||
|
||||
// Start version animation after logo starts
|
||||
await Future.delayed(const Duration(milliseconds: 600));
|
||||
if (mounted) _versionController.forward();
|
||||
|
||||
// Navigate to home screen after all animations complete
|
||||
await Future.delayed(const Duration(milliseconds: 2000));
|
||||
if (mounted) {
|
||||
_navigateToHome();
|
||||
}
|
||||
}
|
||||
|
||||
void _navigateToHome() {
|
||||
// Uncomment dan sesuaikan dengan route yang ada
|
||||
// context.router.replace(const HomeRoute());
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_logoController.dispose();
|
||||
_versionController.dispose();
|
||||
_backgroundController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Text("Splash Page"),
|
||||
body: AnimatedBuilder(
|
||||
animation: Listenable.merge([
|
||||
_logoController,
|
||||
_versionController,
|
||||
_backgroundController,
|
||||
]),
|
||||
builder: (context, child) {
|
||||
// Clamp values to prevent opacity errors
|
||||
final logoOpacity = _logoAnimation.value.clamp(0.0, 1.0);
|
||||
final versionOpacity = _versionAnimation.value.clamp(0.0, 1.0);
|
||||
final backgroundOpacity = _backgroundAnimation.value.clamp(0.0, 1.0);
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
AppColor.primaryWithOpacity(backgroundOpacity),
|
||||
AppColor.primaryWithOpacity(backgroundOpacity * 0.8),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
// Logo di tengah
|
||||
Center(
|
||||
child: Transform.scale(
|
||||
scale: logoOpacity,
|
||||
child: Opacity(
|
||||
opacity: logoOpacity,
|
||||
child: Container(
|
||||
width: 150,
|
||||
height: 150,
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 30,
|
||||
offset: const Offset(0, 15),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(AppValue.radius),
|
||||
child: Assets.images.logo.image(fit: BoxFit.cover),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Version di bagian bawah
|
||||
Positioned(
|
||||
bottom: 60,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Transform.translate(
|
||||
offset: Offset(0, 20 * (1 - versionOpacity)),
|
||||
child: Opacity(
|
||||
opacity: versionOpacity,
|
||||
child: Text(
|
||||
'Version 1.0.0',
|
||||
style: AppStyle.md.copyWith(color: AppColor.textLight),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user