animated_navbar 0.0.1
animated_navbar: ^0.0.1 copied to clipboard
Introducing the Animated Notched Navbar—a stylish, functional Flutter masterpiece.
example/main.dart
import 'dart:math' as math;
import 'package:flutter/material.dart';
void main() => runApp(const MyHome());
// Main application widget
class MyHome extends StatelessWidget {
const MyHome({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: NavPackage(),
);
}
}
// Widget representing the navigation bar
class NavPackage extends StatefulWidget {
const NavPackage({super.key});
@override
State<NavPackage> createState() => _NavPackageState();
}
class _NavPackageState extends State<NavPackage> with TickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _animation;
bool isHovered = false;
@override
void initState() {
super.initState();
// Animation setup for the rotating FloatingActionButton
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 800),
);
_animation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: Curves.easeInOut,
),
);
}
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
return Scaffold(
body: Stack(
children: [
Positioned(
bottom: 0,
left: 0,
child: SizedBox(
width: size.width,
height: 80,
child: Stack(
children: [
// CustomPaint to draw the decorative shape
CustomPaint(
size: Size(size.width, 80),
painter: MyPainter(),
),
Center(
heightFactor: 0.6,
child: MouseRegion(
// Handling mouse hover events for the FloatingActionButton
onEnter: (_) {
_animationController.forward();
setState(() {
isHovered = true;
});
},
onExit: (_) {
_animationController.reverse();
setState(() {
isHovered = false;
});
},
child: AnimatedBuilder(
// Applying rotation animation to the FloatingActionButton
animation: _animation,
builder: (context, child) {
return Transform.rotate(
angle: isHovered ? _animation.value * 0.80 : 0.0,
child: FloatingActionButton(
onPressed: () {
_animationController.forward();
},
backgroundColor: isHovered
? Colors.orange.withOpacity(_animation.value)
: Colors.yellow,
child: const Icon(Icons.add),
),
);
},
),
),
),
SizedBox(
width: size.width,
height: 80,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// Custom IconButton with hover effect
HoverIconButton(
onPressed: () {},
icon: const Icon(Icons.home),
animationController: _animationController,
),
HoverIconButton(
onPressed: () {},
icon: const Icon(Icons.book_online),
animationController: _animationController,
),
Container(
width: size.width * 0.20,
),
HoverIconButton(
onPressed: () {},
icon: const Icon(Icons.carpenter),
animationController: _animationController,
),
HoverIconButton(
onPressed: () {},
icon: const Icon(Icons.shop),
animationController: _animationController,
),
],
),
),
],
),
),
),
],
),
);
}
}
// Custom IconButton with hover effect
class HoverIconButton extends StatefulWidget {
final VoidCallback onPressed;
final Icon icon;
final AnimationController animationController;
const HoverIconButton({
super.key,
required this.onPressed,
required this.icon,
required this.animationController,
});
@override
// ignore: library_private_types_in_public_api
_HoverIconButtonState createState() => _HoverIconButtonState();
}
class _HoverIconButtonState extends State<HoverIconButton> {
bool isHovered = false;
@override
Widget build(BuildContext context) {
return MouseRegion(
// Handling mouse hover events for the IconButton
onEnter: (_) {
widget.animationController.forward();
setState(() {
isHovered = true;
});
},
onExit: (_) {
widget.animationController.reverse();
setState(() {
isHovered = false;
});
},
child: IconButton(
onPressed: widget.onPressed,
icon: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: isHovered
? Icon(
widget.icon.icon,
size: 50,
color: const Color.fromARGB(255, 9, 9, 9),
)
: Icon(
widget.icon.icon,
size: 24,
),
),
),
);
}
}
// Custom painter for drawing a decorative shape with a dripping effect
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = Colors.yellow
..style = PaintingStyle.fill;
Path path = Path()..moveTo(0, 20);
path.quadraticBezierTo(size.width * 0.20, 0, size.width * 0.40, 0);
path.quadraticBezierTo(size.width * 0.40, 10, size.width * 0.40, 20);
path.arcToPoint(Offset(size.width * 0.60, 20),
radius: const Radius.circular(10.0), clockwise: false);
path.quadraticBezierTo(size.width * 0.60, 0, size.width * 0.60, 0);
path.quadraticBezierTo(size.width * 0.80, 0, size.width, 20);
path.lineTo(size.width, size.height);
path.lineTo(0, size.height);
path.close();
canvas.drawShadow(path, Colors.yellow, 5, true);
canvas.drawPath(path, paint);
// Draw dripping effect
if (path.contains(Offset(size.width * 0.50, 20))) {
double dripHeight = 60;
double dripWidth = 10;
double gap = 10;
for (double i = 0; i < dripHeight; i += gap) {
double x = size.width * 0.50 - dripWidth / 2;
double y = 20 + i;
double endY = math.min(y + gap, size.height - 80);
canvas.drawLine(
Offset(x, y),
Offset(x, endY),
paint..color = Colors.orange.withOpacity(0.5),
);
}
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return false;
}
}