MoodCanvas/lib/widgets/simple_bottom_nav_bar.dart
fengshengxiong 91b7eebbf2 接入TopON
2026-01-22 16:34:55 +08:00

191 lines
5.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:animated_bottom_navigation_bar/animated_bottom_navigation_bar.dart';
class SimpleBottomNavBar extends StatefulWidget {
final int currentIndex;
final Function(int) onTap;
const SimpleBottomNavBar({
super.key,
required this.currentIndex,
required this.onTap,
});
@override
State<SimpleBottomNavBar> createState() => _SimpleBottomNavBarState();
}
class _SimpleBottomNavBarState extends State<SimpleBottomNavBar>
with TickerProviderStateMixin {
late AnimationController _fabAnimationController;
late AnimationController _borderRadiusAnimationController;
late Animation<double> fabAnimation;
late Animation<double> borderRadiusAnimation;
late CurvedAnimation fabCurve;
late CurvedAnimation borderRadiusCurve;
late AnimationController _hideBottomBarAnimationController;
final List<IconData> _iconList = [
Icons.dashboard_rounded,
Icons.favorite_rounded,
Icons.wb_sunny_rounded,
Icons.settings_rounded,
];
@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<double>(begin: 0, end: 1).animate(fabCurve);
borderRadiusAnimation = Tween<double>(
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 AnimatedBottomNavigationBar(
icons: _iconList,
activeIndex: widget.currentIndex,
onTap: widget.onTap,
backgroundColor: Colors.black,
splashColor: Colors.pinkAccent.withValues(alpha: 0.3),
activeColor: Colors.pinkAccent,
inactiveColor: Colors.grey[400]!,
notchAndCornersAnimation: borderRadiusAnimation,
splashSpeedInMilliseconds: 300,
notchSmoothness: NotchSmoothness.verySmoothEdge,
gapLocation: GapLocation.center,
gapWidth: 60,
leftCornerRadius: 20,
rightCornerRadius: 20,
hideAnimationController: _hideBottomBarAnimationController,
shadow: BoxShadow(
offset: const Offset(0, -3),
blurRadius: 15,
spreadRadius: 1,
color: Colors.black.withValues(alpha: 0.4),
),
);
}
}
class SimpleFloatingActionButton extends StatefulWidget {
final VoidCallback? onPressed;
const SimpleFloatingActionButton({super.key, this.onPressed});
@override
State<SimpleFloatingActionButton> createState() =>
_SimpleFloatingActionButtonState();
}
class _SimpleFloatingActionButtonState extends State<SimpleFloatingActionButton>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _scaleAnimation;
@override
void initState() {
super.initState();
_animationController = AnimationController(
duration: const Duration(milliseconds: 200),
vsync: this,
);
_scaleAnimation = Tween<double>(begin: 1.0, end: 0.95).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: 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.messenger_rounded,
color: Colors.white,
size: 28,
),
),
),
);
},
);
}
}