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

Flutter:如何自定义NavigationBar样式以匹配Figma设计

问题:自定义NavigationBar指示器以匹配Figma设计

我需要实现与Figma设计稿一致的底部导航栏,目前已编写了NavigationBar代码,但最终呈现的导航栏效果与设计不符,请问是否可以修改指示器样式来匹配Figma设计(颜色可后续调整)。

我的实现代码

return Scaffold(
      bottomNavigationBar: NavigationBar(
        onDestinationSelected: (int index) {
          logDebug('selected index: $index');
          setState(() {
            selectedPageIndex = index;
          });
        },
        selectedIndex: selectedPageIndex,
        destinations: <NavigationDestination>[
          const NavigationDestination(
            selectedIcon: Icon(
              Icons.home,
              size: 37,
              color: primaryColor,
            ),
            icon: Icon(
              Icons.home_outlined,
              size: 37,
              color: primaryColor,
            ),
            label: 'Home',
          ),
          const NavigationDestination(
            selectedIcon: Icon(
              Icons.ev_station,
              size: 37,
              color: primaryColor,
            ),
            icon: Icon(
              Icons.ev_station_outlined,
              size: 37,
              color: primaryColor,
            ),
            label: 'someLable',
          ),
          NavigationDestination(
            selectedIcon: const Icon(Icons.car_repair),
            icon: Image.asset(
              'assets/images/car_repair.png',
              width: 40,
              color: primaryColor,
            ),
            label: 'Services',
          ),
          const NavigationDestination(
            selectedIcon: Icon(
              Icons.stars,
              size: 37,
              color: primaryColor,
            ),
            icon: Icon(
              Icons.stars_outlined,
              size: 37,
              color: primaryColor,
            ),
            label: 'Points',
          ),
          const NavigationDestination(
            selectedIcon: Icon(
              Icons.person_2,
              size: 37,
              color: primaryColor,
            ),
            icon: Icon(
              Icons.person_2_outlined,
              size: 37,
              color: primaryColor,
            ),
            label: 'Profile',
          ),
        ],
      ),
      body: SafeArea(
        child: Text("hellp"),
      ),
    );

设计稿与实际效果

设计稿效果

设计稿效果

实际呈现效果

实际效果


解决方案

1. 通过NavigationBarTheme修改指示器样式

Flutter的NavigationBar可以通过NavigationBarTheme调整指示器外观,包括形状、高度、颜色等,能部分贴近设计需求:

return Scaffold(
  bottomNavigationBar: NavigationBarTheme(
    data: NavigationBarThemeData(
      // 自定义指示器圆角矩形形状
      indicatorShape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(8),
      ),
      // 指示器底色
      indicatorColor: Colors.blue.withOpacity(0.2),
      // 调整指示器高度
      indicatorHeight: 4,
      // 选中状态下的文字样式
      labelTextStyle: MaterialStateProperty.all(
        TextStyle(
          fontWeight: FontWeight.bold,
          color: primaryColor,
        ),
      ),
    ),
    child: NavigationBar(
      // 保留原有NavigationBar配置
      onDestinationSelected: (int index) {
        logDebug('selected index: $index');
        setState(() {
          selectedPageIndex = index;
        });
      },
      selectedIndex: selectedPageIndex,
      destinations: <NavigationDestination>[
        // ... 原有destinations代码
      ],
    ),
  ),
  body: SafeArea(child: Text("hellp")),
);

2. 完全自定义底部导航栏(更灵活)

如果NavigationBarTheme的自定义程度不够,可自己实现底部导航栏,完全控制指示器的样式、位置和动画:

return Scaffold(
  bottomNavigationBar: Container(
    height: 70,
    decoration: BoxDecoration(
      color: Colors.white,
      boxShadow: [
        BoxShadow(
          color: Colors.grey.withOpacity(0.2),
          blurRadius: 10,
          offset: Offset(0, -2),
        ),
      ],
    ),
    child: Stack(
      children: [
        // 自定义底部指示器
        Positioned(
          left: selectedPageIndex * (MediaQuery.of(context).size.width / 5),
          bottom: 0,
          width: MediaQuery.of(context).size.width / 5,
          child: Container(
            height: 4,
            decoration: BoxDecoration(
              color: primaryColor,
              borderRadius: BorderRadius.vertical(top: Radius.circular(8)),
            ),
          ),
        ),
        // 导航项列表
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: List.generate(5, (index) {
            return GestureDetector(
              onTap: () {
                logDebug('selected index: $index');
                setState(() {
                  selectedPageIndex = index;
                });
              },
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  // 图标区域
                  if (index == 0)
                    (selectedPageIndex == index)
                        ? Icon(Icons.home, size: 37, color: primaryColor)
                        : Icon(Icons.home_outlined, size: 37, color: primaryColor)
                  else if (index == 1)
                    (selectedPageIndex == index)
                        ? Icon(Icons.ev_station, size: 37, color: primaryColor)
                        : Icon(Icons.ev_station_outlined, size: 37, color: primaryColor)
                  else if (index == 2)
                    (selectedPageIndex == index)
                        ? Icon(Icons.car_repair, color: primaryColor)
                        : Image.asset(
                            'assets/images/car_repair.png',
                            width: 40,
                            color: primaryColor,
                          )
                  else if (index == 3)
                    (selectedPageIndex == index)
                        ? Icon(Icons.stars, size: 37, color: primaryColor)
                        : Icon(Icons.stars_outlined, size: 37, color: primaryColor)
                  else
                    (selectedPageIndex == index)
                        ? Icon(Icons.person_2, size: 37, color: primaryColor)
                        : Icon(Icons.person_2_outlined, size: 37, color: primaryColor),
                  // 文字标签
                  Text(
                    index == 0 ? 'Home' : 
                    index == 1 ? 'someLable' : 
                    index == 2 ? 'Services' : 
                    index == 3 ? 'Points' : 'Profile',
                    style: TextStyle(
                      color: selectedPageIndex == index ? primaryColor : Colors.grey,
                      fontSize: 12,
                    ),
                  ),
                ],
              ),
            );
          }),
        ),
      ],
    ),
  ),
  body: SafeArea(child: Text("hellp")),
);

这种方式可以完全复刻Figma设计中的指示器样式,可根据需求调整容器的圆角、高度、颜色等参数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 00:20:29