Title Only On Selected Bottom Navigation Bar - flutter

I am trying to create an effect on the Bottom Navigation Bar such as that of Google Drive. I want the title of the item only to be displayed, on the selected item, and the others to only display the icons.
Also, this bottom bar becomes somewhat transparent, so you can barely see what's under it. Is this possible to do in flutter? I know it is not possible on the main app bar, since there is an issue talking about it here
image for reference

Hide Title of Unselected BottomNavigationBarItem
You just need to set the show unselected labels property of the bottom navigation bar to false
showUnselectedLabels: false,
Transparent BottomNavigation bar
The Scaffold provides placeholders for both Appbar and BottomNavigation bars. This is how they are placed.
The problem here is that the body does not overlap the Appbar or the BottomNavigation bar, and thus even if you give transparent background it would appear to do nothing.
A workaround would be to put the Body, AppBar and BottomNavigationBar inside a stack and position the AppBar and BottomNavigationBar appropriately.
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Container(
color: Colors.green, // Content of body here
),
Positioned(
left: 0,
right: 0,
top: 0,
child: AppBar(
elevation: 0,
backgroundColor: Colors.indigo.withAlpha(80),
title: Text('Some Text'),
),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: BottomNavigationBar(
elevation: 0,
showUnselectedLabels: false,
backgroundColor: Colors.red.withAlpha(80),
items: [
BottomNavigationBarItem(
title: Text('A'),
icon: Icon(Icons.add),
),
BottomNavigationBarItem(
title: Text('B'),
icon: Icon(Icons.remove),
),
],
),
),
],
),
);
}
}

U should use this code :
bottomNavigationBar: BottomNavigationBar(
//use both properties
type: BottomNavigationBarType.fixed,
showUnselectedLabels: true,
//-----------
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.icon1),
label:'item 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.icon2),
label: 'item 2',
),
],
)

Related

Flutter - How to position snackbar above system navigation bar

I have a transparent system navigation bar in my application.
Getx snack bar is used by the app to throw errors and success messages. What I'm stuck with is that anytime the app throws a snack bar, the snack bar appears and disappears through the transparent navigation bar (i can see the snack bar move through the navigation bar). Is there any way to have the snack bar appear above the navigation bar? How can I position the snack bar above the system navigation bar?
You may want to look into SnackBarBehavior enum which allows one to change the position. If you are using a third party library then you may want to try putting the behavior into an extension method. Alternative ideas exist on this SO Question that may apply in your use case although not an exact duplicate.
The SnackbarBehavior enum states:
Defines where a SnackBar should appear within a Scaffold and how its location should be adjusted when the scaffold also includes a FloatingActionButton or a BottomNavigationBar.
Other ideas include using a position widget with a Stack widget to gain precise control. Add a MediaQuery or other fractional widgets to allow for multiple screen sizes.
I suggest you to use SnackBar Widget that developed by flutter team instead of Getx snackbar. It basically appears above of navigation bar here an basic example;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('BottomNavigationBar Sample'),
),
body: Center(
child: ElevatedButton(
child: const Text('Show Snackbar'),
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('Awesome Snackbar!'),
action: SnackBarAction(
label: 'Action',
onPressed: () {
// Code to execute.
},
),
),
);
},
),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Business',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'School',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
static GetSnackBar SuccessSnackBar({String title = 'Success', String message}) {
Get.log("[$title] $message");
return GetSnackBar(
titleText: Text(title.tr, style: Get.textTheme.headline6.merge(TextStyle(color: Get.theme.primaryColor))),
messageText: Text(message, style: Get.textTheme.caption.merge(TextStyle(color: Get.theme.primaryColor))),
snackPosition: SnackPosition.BOTTOM,
margin: EdgeInsets.all(20),
backgroundColor: Colors.green,
icon: Icon(Icons.check_circle_outline, size: 32, color: Get.theme.primaryColor),
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 18),
borderRadius: 8,
dismissDirection: DismissDirection.horizontal,
duration: Duration(seconds: 5),
);
}
Used like this in my app. Worked fine.
Get.snackbar(
"Bruh",
"Your quantity have to at least one",
colorText: Colors.black,
backgroundColor: Palette.yellowColor,
);
In my case, this is my return to show snackbar for error message, the snackbar appear on top below the appbar
In the getx snackbar there are a snackPosition: attribute
You can use that to display yours

Flutter: Persistent BottomAppBar and BottomNavigationBar

I am new to flutter, and I am building an app that has BottomAppBar which takes the property bottomNavigationBar: of Scaffold() for my home_screen, because I needed it to be at the bottom of the screen and persistent throughout the pages, and I also need a BottomNavigationBar to be persistent also at the top of BottomAppBar, but I can't make that happen because BottomAppBar already takes the bottomNavigationBar: property.
How can I make my BottomNavigationBar persistent alongside my BottomAppBar?
Note: I am using PageView() to scroll through my pages and it will be controlled by the BottomNavigationBar
Edit: attached here is the UI that I am trying to achieve
code snippet:
import 'package:flutter/material.dart';
//screens
import 'package:timewise_flutter/screens/calendar_screen.dart';
import 'package:timewise_flutter/screens/covey_quadrants_screen.dart';
import 'package:timewise_flutter/screens/kanban_screen.dart';
import 'package:timewise_flutter/screens/todo_list_screen.dart';
class OverviewScreen extends StatefulWidget {
static const String id = 'overview_screen';
//const OverviewScreen({Key? key}) : super(key: key);
#override
_OverviewScreenState createState() => _OverviewScreenState();
}
class _OverviewScreenState extends State<OverviewScreen> {
PageController _pageController = PageController(initialPage: 2);
int _bottomNavBarCurrentIndex = 2;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
bottomNavigationBar: SafeArea(
child: BottomAppBar(
elevation: 16.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
tooltip: 'Menu',
icon: Icon(Icons.menu_rounded),
onPressed: () {
print('menu icon pressed!');
//TODO: show bottom modal bottom sheet
},
),
IconButton(
tooltip: 'Pomodoro Timer',
icon: Icon(Icons.hourglass_empty_rounded),
onPressed: () {
print('pomo icon pressed!');
//TODO: show pomodoro timer modal bottom sheet
},
),
IconButton(
tooltip: 'Add',
icon: Icon(Icons.add_circle_outline_outlined),
onPressed: () {
print('add icon pressed!');
//TODO: show add task modal bottom sheet
},
),
],
),
);,
),
body: PageView(
controller: _pageController,
onPageChanged: (page) {
setState(() {
_bottomNavBarCurrentIndex = page;
});
},
children: [
CalendarScreen(),
ToDoListScreen(),
SafeArea(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Overview Screen'),
BottomNavigationBar(
currentIndex: _bottomNavBarCurrentIndex,
type: BottomNavigationBarType.fixed,
backgroundColor: Colors.white,
elevation: 0.0,
iconSize: 16.0,
selectedItemColor: Colors.black,
unselectedItemColor: Colors.grey,
showSelectedLabels: false,
showUnselectedLabels: false,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.calendar_today_rounded),
label: 'Calendar',
tooltip: 'Calendar',
),
BottomNavigationBarItem(
icon: Icon(Icons.checklist_rounded),
label: 'To-Do',
tooltip: 'To-Do List',
),
BottomNavigationBarItem(
icon: Icon(Icons.panorama_fish_eye_rounded),
label: 'Overview',
tooltip: 'Overview',
),
BottomNavigationBarItem(
icon: Icon(Icons.border_all_rounded),
label: 'Covey\'s 4 Quadrants',
tooltip: 'Covey\'s 4 Quadrants',
),
BottomNavigationBarItem(
icon: Icon(Icons.view_column_rounded),
label: 'Kanban Board',
tooltip: 'Kanban Board',
),
],
onTap: (index) {
setState(() {
_bottomNavBarCurrentIndex = index;
_pageController.jumpToPage(index);
});
},
),
],
),
),
),
CoveyQuadrantsScreen(),
KanbanScreen(),
],
),
);
}
}
Unfortunately, this is not a standard way in which the mobile app UI should be designed. This will result in bad user experience.
What if user accidently touches on NavigationBar instead of
AppBar. You will be taken to the new screen and action that I
performed there will be lost or need to handle.
So proper UI guidelines should be met, while we design and develop for the mobile app. Based on guidelines from material.io
Bottom app bars should be used for:
Mobile devices only
Access to a bottom navigation drawer
Screens with two to five actions
Bottom app bars shouldn't be used for:
Apps with a bottom navigation bar
Screens with one or no actions
Refer this link for more useful information about the UI and UX guidelines https://material.io/
I would suggest making a scaffold() with the bottomNavigationBar() as you did. Then you could create a list of Container() objects each representing a different page. For your PageView I'm assuming you have done that, if not then that's the way to do it. Then you could cycle through your pages by setting the body: property of the scaffold to myPages[_currentIndex] or something like that.
Additionally: Like the comment asks, I am also not sure why you would want both BottomNavigationBar and BottomAppBar they both do exactly the same thing. In either case the process is the same as what I described above.

How to prevent iphone notch from overlapping content in bookmarked desktop app?

I'm using SafeArea to display a bottom navigation bar :
SafeArea(
child: ScaffoldMessenger(
child: Scaffold(
body: _tabs[index],
bottomNavigationBar: BottomNavigationBar(
selectedItemColor: Theme.of(context).primaryColor,
unselectedItemColor: Colors.grey,
showUnselectedLabels: true,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.calendar_today), label: "Agenda"),
BottomNavigationBarItem(
icon: Icon(Icons.people), label: "Patients"),
BottomNavigationBarItem(
icon: Icon(Icons.account_balance_wallet), label: "Comptes"),
BottomNavigationBarItem(
icon: Icon(Icons.settings), label: "Réglages"),
],
currentIndex: index,
onTap: (i) => context.read(navigationIndexProvider).index = i,
),
),
),
);
When bookmarked on iphone desktop, the safe area does not prevent the notch from overlapping the bottom navbar.
Here is the result :
How to properly prevent notch from overlapping the bottom bar ?
In SAFEAREA widget there is an argument -bottom
Set this bottom either true or false.
SafeArea(
bottom:true,
child:ScaffoldMessanger()
)
I don't remember the correct one, you can check both and let us know which one works for you.
I think since you're using bottomNavigationBar, the SafeArea should not be wrapped around Scaffold. It should be wrapped by Scaffold like this:
Scaffold(
body: SafeArea(child:
_tabs[index] ...
I think you should only wrap Scaffold with SafeArea when you're not using any kind of bottomNavigationBar

Flutter - Disable Bottom Navigation Bar Animation (growing text)

I want to disable the Bottom Navigation Bar animation for selected item to get the same text/icon size of unselected items.
That's my code:
class BottomNavigationBarHome extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BottomNavigationBar(
unselectedItemColor: Colors.black38,
backgroundColor: Colors.white,
items: [
BottomNavigationBarItem(
icon: Icon(BalanceIcon.scale_balance, size: 15.0),
title: Text('Item 1', style: TextStyle(
),)
),
BottomNavigationBarItem(
icon: Icon(BalanceIcon.scale_balance),
title: Text('Item 2')
),
BottomNavigationBarItem(
icon: Icon(BalanceIcon.scale_balance),
title: Text('Item 3')
),
]
);
}
}
I have already tried setting the same font size, the animation is still here
You can try add type to BottomNavigationBar
BottomNavigationBar(
type: BottomNavigationBarType.fixed,
...
)
The previous answers are correct but you need a combination of both, fixed type and defined font sizes:
BottomNavigationBar(
type: BottomNavigationBarType.fixed,
selectedFontSize: 12.0,
unselectedFontSize: 12.0,
...
)
BottomNavigationBarType.fixed prevents the items from moving horizontally and makes the labels of the unselected items visible.
selectedFontSize: 12.0, unselectedFontSize: 12.0 prevents the font size change when selecting an item that happens even if the type is fixed.
To re-add the gap between icon and label that disappears with this configuration, you can add a bottom padding to the icons in your BottomNavigationBarItem:
BottomNavigationBarItem(
icon: Padding(
padding: EdgeInsets.only(bottom: 2.5),
child: <your icon>,
),
label: <your title>,
),
Add selectedFontSize & unselectedFontSize in BottomNavigationBar and set the same font sizes
BottomNavigationBar(
selectedFontSize: 15.0,
unselectedFontSize: 15.0,

How to make bottomNavigationBar notch transparent

I want to make the notch margin spacing (space between FAB's sides and bottom bar) like android material design explain in Inset FAB, It looks like a zoom background text in this small visible round portion. How we can make notching space transparent to see the text behind it?
However, mine bottom bar is not showing like that
My implementation
Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.white,
child: Image.asset("images/paw.png"),
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => Map()));
},
),
bottomNavigationBar: BottomAppBar(
shape: CircularNotchedRectangle(),
child: new Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(Icons.menu),
color: Colors.transparent,
onPressed: () {},
),
],
),
color: Utiles.primary_bg_color,
),
body: Container(...)
You need extendBody: true in Scaffold
class SO extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
extendBody: true,
appBar: AppBar(),
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Text('text text text text text text text text text text text text text text text text text text text text ');
},
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
onPressed: () {},
),
bottomNavigationBar: BottomAppBar(
shape: CircularNotchedRectangle(),
notchMargin: 12,
color: Colors.blue,
child: Container(
height: 60,
),
),
);
}
}
BottomAppBar + BottomNavigationBar
The question title asks about BottomNavigationBar so I'm adding this answer to help people using both a BottomAppBar with a BottomNavigationBar.
If you're not using BottomNavigationBar, ignore this.
NavBar Covers Notch
By default, a BottomNavigationBar used as a child inside a BottomAppBar, will cover the notch like so:
We need to remove its color & shadow to let the notch show.
Using BottomNavigationBar in BottomAppBar
To keep the notch visible...
BottomNavigationBar needs:
a backgroundColor specified, with 0 alpha (completely transparent)
otherwise, the default onBackground theme color is used, covering the notch
elevation: 0 to remove an ugly shadow under BottomNavigationBar
the transparent backgroundColor makes the shadow visible & horrendous
BottomAppBar needs:
shape: CircularNotchedRectangle() obviously, to have a notch for the FAB
elevation: 0 to remove a slight shadow under the notched FAB (barely visible)
Scaffold needs:
extendBody: true to allow body content to flow underneath notched FAB
SafeArea needs:
if using SafeArea, use bottom:false arg, so our body can flow below past the BottomNavigationBar, under the FAB
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
extendBody: true, // CRITICAL for body flowing under FAB
body: SafeArea(
child: Center(
child: Container(
color: Colors.greenAccent,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
),
bottom: false,
// ↑ SafeArea(bottom:false) allows Scaffold body:+extendBody: to hit bottom edge
),
// ↓ Location: centerDocked positions notched FAB in center of BottomAppBar ↓
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
bottomNavigationBar: BottomAppBar( // ****** APP BAR ******************
clipBehavior: Clip.antiAlias,
shape: CircularNotchedRectangle(), // ← carves notch for FAB in BottomAppBar
color: Theme.of(context).primaryColor.withAlpha(255),
// ↑ use .withAlpha(0) to debug/peek underneath ↑ BottomAppBar
elevation: 0, // ← removes slight shadow under FAB, hardly noticeable
// ↑ default elevation is 8. Peek it by setting color ↑ alpha to 0
child: BottomNavigationBar( // ***** NAVBAR *************************
elevation: 0, // 0 removes ugly rectangular NavBar shadow
// CRITICAL ↓ a solid color here destroys FAB notch. Use alpha 0!
backgroundColor: Theme.of(context).primaryColor.withAlpha(0),
// ====================== END OF INTERESTING STUFF =================
selectedItemColor: Theme.of(context).colorScheme.onSurface,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.ac_unit_outlined,
size: 40,
color: Theme.of(context).colorScheme.onBackground),
label: 'Home'),
BottomNavigationBarItem(
icon: Icon(Icons.access_alarm,
size: 40,
color: Theme.of(context).colorScheme.onBackground),
label: 'Edit')
],
),
),
);
Result
With the above pieces in place you should see something like this:
Use, extendBody: true
From the docs,
extendBody: true ensures that that scaffold's body will be visible through the bottom navigation bar's notch
Do:
return Scaffold(
extendBody: true,
(...)
after
body: SafeArea(
bottom: false,
(...)
after "no add backgroundColor"
BottomNavigationBar(
//backgroundColor:
If you use safe Area ,then extended Body and probably other methods doesn't work. So set the safe Area to (false).