I'm having trouble designing the bottom nav bar. How can I make the diagonal line from the corners wrap around the center button?
I tried to do it with some libraries and drawing but I was not successful. How can I design the diagonal lines that wrap around the center button to wrap under the center button?
class CustomNotchedShape extends NotchedShape {
const CustomNotchedShape();
@override
Path getOuterPath(Rect host, Rect? guest) {
if (guest == null || !host.overlaps(guest)) return Path()..addRect(host);
final double radius = 25;
Path path = Path();
path.moveTo(0, host.height);
path.lineTo(0, radius);
path.quadraticBezierTo(0, 0, radius, 0);
path.lineTo(host.width - radius, 0);
path.quadraticBezierTo(host.width, 0, host.width, radius);
path.lineTo(host.width, host.height);
path.lineTo(0, host.height);
final buttonPath = Path();
final centerX = guest.center.dx;
final buttonWidth = guest.width * 1.6;
final curveHeight = 15.0;
buttonPath.moveTo(centerX - buttonWidth / 2, host.height);
buttonPath.quadraticBezierTo(
centerX, host.height + curveHeight,
centerX + buttonWidth / 2, host.height
);
return Pathbine(PathOperation.difference, path, buttonPath);
}
}
@RoutePage()
class HomeStackPage extends StatelessWidget {
const HomeStackPage({super.key});
@override
Widget build(BuildContext context) {
return AutoTabsScaffold(
routes: const [
HomeRoute(),
SupportRoute(),
NewsStackRoute(),
ProfileRoute(),
],
extendBody: true,
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: Container(
height: 64,
width: 64,
child: FloatingActionButton(
elevation: 4,
backgroundColor: const Color(0xFF2E7D32),
shape: const CircleBorder(),
child: Stack(
clipBehavior: Clip.none,
children: [
const Icon(
Icons.shopping_bag_outlined,
color: Colors.white,
size: 30,
),
Positioned(
right: -4,
top: -4,
child: Container(
padding: const EdgeInsets.all(4),
decoration: const BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: const Text(
'0',
style: TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
onPressed: () {},
),
),
bottomNavigationBuilder: (context, tabsRouter) {
return Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, -3),
),
],
),
child: BottomAppBar(
elevation: 0,
notchMargin: 8,
shape: const CustomNotchedShape(),
color: Colors.white,
child: Container(
height: 60,
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildNavItem(
icon: Icons.home_outlined,
label: 'Anasayfa',
isSelected: tabsRouter.activeIndex == 0,
onTap: () => tabsRouter.setActiveIndex(0),
),
_buildNavItem(
icon: Icons.favorite_border,
label: 'Destek ol',
isSelected: tabsRouter.activeIndex == 1,
onTap: () => tabsRouter.setActiveIndex(1),
),
const SizedBox(width: 64),
_buildNavItem(
icon: Icons.campaign_outlined,
label: 'Haberler',
isSelected: tabsRouter.activeIndex == 2,
onTap: () => tabsRouter.setActiveIndex(2),
),
_buildNavItem(
icon: Icons.person_outline,
label: 'Profile',
isSelected: tabsRouter.activeIndex == 3,
onTap: () => tabsRouter.setActiveIndex(3),
),
],
),
),
),
);
},
);
}
Widget _buildNavItem({
required IconData icon,
required String label,
required bool isSelected,
required VoidCallback onTap,
}) {
return InkWell(
onTap: onTap,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
icon,
color: isSelected ? const Color(0xFF2E7D32) : Colors.grey,
size: 24,
),
const SizedBox(height: 4),
Text(
label,
style: TextStyle(
color: isSelected ? const Color(0xFF2E7D32) : Colors.grey,
fontSize: 12,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
),
),
],
),
);
}
}