【问题标题】:How to change icon on TabItem on currentTab如何在 currentTab 上更改 TabItem 上的图标
【发布时间】:2021-02-03 05:49:43
【问题描述】:

我有一个 BottomNavigationBar,它可以在活动和非活动状态下完美地改变颜色,但我不想改变颜色,而是用 SVG 图像改变活动和非活动状态的图标。以下是我的代码:

class AppNavigation extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => AppState();
}

const assetHome = 'assets/home_off.svg';
const assetRedemptions = 'assets/redeemed_off.svg';
const assetProfile = 'assets/profile_off.svg';


const assetHome1 = 'assets/home_on.svg';
const assetRedemptions1 = 'assets/redeemed_on.svg';
const assetProfile1 = 'assets/profile_on.svg';


class AppState extends State<AppNavigation> {
 
  static int currentTab = 0;

 // list tabs here
  final List<TabItem> tabs = [
    TabItem(
      tabName: "Home",
      icon: Icons.home,
      page: MyDealApp(),
    ),
    TabItem(
      tabName: "Announcement",
      icon: Icons.announcement,
      page: MyRedemptionApp(),
    ),
    TabItem(
      tabName: "Notification",
      icon: Icons.notifications,
      page: MyProfileApp(),
    ),
  ];

  AppState() {
    tabs.asMap().forEach((index, details) {
      details.setIndex(index);
    });
  }

  void _selectTab(int index) {
    if (index == currentTab) {
      tabs[index].key.currentState.popUntil((route) => route.isFirst);
   
    } else {
      setState(() => currentTab = index);
      debugPrint("currentTabber:$currentTab");
    }
  }

  @override
  Widget build(BuildContext context) {
    // WillPopScope handle android back btn
    return WillPopScope(
      onWillPop: () async {
        final isFirstRouteInCurrentTab =
        !await tabs[currentTab].key.currentState.maybePop();
        if (isFirstRouteInCurrentTab) {
          // if not on the 'main' tab
          if (currentTab != 0) {
            // select 'main' tab
            _selectTab(0);
            // back button handled by app
            return false;
          }
        }
        return isFirstRouteInCurrentTab;
      },
      child: Scaffold(
        // indexed stack shows only one child
        body: IndexedStack(
          index: currentTab,
          children: tabs.map((e) => e.page).toList(),
        ),
        // Bottom navigation
        bottomNavigationBar: BottomNavigation(
          onSelectTab: _selectTab,
          tabs: tabs,
        ),
      ),
    );
  }
}

class TabItem {
  // you can customize what kind of information is needed
  // for each tab
  final String tabName;
  final IconData icon;
  final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
  int _index = 0;
  Widget _page;

  TabItem({
    @required this.tabName,
    @required this.icon,
    @required Widget page,
  }) {
    _page = page;
  }

  void setIndex(int i) {
    _index = i;
  }

  int getIndex() => _index;

  Widget get page {
    return Visibility(
      // only paint this page when currentTab is active
      visible: _index == AppState.currentTab,
      // important to preserve state while switching between tabs
      maintainState: true,
      child: Navigator(
        // key tracks state changes
        key: key,
        onGenerateRoute: (routeSettings) {
          return MaterialPageRoute(
            builder: (_) => _page,
          );
        },
      ),
    );
  }
}

class BottomNavigation extends StatelessWidget {
  BottomNavigation({
    this.onSelectTab,
    this.tabs,
  });

  final ValueChanged<int> onSelectTab;
  final List<TabItem> tabs;

  @override
  Widget build(BuildContext context) {
    return BottomNavigationBar(
      type: BottomNavigationBarType.fixed,
      items: tabs
          .map(
            (e) => _buildItem(
          index: e.getIndex(),
          icon: e.icon,
          tabName: e.tabName,
        ),
      )
          .toList(),
      onTap: (index) => onSelectTab(
        index,
      ),
    );
  }

  BottomNavigationBarItem _buildItem(
      {int index, IconData icon, String tabName}) {
    return BottomNavigationBarItem(
      icon: Icon(
        icon,
        color: _tabColor(index: index),
      ),
      title: Text(
        tabName,
        style: TextStyle(
          color: _tabColor(index: index),
          fontSize: 12,
        ),
      ),
    );
  }

  Color _tabColor({int index}) {
    return AppState.currentTab == index ? colorGreen : Colors.grey;
  }

 }

如您所见 _tabColor 在活动和非活动时从蓝色切换到灰色,但我想要一个带有上面声明的 SVG 图像的图标切换。 assetHome 用于MyDealApp(),当它处于活动状态时assetHome1,用于MyDealApp(),当它处于非活动状态时,assetRedemptions,用于MyRedemptionApp(),当它处于活动状态时,assetRedemptions1,用于MyRedemptionApp(),当它处于非活动状态时,最后是@ 987654335@ 用于MyProfileApp(),当它处于活动状态时,assetProfile1 用于MyProfileApp(),当它处于非活动状态时。

【问题讨论】:

    标签: flutter tabitem flutter-bottomnavigation


    【解决方案1】:

    您可以使用BottomNavigationBarItemactiveIconicon 参数。如果提供了activeIcon,则icon只会在未选中该项时显示。

     BottomNavigationBarItem _buildItem(
          {int index, IconData activeIcon, IconData inactiveIcon, String tabName}) {
        return BottomNavigationBarItem(
          activeIcon: Icon(
            activeIcon,
            color: _tabColor(index: index),
          ),
          icon: Icon(
            inactiveIcon,
            color: _tabColor(index: index),
          ),
          title: Text(
            tabName,
            style: TextStyle(
              color: _tabColor(index: index),
              fontSize: 12,
            ),
          ),
        );
      }
    

    【讨论】:

    • 但是有了这个,我将在所有底部导航栏上使用相同的图标
    • 我想为每个人设置一个不同的图标
    • 我认为您使用 _buildItem 和所有选项卡的相同参数。我已经更新了答案以澄清。 @mideveloper
    • 是的,但是有没有办法可以在活动和不活动时切换图标。我使用了您更新的代码,但仍然没有为我切换图标。
    猜你喜欢
    • 1970-01-01
    • 2019-09-06
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    • 2011-03-04
    • 1970-01-01
    相关资源
    最近更新 更多