flutter - A custom bottom navigation bar design - Stack Overflow

admin2025-04-22  3

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,
            ),
          ),
        ],
      ),
    );
  }
}
转载请注明原文地址:http://anycun.com/QandA/1745303710a90615.html