import 'package:flutter/material.dart'; import 'package:animated_bottom_navigation_bar/animated_bottom_navigation_bar.dart'; import 'package:aesthetica_wallpaper/widgets/animated_background.dart'; class CustomBottomNavBar extends StatefulWidget { final int currentIndex; final Function(int) onTap; final VoidCallback? onFabPressed; const CustomBottomNavBar({ super.key, required this.currentIndex, required this.onTap, this.onFabPressed, }); @override State createState() => _CustomBottomNavBarState(); } class _CustomBottomNavBarState extends State with TickerProviderStateMixin { late AnimationController _fabAnimationController; late AnimationController _borderRadiusAnimationController; late Animation fabAnimation; late Animation borderRadiusAnimation; late CurvedAnimation fabCurve; late CurvedAnimation borderRadiusCurve; late AnimationController _hideBottomBarAnimationController; final List _iconList = [ Icons.dashboard_rounded, Icons.favorite_rounded, Icons.chat_bubble_rounded, Icons.settings_rounded, ]; final List _labelList = ['Home', 'Favorites', 'Messages', 'Settings']; @override void initState() { super.initState(); _fabAnimationController = AnimationController( duration: const Duration(milliseconds: 500), vsync: this, ); _borderRadiusAnimationController = AnimationController( duration: const Duration(milliseconds: 500), vsync: this, ); fabCurve = CurvedAnimation( parent: _fabAnimationController, curve: const Interval(0.5, 1.0, curve: Curves.fastOutSlowIn), ); borderRadiusCurve = CurvedAnimation( parent: _borderRadiusAnimationController, curve: const Interval(0.5, 1.0, curve: Curves.fastOutSlowIn), ); fabAnimation = Tween(begin: 0, end: 1).animate(fabCurve); borderRadiusAnimation = Tween( begin: 0, end: 1, ).animate(borderRadiusCurve); _hideBottomBarAnimationController = AnimationController( duration: const Duration(milliseconds: 200), vsync: this, ); Future.delayed( const Duration(milliseconds: 300), () => _fabAnimationController.forward(), ); Future.delayed( const Duration(milliseconds: 300), () => _borderRadiusAnimationController.forward(), ); } @override void dispose() { _fabAnimationController.dispose(); _borderRadiusAnimationController.dispose(); _hideBottomBarAnimationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return GlowingBottomNavBar( child: AnimatedBottomNavigationBar.builder( itemCount: _iconList.length, tabBuilder: (int index, bool isActive) { final color = isActive ? Colors.pinkAccent : Colors.grey[400]; return SizedBox( height: 56, child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ // 图标容器,带有动画效果 AnimatedContainer( duration: const Duration(milliseconds: 200), padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: isActive ? Colors.pinkAccent.withValues(alpha: 0.15) : Colors.transparent, borderRadius: BorderRadius.circular(8), border: isActive ? Border.all( color: Colors.pinkAccent.withValues(alpha: 0.3), width: 1, ) : null, ), child: AnimatedScale( scale: isActive ? 1.05 : 1.0, duration: const Duration(milliseconds: 200), child: Icon(_iconList[index], size: 20, color: color), ), ), const SizedBox(height: 2), // 标签文字,带有动画效果 AnimatedDefaultTextStyle( duration: const Duration(milliseconds: 200), style: TextStyle( color: color, fontSize: isActive ? 10 : 8, fontWeight: isActive ? FontWeight.w600 : FontWeight.w400, letterSpacing: isActive ? 0.2 : 0, ), child: Text(_labelList[index]), ), // 活跃指示器 AnimatedContainer( duration: const Duration(milliseconds: 200), margin: const EdgeInsets.only(top: 1), height: 2, width: isActive ? 12 : 0, decoration: BoxDecoration( color: Colors.pinkAccent, borderRadius: BorderRadius.circular(1), ), ), ], ), ); }, backgroundColor: Colors.black, activeIndex: widget.currentIndex, splashColor: Colors.pinkAccent.withValues(alpha: 0.3), notchAndCornersAnimation: borderRadiusAnimation, splashSpeedInMilliseconds: 300, notchSmoothness: NotchSmoothness.verySmoothEdge, gapLocation: GapLocation.center, gapWidth: 60, leftCornerRadius: 20, rightCornerRadius: 20, onTap: widget.onTap, hideAnimationController: _hideBottomBarAnimationController, shadow: BoxShadow( offset: const Offset(0, -3), blurRadius: 15, spreadRadius: 1, color: Colors.black.withValues(alpha: 0.4), ), ), ); } } class CustomFloatingActionButton extends StatefulWidget { final VoidCallback? onPressed; const CustomFloatingActionButton({super.key, this.onPressed}); @override State createState() => _CustomFloatingActionButtonState(); } class _CustomFloatingActionButtonState extends State with SingleTickerProviderStateMixin { late AnimationController _animationController; late Animation _scaleAnimation; late Animation _rotationAnimation; @override void initState() { super.initState(); _animationController = AnimationController( duration: const Duration(milliseconds: 200), vsync: this, ); _scaleAnimation = Tween(begin: 1.0, end: 0.95).animate( CurvedAnimation(parent: _animationController, curve: Curves.easeInOut), ); _rotationAnimation = Tween(begin: 0.0, end: 0.1).animate( CurvedAnimation(parent: _animationController, curve: Curves.easeInOut), ); } @override void dispose() { _animationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: _animationController, builder: (context, child) { return Transform.scale( scale: _scaleAnimation.value, child: Transform.rotate( angle: _rotationAnimation.value, child: Container( decoration: BoxDecoration( shape: BoxShape.circle, gradient: const LinearGradient( colors: [Colors.pinkAccent, Colors.purpleAccent], begin: Alignment.topLeft, end: Alignment.bottomRight, ), boxShadow: [ BoxShadow( color: Colors.pinkAccent.withValues(alpha: 0.4), blurRadius: 12, spreadRadius: 2, offset: const Offset(0, 4), ), ], ), child: FloatingActionButton( onPressed: () { _animationController.forward().then((_) { _animationController.reverse(); }); widget.onPressed?.call(); }, backgroundColor: Colors.transparent, elevation: 0, child: const Icon( Icons.palette_rounded, color: Colors.white, size: 28, ), ), ), ), ); }, ); } }