Flutter BottomNavigationBarItem accepts only Icon and no other widgets? - flutter

In our Flutter Cupertino project, we need to show a badge on one of the bottom bar icons. How many articles are already in the shopping cart to be precise.
I've tried different widgets and solutions provided here, but the BottomNavigationBarItem accepts only icon: Icon(..) and nothing else. If I, for example, put icon: Stack(..) instead of the icon: Icon(..), there are error messages shown, for example
"Invalid const value..."
Here is some sample code:
class CupertinoStoreHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
tabBar: CupertinoTabBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.home),
title: Text('Kühlschrank'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.profile_circled),
title: Text('Konto'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.shopping_cart),
title: Text('Warenkorb'),
),
],
),
So if I can not put anything instead of the Icon(..). No other widget, no Stack(..).
Why? How can I put some other widget, like for example Badge(..):
badges: ^1.0.2
import 'package:badges/badges.dart';
This question is different from the possible duplicate, because I already tried the solution posted there and still can not use Stack(..) but only Icon(..).

I tried reproducing the problem, but it does work after changing a few things. First of all the icon property accepts a Widget and therefore not only an Icon, so this is not the problem.
I did notice however, in items: const <BottomNavigationBarItem>[ you should remove the const keyword as it is not necessary and also not constant.
And lastly, you need to add a tab builder to CupertinoTabScaffold this basically returns what's displayed above the bottom navigation bar.
Your final code then looks like this:
return CupertinoTabScaffold(
tabBuilder: (BuildContext context, int i) {
return CupertinoActivityIndicator();
},
tabBar: CupertinoTabBar(
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Badge(
badgeContent: Text('3'),
child: Icon(Icons.settings),
),
title: Text('Kühlschrank'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.profile_circled),
title: Text('Konto'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.shopping_cart),
title: Text('Warenkorb'),
),
],
),
);

Related

Unformatted BottomNavigationBar Flutter

I created a simple bottom navigation bar, (my code below)...
bottomNavigationBar: BottomNavigationBar(
backgroundColor: COLOR_WHITE,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.account_circle_rounded),
label: 'Profile',
),
BottomNavigationBarItem(
label: 'something', icon: Icon(Icons.star)),
],
)
...but then I really wanted to click on the icons, so I tried adding an Icon Button for its onPressed() method.
bottomNavigationBar: BottomNavigationBar(
backgroundColor: COLOR_WHITE,
items: [
BottomNavigationBarItem(
icon: IconButton(
icon: const Icon(Icons.account_circle_rounded),
onPressed: () {
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context) => ProfileScreen(userID :widget.userID)),
);
},
),
label: "Profile"
),
BottomNavigationBarItem(
label: 'something', icon: Icon(Icons.star)),
],
),
It gets all ugly, and I wanted the paddings and size all around to remain the same, but since I didn't add code to change those features, I don't get why it happened in the first place. Can someone help me solve it? Thanks!!
BottomNavigationBar has an onTap method you can use to trigger your callbacks so you don't need an IconButton. onTap gives you the index of the item tapped so you can map it to the appropriate page. You can also update the currentIndex property on the BottomNavigatorBar to highlight the appropriate item.
See this documentation for BottomNavigationBar for a good example: https://api.flutter.dev/flutter/material/BottomNavigationBar-class.html
the mistake you have made was in the first BottomNavigationBarItem you have IconButton Widget and in second Icon widget... both having different styles by default(flutter developers gave default values for padding size etc)... so below code will work. i implemented locally and checked as well..
BottomNavigationBar(
backgroundColor: Colors.white,
items: [
BottomNavigationBarItem(
icon: IconButton(
icon: const Icon(Icons.account_circle_rounded),
onPressed: () {
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context) =>
ProfileScreen(userID:widget.userID)),
);
},[enter image description here][1]
),
label: "Profile"
),
BottomNavigationBarItem(
label: 'something', icon: IconButton(
icon: const Icon(Icons.star),
onPressed: () {
},
),),
],
)
enter image description here

How to define content and code for a button icon

I have just started programming with Flutter and Dart
And I wanted to know how to set the code and content for a tab or button
For example, I put a button icon in the bottom navigator and what code and method is needed so that after clicking on that button, a new page will open one by one and the operation will be performed.
Thanks.
For bottom navigation bar you can use like this:
`
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('BottomNavigationBar Sample'),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
backgroundColor: Colors.red,
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Business',
backgroundColor: Colors.green,
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'School',
backgroundColor: Colors.purple,
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'Settings',
backgroundColor: Colors.pink,
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
}
`
You need to set onTap() for actions when you press the button and setState() to update the state of the widget.
All buttons (TextButton, ElevatedButton ect) will be having onTap() property, you can call a method inside onTap().
For more details visit this: https://flutter.dev/docs/development/ui/widgets/material#Buttons
This is a very specific use case and has a different solution to what you would usually do with buttons.
The documentation for the BottomNavigationBar() shows a few code examples. You can copy paste that and modify it to suit your need. What they basically do is add BottomNavigationBar() items and add an onChanged/onTap method which you would use to change the page.
For buttons in general, they would have an onPressed parameter where you can pass a function or an anonymous function (e.g. () {your code here}). Flutter provides you with a few default buttons such as ElevatedButton() and TextButton() which you can read more about here (https://api.flutter.dev/flutter/material/ElevatedButton-class.html) and here (https://api.flutter.dev/flutter/material/TextButton-class.html). They have parameters which allow you to tweak them. This is where you can run functions when they are pressed.
If you want to make a non-button widget clickable you can use a GestureDetector() which you can read more about here (https://api.flutter.dev/flutter/widgets/GestureDetector-class.html). It is also has an onTap similar to the buttons but also has much more options such as long, double, triple, etc. taps as well as gestures like swipes.
It all comes down to getting used to all those different widgets and you will get familiar with them through practice.

Flutter: how to show a badge in a CupertinoTabBar and update the value based on user input

I have a CupertinoApp with a CupertinoTabScaffold, a CupertinoTabBar and a series of BottomNavigationBarItem(s). I managed to add a badge in one of the BottomNavigationBarItem (the basket tab). See the picture below as well as my code
class _HomeScreenState extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
tabBar: CupertinoTabBar(
backgroundColor: kColorPrimaryLight,
items: [
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.search),
title: Text('Discover'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.person_solid),
title: Text('Account'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.book_solid),
title: Text('Stories'),
),
BottomNavigationBarItem(
icon: Badge(
badgeContent: Text(
appData.basketList.length.toString(),
style: kDescriptionTextStyle,
),
child: Icon(CupertinoIcons.shopping_cart)),
title: Text('Basket'),
),
],
),
Now I would like to update that badge text based on an event which get triggered in one of the the other tab. I am storing the value of the badge in a singletons (appData.basketList) and this information is available to all my screens. Every time I trigger that event then the appData.basketList.length.toString() changes but my badge does not change. It only change if I hot reload... so here is my question: how can I update the text of my badge?
Thanks !

Error when loading an image from the assets

I am trying to use a PNG file as an icon image.
I have an assets folder in the root of my project.
The file's path is assets/icons/Dumbbell.png.
I loaded my assets in the pubspec file:
flutter:
uses-material-design: true
assets:
- assets/icons/
And in a Stateful widget's state I'm trying to use it:
#override
Widget build(BuildContext context) {
return Scaffold(
...
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
title: Text('Workout'),
icon: Image.asset(
'assets/icons/Dumbbell.png',
),
),
],
),
);
}
I just can't make it work!
EDIT: I removed the const keyword and added another BottomNavigationBarItem and now everything is working perfectly!
To fix your issue, just remove the const keyword because your icon is not constant and also you need at least two BottomNavigationBarItem widgets to make it work:
items: [
BottomNavigationBarItem(
title: Text('Workout'),
icon: Image.asset(
'assets/icons/Dumbbell.png',
),
),
BottomNavigationBarItem(
title: Text('Another item'),
icon: Image.asset(
'assets/icons/Dumbbell.png',
),
),
],
More info here: https://api.flutter.dev/flutter/material/BottomNavigationBar-class.html
try this..
use ImageIcon class instead of Image.asset
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: ImageIcon(AssetImage("assets/mascot.png")),
title: Text("workout"),
),
],
),
try again with this demo
Image(image: AssetImage('assets/images/intro_0.jpg'),fit: BoxFit.fitWidth,)
diegoveloper's words is right. and BottomNavigationBar need two more items.
those code worked:
bottomNavigationBar:BottomNavigationBar(
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
title: Text('Workout'),
icon: Image(image: AssetImage('assets/images/intro_0.jpg'),fit: BoxFit.fitWidth,),
),
BottomNavigationBarItem(
title: Text('Workout'),
icon: Image(image: AssetImage('assets/images/intro_0.jpg'),fit: BoxFit.fitWidth,),
),
],
),

Changing the Bottom Navigation Bar when switching between screens in the body of a Scaffold

HomeScreen() function call the Home screen of App.
How I Can route/move to "Team", "Add", etcetera page without BottomNavigationBar and AppBar.
I want show another page and back button, with new Bottom Navigation Bar.
I have this on my Flutter Project:
class APPMain extends StatefulWidget {
#override
_APPMainState createState() => _APPMainState();
}
class _APPMainState extends State<APPMain> {
int _currentIndex = 0;
_onTapped(int index) {
setState(() {
_currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
List<Widget> screens = [
HomeScreen(),
Center(child: Text("Team")),
Center(child: Text("Add")),
Center(child: Text("Search")),
Center(child: Text("Settings")),
];
return Scaffold(
appBar: AppBar(
backgroundColor: Color(0xffffffff),
iconTheme: IconThemeData(color: Colors.grey),
title: Text("Test App", style: TextStyle(color: Colors.grey),),
actions: <Widget>[
IconButton(
icon: Icon(Icons.account_circle),
onPressed: (){},
),
],
),
body: Container(
color: Color(0xfff4f4f4),
child: Center(
child: screens[_currentIndex],
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
type: BottomNavigationBarType.fixed,
fixedColor: Colors.red,
onTap: _onTapped,
items: [
BottomNavigationBarItem(
title: Text('Home'), icon: Icon(Icons.home)),
BottomNavigationBarItem(
title: Text('Team'), icon: Icon(Icons.group)),
BottomNavigationBarItem(
title: Text('Add'), icon: Icon(Icons.add)),
BottomNavigationBarItem(
title: Text('Search'), icon: Icon(Icons.search)),
BottomNavigationBarItem(
title: Text('Settings'), icon: Icon(Icons.settings)),
]),
);
}
}
Thank you so much for help.
This is almost certainly a duplicate but I wasn't able to find a question asking something similar with a quick search so I'll answer anyways.
The answer is actually quite simple, but requires understanding a bit more about how to write flutter applications - you should be using a Navigator or the navigator built right into MaterialApp or WidgetApp rather than making your own navigation. The simplest way is to use MaterialApp's routes property and pass in a map with each of your pages. Then when you want to switch pages, you simply use Navigator.pushNamed(context, <name>) from wherever you want to switch the page (i.e. a button).
The part that can be slightly confusing when you come from other frameworks is that rather than having one Scaffold and switching the body of it, the entire page should switch and each page should have a Scaffold.
Here's an example in the documentation showing how to navigate between pages.
For the record, although it's a bad idea you could make it work with your original code as well - all you'd have to do is build a different BottomNavigationBar with different options depending on what _currentIndex is set to. But I don't recommend that. With what I've suggested you also get animations between pages, back button functionality, you can hook up analytics to track page usage, and a bunch more things that flutter provides as part of navigation.