how can I achieve a bottom navigation bar with these features? - flutter

There are five navigation items in total and the widths are 154,153,154,153,154. I know it's kind of strange but the UI design is like this. As for this I guess I cannot use any Widget about navigator in the flutter lib.
Each item contains an icon and a text as usual but the distance between the two should be set exactly. I don't know if it can be set in flutter widget bottomNavigatorBar.
Commonly, the color of the icon, text and the background will change when selected.
What I have done: I created a widget and add it to the bottom of every pages. As you can imagine, when jumping to a new page, the navigation bar will re-render. That is not the same as we use in our mobile phones.
I have found some articles and blogs, but still can't solve my problem. Is there any reference?

You can use the below code and redirect this page into main.dart and can use test and icon also.
class nav extends StatefulWidget {
#override
_navState createState() => _navState();
}
class _navState extends State<nav> {
int tabIndex = 0;
List<Widget> listScreens;
#override
void initState() {
ScreenUtil.init(width: 375, height: 812);
super.initState();
listScreens = [
Home(),
Treatments(),
Request(),
Appointments(),
Menu(),
];
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: listScreens[tabIndex],
bottomNavigationBar: new Theme(
data: Theme.of(context).copyWith(
canvasColor: Color(0xFF320151),
primaryColor: Color(0xFF320151)),
child: BottomNavigationBar(
backgroundColor: Color(0xFF38095c),
selectedItemColor: Color(0xFFe34fd1),
unselectedItemColor: Color(0xFF510382),
currentIndex: tabIndex,
onTap: (int index) {
setState(() {
tabIndex = index;
});
},
items: [
BottomNavigationBarItem(
title: Text(""),
icon: Container(
width: 154, child: Center(child: Icon(AntDesign.home))),
),
BottomNavigationBarItem(
title: Text(""),
icon: Container(
width: 153,
child: Center(
child: Icon(MaterialCommunityIcons.medical_bag))),
),
BottomNavigationBarItem(
title: Text(""),
icon: Container(
width: 154,
child: Center(child: Icon(Fontisto.share_a))),
),
BottomNavigationBarItem(
title: Text(""),
icon: Container(
width: 153,
child: Center(child: Icon(AntDesign.calendar))),
),
BottomNavigationBarItem(
title: Text(""),
icon: Container(
width: 154,
child: Center(child: Icon(Ionicons.ios_person))),
),
]),
)),
);
}
}

Related

How to keep navigation bar when push to subpages and back to main page?

screentshot
In my app there are some features in home page,what I want is when direct to their sub pages and still keep the buttom navigation bar.
Code for navigation bar Below the answer
Code for parts of home page
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold( resizeToAvoidBottomInset:false,
body: SlidingUpPanel(
body: Center(
child:Container(
constraints: BoxConstraints.expand(),
margin: const EdgeInsets.only(top:23),
child: Column(
children: [
.....
Container(
width: 730,
height: 190,
alignment:Alignment.center,
child:Wrap(
children: <Widget>[
//...otherFiveFeatures...//
OutlinedButton(
onPressed:()async{
var nav = await Navigator.of(context).pushNamed('/routerMobileScannerPage');
if(nav==true||nav==null)
{Navigator.of(context).pushNamedAndRemoveUntil('/routerHomePage',(Route<dynamic>route)=>false);
}
},
),
],
),
)
],
),
),
),
collapsed: Container(),
panel: Center(),
),
)
);
}
To achieve this, you need to manage multiple widgets for a single selection index. For example, from Home Screen you want to navigate to Details screen keeping the Home tab selected, you need to manage a flag for that selection. Something like this.
Code to get widget based on selection
Widget _getBodyWidget() {
switch (currentIndex) {
case 0:
return shouldShowDetails ? DetailsView() : HomeView();
case 1:
return CategoriesView();
default:
return HomeView();
}
}
In the code above, there is a flag shouldShowDetails which will be assigned as true when user taps on the Details button. When user wants to come to HomeScreen, change to false.
For such scenarios, I would suggest you to use the Provider plugin. It provides us an easy way to update the widget state based on such flags.
Code for buttom navigation bar
class PageCTRLWidget extends State<statePageCTRLWidget> with AutomaticKeepAliveClientMixin{
#override
bool get wantKeepAlive => true;
int currentIndex=0;
final screens=[
stateHomePageWidget(),
Center(child: Text('Categories',style: TextStyle(fontSize: 45),),),
Center(child: Text('Assistant',style: TextStyle(fontSize: 45),),),
stateMemberPageWidget()
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: currentIndex,
children: screens,
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
selectedItemColor: Colors.orange,
currentIndex: currentIndex,
onTap:(tappedIndex)=>setState(()=>currentIndex=tappedIndex),
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.menu_book_rounded),
label: 'Categories',
),
BottomNavigationBarItem(
icon: Icon(Icons.add_location_alt_rounded),
label: 'Assistant',
),
BottomNavigationBarItem(
icon: Icon(Icons.account_box_rounded),
label: 'Member',
)
],
),
);
}
}

Flutter: "Multiple GlobalKeys in the Widget tree" while Navigation

I'm facing an issue of "Multiple GlobalKeys in the Widget tree" while Navigation.
I have a BottomNavigationBar & a Drawer defined in the Scaffold of a Base Screen and in the body parameter of Scaffold I have multiple screens which I'm accessing with BottomNavigationBar. The thing is, I'm accessing the Drawer of the Base Screen from one of the multiple screens by using a GlobalKey, and everything's working fine but when I Navigate to the Base Screen from Another Screen then I get the above-mentioned error.
I have tried a solution of not using a static keyword while defining the key and it solves the error of navigation but then I can't access the Drawer because then I get another error of "method 'openDrawer' was called on null".
This is a separate class where I have defined the Key:
class AppKeys {
final GlobalKey<ScaffoldState> homeKey = GlobalKey<ScaffoldState>();
}
This is the Base Screen:
class Base extends StatefulWidget {
#override
_BaseState createState() => _BaseState();
}
class _BaseState extends State<Base> {
int selectedScreen = 0;
final screens = List<Widget>.unmodifiable([Home(), Cart(), Orders(), Help()]);
AppKeys appKeys = AppKeys();
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: MyDrawer(),
key: appKeys.homeKey,
body: screens[selectedScreen],
bottomNavigationBar: SizedBox(
height: 80,
child: BottomNavigationBar(
onTap: (val) {
setState(() {
selectedScreen = val;
});
},
currentIndex: selectedScreen,
selectedItemColor: AppColor.primary,
elevation: 20.0,
unselectedItemColor: Colors.grey,
showUnselectedLabels: true,
type: BottomNavigationBarType.fixed,
iconSize: 25,
selectedFontSize: 15,
unselectedFontSize: 15,
items: [
BottomNavigationBarItem(
icon: Icon(AnanasIcons.home), title: Text("Home")),
BottomNavigationBarItem(
icon: Icon(AnanasIcons.cart), title: Text("Cart")),
BottomNavigationBarItem(
icon: Icon(AnanasIcons.orders), title: Text("My Orders")),
BottomNavigationBarItem(
icon: Icon(AnanasIcons.help), title: Text("Help")),
],
),
),
);
}
}
This is the Home Screen from where I'm accessing the Drawer:
class Home extends StatelessWidget {
final AppKeys appKeys = AppKeys();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(
AnanasIcons.menu,
color: Colors.black,
),
onPressed: () {
appKeys.homeKey.currentState.openDrawer();
}),
backgroundColor: Theme.of(context).canvasColor,
title: Text("Hi"),
actions: [
IconButton(
icon: Icon(
Icons.person,
color: Colors.black,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Profile(),
));
})
],
),
body: Container(),
);
}
}
I've found the answer! Instead of pushing the route with the key, we need to remove all the routes from the stack till the screen where we have to go.
Here's the code for that:
Navigator.of(context).popUntil(ModalRoute.withName(Base.routeName));

How to make Bottom Navigation Bar visible on every page of my app in flutter?

Please, anyone, tell me how can I make Bottom Navigation Bar visible on every page of my app in flutter? I know there's an option called Custom Navigator (https://pub.dev/packages/custom_navigator), but how to use this for more than 2 subpages? Please help me I am stucked on a big project. Thank you in Advance :)
you just need to change widgets on the same page, not navigating, check this code out!
import 'package:flutter/material.dart';
import './pages/home.dart'; //imported widget 1
import './pages/listed_homes.dart'; //imported widget 2
import './widgets/form_card.dart'; //imported widget 3
class BottomNav extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return BottomNavState();
}
}
class BottomNavState extends State<BottomNav> {
int _currentIndex = 0; //initialize index that alters widgets when increased or decreased`
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (value) {
_currentIndex = value;
setState(() {});
},
items: [
BottomNavigationBarItem(
//<--- item 1 text and icon declared
icon: Icon(Icons.book),
title: Text('Find a home')),
BottomNavigationBarItem(
//<--- item 2 text and icon declared
icon: Icon(Icons.add_a_photo),
title: Text('Enlist a home')),
BottomNavigationBarItem(
//<--- item 3 text and icon declared
icon: Icon(Icons.message),
title: Text('Messages')),
]),
body: Stack(children: [
[
Home(_cent), //widget one
FormCard(widget.model), //widget two
Messages() //widget three
][_currentIndex], //Alter widgets with changing index
Positioned(
top: 30,
left: 15,
child: IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
padding: EdgeInsets.all(0.0),
iconSize: 40.0,
),
)
]),
);
}
}
Check this method to keep a widget on every page:
MaterialApp(
title: 'Flutter Demo',
initialRoute:"/home",
routes: [
...
],
builder: (context, child) {
return Stack(
children: [
child!,
Overlay(
initialEntries: [
OverlayEntry(
builder: (context) {
return YourCustomWidget(); *//This widget now appears on all pages*
},
),
],
),
],
);
},

how to show the drawer icon on bottom right in flutter?

I need to show the the total of 5 icons (4 bottom navigation icon + 1 menu drawer icon) in the bottom of the page. I am using BottomNavigationBarItem to show the four bottom navigation icons. In that i need to add the menu drawer icon. I can find answers for only bottom right and left. Kindly help to resolve this
class HomeScreen extends StatefulWidget{
final int indexvalue;
HomeScreen({Key key, #required this.indexvalue}) : super(key: key);
#override
State createState() {
return HomeScreenState();
}
}
class HomeScreenState extends State<HomeScreen> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
int _selectedPage = 0;
final _pageOptions = [
Screen1(),
WebView1(),
Home(),
Leader(),
];
#override
Widget build(BuildContext context){
Size size = MediaQuery.of(context).size;
var val = widget.indexvalue;
print(widget.indexvalue);
return MaterialApp(
title: 'Home',
home: Scaffold(
key: _scaffoldKey,
appBar: AppBar(title: Text('Home'),),
body: _pageOptions[_selectedPage],
endDrawer: build_1(),
bottomNavigationBar: new Theme(
data: Theme.of(context).copyWith(
// sets the background color of the `BottomNavigationBar`
canvasColor: Colors.green,
// sets the active color of the `BottomNavigationBar` if `Brightness` is light
primaryColor: Colors.red,
textTheme: Theme
.of(context)
.textTheme
.copyWith(caption: new TextStyle(color: Colors.yellow))), // sets the inactive color of the `BottomNavigationBar`
child: new BottomNavigationBar(
showSelectedLabels: false, // <-- HERE
showUnselectedLabels: false,
currentIndex: _selectedPage,
onTap: (int index) {
setState(() {
_selectedPage = index;
});
},
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('Home')),
BottomNavigationBarItem(icon: Icon(Icons.photo_library), title: Text('photo_library')),
BottomNavigationBarItem(icon: Icon(Icons.book), title: Text('book')),
BottomNavigationBarItem(icon: Icon(Icons.notifications), title: Text('download')),
],
),
),
)
);
}
}
build_1(){
return SizedBox(
//width: size.width,
child: Drawer(
child: new ListView(
children: <Widget>[
new DrawerHeader(
child: new Text("Drawer Header"),
decoration: new BoxDecoration(
color: Colors.blue,
),
),
new Text("Item 1"),
new Text("Item 2"),
new Text("Item 3"),
new Text("Item 4"),
new Text("Item 5"),
new Text("Item 6"),
],
),
),
);
}
You can add another item in your bottomNavigationBar
BottomNavigationBarItem(icon: Icon(Icons.menu), title: Text('Menu'))
and check the index in onTap method and call _scaffoldKey.currentState.openDrawer(); to open the drawer
onTap: () {
int menuIndex = 4;//if you want it to be the last(bottom right)
if (index == menuIndex) {
_scaffoldKey.currentState.openDrawer();
}
else {
setState(() {
_selectedPage = index;
});
}
}
}
if you want to just add an icon everywhere in your screen to open your drawer just call
_scaffoldKey.currentState.openDrawer(); in onTap method
For exampe:
IconButton(
icon: Icon(Icons.menu),
color: Colors.white,
onPressed: () {
_scaffoldKey.currentState.openDrawer();
},)
If you are using in your Scaffold:
drawer: Drawer() use _scaffoldKey.currentState.openDrawer();
endDrawer: Drawer() use _scaffoldKey.currentState.openEndDrawer();

How to make container fix positioned even after keyboard is displayed

I've been playing with this for some time and can not get this working. Basically I've got bottom navigation bar and I want at the top of the bottom navigation bar fixed positioned container which stay there even if the keyboard is displayed. So far no matter what I tried the container ends up at the top of the keyboard when the keyboard is called. Here is my code where I ended up so far. Basically my last hope was to wrap it in Stack widget but that didn't work.
class HomeScreen extends StatefulWidget { static const String id = '/app'; final FirebaseUser user; HomeScreen({this.user});
#override _HomeScreenState createState() => _HomeScreenState(); }
class _HomeScreenState extends State<HomeScreen> { int _currentIndex
= 0; final List<Widget> _children = [Screen1(), Screen2()];
void bottomTabHandler(int index) {
setState(() {
_currentIndex = index;
}); }
#override Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: _currentIndex,
onTap: bottomTabHandler,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.receipt),
title: Text('Option1'),
),
BottomNavigationBarItem(
icon: Icon(Icons.receipt),
title: Text('Option2'),
),
BottomNavigationBarItem(
icon: Icon(Icons.add), title: Text('Option3')),
],
),
appBar: AppBar(
centerTitle: true,
title: Text('XXX'),
automaticallyImplyLeading: false,
),
endDrawer: AppbarDrawer(),
body: Stack(
children: <Widget>[
_children[_currentIndex],
Positioned(
bottom: 0,
child: Container(
width: 250,
height: 100,
color: Colors.blue,
),
),
],
),
);
}
}
I've got simple TextField at screen1 and this is what I get
If you want to make sure the Widgets don't get adjusted when the keyboard appears, you can use the resizeToAvoidBottomInset property of the Scaffold:
return Scaffold(
resizeToAvoidBottomInset: false,
body: Stack(
...