Q:

Bottomnavigationbar item icon in flutter app

I want to change the icon of an active bottomnavigationbar item, ie if the item is selected the icon is filled and if it’s unselected it shows the outline.  

A:

Check the code below with explanations:
import 'package:flutter/material.dart';

class MainScreen extends StatefulWidget {

  @override
  _MainScreenState createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen>
    with SingleTickerProviderStateMixin {
  // we need this to switch between tabs
  TabController _tabController;
  // here we remember the current tab, by default is the first one (index 0)
  int _currentTabIndex = 0;

  @override
  void initState() {
    super.initState();
    // init the TabController
    _tabController = TabController(vsync: this, length: _Tab.values.length);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0.0,
        backgroundColor: Colors.white,
        title: Text(_getTitleForCurrentTab(_Tab.values[_currentTabIndex])), // set the title in the AppBar
      ),
      body: TabBarView(
        controller: _tabController, // we set our instantiated TabController as the controller
        children: <Widget>[
          // here we put the screen widgets corresponding to each tab
          // the order must correspond to the order given below in bottomNavigationBar
          Tab1Widget(), // these are your custom widgets for each tab you have
          Tab2Widget(),
          Tab3Widget(),
        ],
      ),
      bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        onTap: (int index) {
          // when a tab icon was tapped we just change the current index of the tab with the new one
          // this set state call will re-render the screen and will set new the tab as active
          setState(() {
            _currentTabIndex = index;
          });

          // also we want to change the screen content not just the active tab icon
          // so we use the TabController to go to another tab giving it the index of the tab which was just clicked
          _tabController.animateTo(index);
        },
        // here we render all the icons we want in the BottomNavigationBar
        // we get all the values of the _Tab enum and for each one we render a BottomNavigationBarItem
        items: _Tab.values
            .map((_Tab tab) => BottomNavigationBarItem(
                title: Text(_getTitleForCurrentTab(tab)), // set the title of the tab icon
                icon: Image.asset(
                  _getAssetForTab(tab),
                  width: 24.0,
                  height: 24.0,
                ))) // set the icon of the tab
            .toList(),
      ),
    );
  }

  /// Get the asset icon for the given tab
  String _getAssetForTab(_Tab tab) {
    // check if the given tab parameter is the current active tab
    final active = tab == _Tab.values[_currentTabIndex];

    // now given the tab param get its icon considering the fact that if it is active or not
    if (tab == _Tab. TAB1) {
      return active ? ' assets/tab1_active.png' : 'assets/tab1.png';
    } else if (tab == _Tab. TAB2) {
      return active ? ' assets/tab2_active.png' : 'assets/tab2.png';
    }
    return active ? ' assets/tab3_active.png' : 'assets/tab3.png';
  }

  /// Get the title for the current selected tab
  String _getTitleForCurrentTab(_Tab tab) {
    if (tab == _Tab. TAB1) {
      return 'tab1_title';
    } else if (tab == _Tab. TAB2) {
      return 'tab2_title';
    }
    return 'tab3_title';
  }
}

// Just an enum with all the tabs we want to have
enum _Tab {
  TAB1,
  TAB2,
  TAB3,
}

