Change Background Color of Active Button Navigation Bar Item in Cupertino Tab Bar(Flutter)

2k views Asked by At

I'm making an application wherein the active bottom navigation bar item needs to have a different background than the inactive ones. I tried wrapping it into activeicon header and leaving the label as null. But, I kept on having a line below that is not the same color as my background in activeicon. I tried placing it in a SizedBox or setting it to height: double.infinity but it didn't work. I need to use a Cupertino tab bar so that my nav bar would be persistent. I want to remove the line below the active item so it would look more seamless.

Here's the current state of my navbar: navbar

I hope you could give me a solution to this. It has been weeks of me trying to solve it.

Here's my code

class Nav extends StatelessWidget {
  const Nav({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return CupertinoTabScaffold(
      tabBar: CupertinoTabBar(
        backgroundColor: CupertinoTheme.of(context).primaryColor,
        activeColor: Colors.black,
        inactiveColor: Colors.white,
        iconSize: 25,
        items: <BottomNavigationBarItem>[
          _bottomNavigationBarItem(Icons.track_changes, "Track", context),
          _bottomNavigationBarItem(Icons.add_location_sharp, "Create", context),
          _bottomNavigationBarItem(Icons.map_rounded, "Travels", context),
          _bottomNavigationBarItem(Icons.settings, "Settings", context)
        ],
      ),
      tabBuilder: (context, index) {
        switch (index) {
          case 0:
            return CupertinoTabView(builder: (context) {
              return const CupertinoPageScaffold(
                child: TrackPage(),
              );
            });
          case 1:
            return CupertinoTabView(builder: (context) {
              return const CupertinoPageScaffold(
                child: CreatePage(),
              );
            });
          case 2:
            return CupertinoTabView(builder: (context) {
              return const CupertinoPageScaffold(
                child: TravelsPage(),
              );
            });
          case 3:
            return CupertinoTabView(builder: (context) {
              return const CupertinoPageScaffold(
                child: SettingsPage(),
              );
            });
          default:
            return CupertinoTabView(builder: (context) {
              return const CupertinoPageScaffold(
                child: CreatePage(),
              );
            });
        }
      },
    );
  }
}

BottomNavigationBarItem _bottomNavigationBarItem(
    IconData icon, String label, BuildContext context) {
  return BottomNavigationBarItem(
    activeIcon: Container(
      width: double.infinity,
      height: double.infinity,
      color: CupertinoTheme.of(context).primaryContrastingColor,
      padding: const EdgeInsets.only(top: 6.0),
      child: Column(
        children: [
          Expanded(
            child: Icon(icon, color: Colors.black),
          ),
          const SizedBox(height:10),
          Expanded(
            child:
              Text(label, style: const TextStyle(color: Colors.black, fontSize: 12))),
        ],
      )),
    icon: Padding(
      padding: const EdgeInsets.only(top: 6.0),
      child: Column(
        children: [
          Expanded(
            child: Icon(icon),
          ),
          const SizedBox(height:10),
          Expanded(
            child:
              Text(label, style: const TextStyle( fontSize: 12))),
        ],
      ),
    ),
  );
}

2

There are 2 answers

1
Ravindra S. Patil On

I think this is not possible to change background color of selected BottomNavigationBar

refer BottomNavigationBar here ,change Color on your need

try below code on Dartpad here

try this answer hope its helpful to you.

import 'package:flutter/material.dart';

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

/// This is the main application widget.
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      title: _title,
      home: MyStatefulWidget(),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  const MyStatefulWidget({Key? key}) : super(key: key);

  @override
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  final selectedItemColor = Colors.white;
  final unSelectedItemColor = Colors.white30;
  final selectedBackGroundColor = Colors.green;
  final unselectedBackGroundColor = Colors.blue;
  int selectedIndex = 0;
  static const TextStyle optionStyle =
      TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
  static const List<Widget> _widgetOptions = <Widget>[
    Text(
      'Index 0: Track',
      style: optionStyle,
    ),
    Text(
      'Index 1: Create',
      style: optionStyle,
    ),
    Text(
      'Index 2: Travel',
      style: optionStyle,
    ),
    Text(
      'Index 3: Setting',
      style: optionStyle,
    ),
  ];
  Color _getBgColor(int index) => selectedIndex == index
      ? selectedBackGroundColor
      : unselectedBackGroundColor;

  Color _getItemColor(int index) =>
      selectedIndex == index ? selectedItemColor : unSelectedItemColor;

  void _onItemTapped(int index) {
    setState(() {
      selectedIndex = index;
    });
  }

  Widget _buildIcon(IconData iconData, String text, int index) => Container(
        width: double.infinity,
        height: kBottomNavigationBarHeight,
        child: Material(
          color: _getBgColor(index),
          child: InkWell(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Icon(iconData),
                Text(
                  text,
                  style: TextStyle(
                    fontSize: 12,
                    color: _getItemColor(index),
                  ),
                ),
              ],
            ),
            onTap: () => _onItemTapped(index),
          ),
        ),
      );
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('BottomNavigationBar Sample'),
      ),
      body: Center(
        child: _widgetOptions.elementAt(selectedIndex),
      ),
      bottomNavigationBar: BottomNavigationBar(
        selectedFontSize: 0,
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: _buildIcon(
              Icons.track_changes,
              'Track',
              0,
            ),
            title: SizedBox(),
          ),
          BottomNavigationBarItem(
            icon: _buildIcon(
              Icons.add_location_sharp,
              'Create',
              1,
            ),
            title: SizedBox(),
          ),
          BottomNavigationBarItem(
            icon: _buildIcon(
              Icons.map_rounded,
              'Travel',
              2,
            ),
            title: SizedBox(),
          ),
          BottomNavigationBarItem(
            icon: _buildIcon(
              Icons.settings,
              'Setting',
              3,
            ),
            title: SizedBox(),
          ),
        ],
        currentIndex: selectedIndex,
        selectedItemColor: selectedItemColor,
        unselectedItemColor: unSelectedItemColor,
      ),
    );
  }
}

Your result screen-> image

0
Md. Yeasin Sheikh On

Unable to find any parameter to handle this situation, seems like it is hard-coded on source-code. You can use Transform to manipulate the bottomNavigationBar. also you can create custom bottomNavigationBar using Row,Column and using active index for styling.

class Nav extends StatelessWidget {
  const Nav({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Transform.translate( //<- this
      offset: const Offset(0, 4),
      child: CupertinoTabScaffold(...