You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在BottomNavigationBarItem中绝对定位带数值的徽章?

实现带数值徽章的BottomNavigationBarItem

我看你已经用Stack来尝试实现徽章了,这个思路完全没问题!我来帮你补全并优化这个实现,让徽章看起来更美观,还能支持动态更新数值:

完整示例代码

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Bottom Nav with Badge',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const BottomNavWithBadge(),
    );
  }
}

class BottomNavWithBadge extends StatefulWidget {
  const BottomNavWithBadge({super.key});

  @override
  State<BottomNavWithBadge> createState() => _BottomNavWithBadgeState();
}

class _BottomNavWithBadgeState extends State<BottomNavWithBadge> {
  int _selectedIndex = 0;
  // 模拟各导航项的徽章数值
  final Map<int, int> _badgeCounts = {0: 3, 1: 0, 2: 12};

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
      // 点击后可以清空对应徽章数值,模拟已读效果
      _badgeCounts[index] = 0;
    });
  }

  // 封装带徽章的图标组件,复用更方便
  Widget _buildBadgedIcon(IconData icon, int count) {
    return Stack(
      clipBehavior: Clip.none, // 允许徽章超出Stack范围显示,避免被截断
      children: [
        Icon(icon, size: 28),
        if (count > 0) // 数值为0时自动隐藏徽章,避免空占位
          Positioned(
            top: -4,
            right: -4,
            child: Container(
              padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
              decoration: const BoxDecoration(
                color: Colors.red,
                borderRadius: BorderRadius.all(Radius.circular(12)),
              ),
              constraints: const BoxConstraints(
                minWidth: 20,
                minHeight: 20,
              ),
              child: Text(
                '$count',
                style: const TextStyle(
                  color: Colors.white,
                  fontSize: 12,
                  fontWeight: FontWeight.bold,
                ),
                textAlign: TextAlign.center,
              ),
            ),
          ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Bottom Nav Badge Demo')),
      body: const Center(child: Text('Selected Page Content')),
      bottomNavigationBar: BottomNavigationBar(
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: _buildBadgedIcon(Icons.home, _badgeCounts[0]!),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: _buildBadgedIcon(Icons.notifications, _badgeCounts[1]!),
            label: 'Notifications',
          ),
          BottomNavigationBarItem(
            icon: _buildBadgedIcon(Icons.shopping_cart, _badgeCounts[2]!),
            label: 'Cart',
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.blue,
        unselectedItemColor: Colors.grey,
        type: BottomNavigationBarType.fixed, // 确保多导航项时不会挤在一起
        onTap: _onItemTapped,
      ),
    );
  }
}

关键细节说明

  • Stack布局:用Stack把图标和徽章叠加,clipBehavior: Clip.none是关键,能让徽章超出图标范围显示不会被截断
  • 徽章定位:通过Positioned的top和right参数,把徽章精准放在图标的右上角,数值可以根据自己的视觉需求调整
  • 动态显示逻辑:加了if (count > 0)判断,当数值为0时自动隐藏徽章,避免空徽章影响界面美观
  • 样式优化:给徽章设置了圆角红色背景、白色小号粗体字,同时限制最小宽高,保证单个数字和多位数都能正常显示
  • 复用性:把带徽章的图标封装成_buildBadgedIcon方法,多个导航项可以直接调用,减少重复代码

你可以根据自己的需求调整徽章的颜色、大小、位置,或者把_badgeCounts改成从后端接口获取的动态数据,实现实时更新徽章数值的效果~

内容的提问来源于stack exchange,提问作者David Airapetyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:24:28