How To Fix Bottom navigation in flutter? - flutter

How to fix Bottom Navigation in Flutter?
MediaQuery.Of() called with context That does not contain a
MediaQuery.Bottom Navigation Not working.
This code Showing Error What is MediaQuery.Of() called with context That does not contain a MediaQuery?
import 'package:flutter/material.dart';
void main(){
runApp(Home());
}
class Home extends StatefulWidget{
#override
State<StatefulWidget> createState() => _HomeState();
}
class _HomeState extends State<Home>{
int currindex=0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Bottom Nav "),
),
body: Container(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currindex,
items:[BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text("Home"),
backgroundColor: Colors.blue
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text("Search"),
backgroundColor: Colors.blue
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
title: Text("Profile"),
backgroundColor: Colors.blue
),],
onTap: (index){
setState(() {
currindex=index;
});
},
));
}
}

it is because you are not using MaterialApp(), you need to use MaterialApp() in your widget tree
look at this demo....
void main() => runApp(Home());
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: //your Title,
theme: //your theme,
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget{
#override
State<StatefulWidget> createState() => _HomePageState();
}
//and your _HomePageState widget goes here

Related

How to use bottomNavigationBar in a separate file?

I have the following code that is working properly:
import 'package:flutter/material.dart';
import 'screen_curiosities.dart';
import 'screen_movies.dart';
import 'screen_releases.dart';
import '../utils/side_menu.dart';
import '../utils/bottom_menu.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
int selectedIndex = 0;
List screens = [
ScreenMovies(),
ScreenReleases(),
ScreenCuriosities()
];
void onClicked(int index) {
setState(() {
selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Movies'),
backgroundColor: Colors.black,
),
body: Center(
child: screens.elementAt(selectedIndex),
),
drawer: SideMenu(),
bottomNavigationBar: BottomNavigationBar(
items:[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Movies',
),
BottomNavigationBarItem(
icon: Icon(Icons.new_releases),
label: 'Releases',
),
BottomNavigationBarItem(
icon: Icon(Icons.question_answer),
label: 'Curiosities',
)
],
currentIndex: selectedIndex,
onTap: onClicked,
selectedItemColor: Colors.red[800],
backgroundColor: Colors.black,
unselectedItemColor: Colors.white,
)
);
}
}
Now I am trying to separate the Widget BottomNavigationBar to another file and call him on the property "bottomNavigationBar" from Scaffold. It would be like this:
bottomNavigationBar: BottomMenu()
I did it with the Widget Drawer and it worked, but when I tried the same thing with bottomNavigationBar it wasn't successful.
When I try to use the variable selectedIndex in the new Widget it is always undefined.
I tried many things, but I couldn't solve this. Is there any way to use the Widget bottomNavigationBar in a separated file?
EDIT
Below, follow the 2 files that I need to make this link from the menu to the page in order to make them work together:
file home.dart
import 'package:flutter/material.dart';
import 'screen_curiosities.dart';
import 'screen_movies.dart';
import 'screen_releases.dart';
import '../utils/side_menu.dart';
import '../utils/bottom_menu.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
int selectedIndex = 0;
List screens = [
ScreenMovies(),
ScreenReleases(),
ScreenCuriosities()
];
void onClicked(int index) {
setState(() {
selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Movies'),
backgroundColor: Colors.black,
),
body: Center(
child: screens.elementAt(selectedIndex),
),
drawer: SideMenu(),
bottomNavigationBar: BottomMenu() // Using the Widget here
}
}
file bottom_menu.dart
import 'package:flutter/material.dart';
class BottomMenu extends StatelessWidget {
#override
Widget build(BuildContext context) {
return BottomNavigationBar(
items:[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Movies',
),
BottomNavigationBarItem(
icon: Icon(Icons.new_releases),
label: 'Releases',
),
BottomNavigationBarItem(
icon: Icon(Icons.question_answer),
label: 'Curiosities',
)
],
currentIndex: selectedIndex, // the variable is undefined
onTap: onClicked, // the function is undefined
selectedItemColor: Colors.red[800],
backgroundColor: Colors.black,
unselectedItemColor: Colors.white,
);
}
}
You can copy paste run two full code below
You can pass selectedIndex and onClicked to BottomMenu
code snippet
bottomNavigationBar: BottomMenu(
selectedIndex: selectedIndex,
onClicked: onClicked,
));
...
class BottomMenu extends StatelessWidget {
final selectedIndex;
ValueChanged<int> onClicked;
BottomMenu({this.selectedIndex, this.onClicked});
working demo
full code main.dart
import 'package:flutter/material.dart';
import 'bottom.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
int selectedIndex = 0;
List screens = [ScreenMovies(), ScreenReleases(), ScreenCuriosities()];
void onClicked(int index) {
setState(() {
selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Movies'),
backgroundColor: Colors.black,
),
body: Center(
child: screens.elementAt(selectedIndex),
),
//drawer: SideMenu(),
bottomNavigationBar: BottomMenu(
selectedIndex: selectedIndex,
onClicked: onClicked,
));
}
}
class ScreenMovies extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Text("ScreenMovies"),
);
}
}
class ScreenReleases extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Text("ScreenReleases"),
);
}
}
class ScreenCuriosities extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Text("ScreenCuriosities"),
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Home(),
);
}
}
full code bottom.dart
import 'package:flutter/material.dart';
class BottomMenu extends StatelessWidget {
final selectedIndex;
ValueChanged<int> onClicked;
BottomMenu({this.selectedIndex, this.onClicked});
#override
Widget build(BuildContext context) {
return BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Movies',
),
BottomNavigationBarItem(
icon: Icon(Icons.new_releases),
label: 'Releases',
),
BottomNavigationBarItem(
icon: Icon(Icons.question_answer),
label: 'Curiosities',
)
],
currentIndex: selectedIndex,
onTap: onClicked,
selectedItemColor: Colors.red[800],
backgroundColor: Colors.black,
unselectedItemColor: Colors.white,
);
}
}

NoSuchMethodError: The getter was called on null

`
class MainPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider( //Comes from provider class
create: (context) => LocaleProvider(),
builder: (context, child) {
final provider = Provider.of<LocaleProvider>(context);
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Forts In Maharashtra',
locale: provider.locale,
supportedLocales: L10n.all,
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
home: MyApp(),
);
});
}
}
class MyApp extends StatefulWidget {
//static const String _title = 'Forts in Maharashtra';
MyApp({Key key, this.title}) : super(key: key);
final String title;
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
new FirebaseNotifications().setUpFirebase();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(accentColor: Colors.deepOrange),
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text(
AppLocalizations.of(context).apptitle, //Translates the text
style: TextStyle(fontSize: 23.0),
),
backgroundColor: Colors.deepOrange,
actions: [
Icon(Icons.language, size: 28),
LanguagePick(),
const SizedBox(width: 12),
],
),
body: MyBottomNavigationBar()),
);
}
}
class MyBottomNavigationBar extends StatefulWidget {
class _MyBottomNavigationBarState extends State<MyBottomNavigationBar> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: _children[_currentindex],
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
selectedItemColor: Colors.deepOrange,
onTap: onTappedBar,
currentIndex: _currentindex,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.explore),
label: AppLocalizations.of(context).exploreforts), //Giving error here
BottomNavigationBarItem(
icon: Icon(MdiIcons.waves), label: 'Sea Forts'),
BottomNavigationBarItem(
icon: Icon(Icons.terrain), label: 'Attractions'),
BottomNavigationBarItem(
icon: Icon(Icons.location_city), label: 'City Forts'),
],
));
}
}`
I am trying to use the Localization feature in my application. I am able to change the AppBar title to another language but I am unable to change the language on the BottomNavigationBar. I am having trouble changing the language in BottomNavigationBar. The App language is changed on the AppBar but I am facing issues while using the same in the BottomNavigationBar. I have added comments where required.
This is because you are defining two MaterialApp. You only need to define one in the main and render it in the entire app, remove the MaterialApp from the _MyAppState class

Flutter: animate appbar color with bottomnavigationbar

I wonna animate my appbar color the same way as the bottomnavigationbar does with the shifting type. So the appbar and bottomnavigationbar change color together.
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _tabIndex = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Dash')),
body: Container(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _tabIndex,
onTap: (value) => setState(() => _tabIndex = value),
type: BottomNavigationBarType.shifting,
unselectedItemColor: Theme.of(context).unselectedWidgetColor,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.dashboard), title: Text('Dash'), backgroundColor: Colors.blue),
BottomNavigationBarItem(
icon: Icon(Icons.insert_chart), title: Text('Data'), backgroundColor: Colors.red),
BottomNavigationBarItem(
icon: Icon(Icons.monetization_on), title: Text('Income'), backgroundColor: Colors.orange),
]),
);
}
}
How can I do this? (I'm fairly new to flutter) Thanks!
It's very simple. Simply change color based on the selected index.
Here you go
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _tabIndex = 0;
var colors = [Colors.blue, Colors.red, Colors.orange];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Dash'),
backgroundColor: colors[_tabIndex],
),
body: Container(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _tabIndex,
onTap: (value) => setState(() => _tabIndex = value),
type: BottomNavigationBarType.shifting,
unselectedItemColor: Theme.of(context).unselectedWidgetColor,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.dashboard),
title: Text('Dash'),
backgroundColor: colors[0]),
BottomNavigationBarItem(
icon: Icon(Icons.insert_chart),
title: Text('Data'),
backgroundColor: colors[1]),
BottomNavigationBarItem(
icon: Icon(Icons.monetization_on),
title: Text('Income'),
backgroundColor: colors[2]),
]),
);
}
}
See the live demo here.

MaterialPageRoute goes to a new page without the appbar using it with bottomNavigationBar

I have an app with three routes and uses the bottomNavigationBar to navigate between them. In one of the routes I have a button in the page that will also navigate to one of the pages.
Heres my main page
import 'package:flutter/material.dart';
import 'page_two.dart';
import 'page_three.dart';
void main() {
return runApp(MyApp());
}
/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _selectedIndex = 0;
List<Widget> _widgetOptions = <Widget>[
Text('Main'),
PageTwo(),
PageThree(),
];
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, color: Colors.black),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.business, color: Colors.black),
title: Text('Business'),
),
BottomNavigationBarItem(
icon: Icon(Icons.business, color: Colors.black),
title: Text('Business'),
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
}
Page Two
import 'package:flutter/material.dart';
import 'main.dart';
class PageTwo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: RaisedButton(
child: Text('Go page 1'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MyApp()),
);
},
),
);
}
}
and Page Three with a button that navigates to page two
import 'package:flutter/material.dart';
import 'page_two.dart';
class PageThree extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: RaisedButton(
child: Text('Go page 1'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => PageTwo()),
);
},
),
);
}
}
When I press the button on Page Three, it will go to Page Two without the AppBar and the BottomNavigationBar
Use GlobalKey and In PageTwo Widget call MyStatefulWidgetState's _onItemTapped function
You can see working demo and full code below
code snippet
final scakey = new GlobalKey<_MyStatefulWidgetState>();
...
child: Text('Go page 2'),
onPressed: () {
scakey.currentState._onItemTapped(1);
full code
import 'package:flutter/material.dart';
void main() {
return runApp(MyApp());
}
final scakey = new GlobalKey<_MyStatefulWidgetState>();
/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: MyStatefulWidget(key: scakey),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _selectedIndex = 0;
final myKey = new GlobalKey<_MyStatefulWidgetState>();
List<Widget> _widgetOptions = <Widget>[
Text('Main'),
PageTwo(),
PageThree(),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: myKey,
appBar: AppBar(
title: const Text('BottomNavigationBar Sample'),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home, color: Colors.black),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.business, color: Colors.black),
title: Text('Business'),
),
BottomNavigationBarItem(
icon: Icon(Icons.business, color: Colors.black),
title: Text('Business'),
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
}
class PageTwo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: RaisedButton(
child: Text('Go page 1'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MyApp()),
);
},
),
);
}
}
class PageThree extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: RaisedButton(
child: Text('Go page 2'),
onPressed: () {
scakey.currentState._onItemTapped(1);
/*Navigator.push(
context,
MaterialPageRoute(builder: (context) => PageTwo()),
);*/
},
),
);
}
}
When using navigation bar to navigate between pages, you are tapping on BottomNavigationBarItem to change the index by calling setState() and as the result, build method is triggered with a new _selectedIndex and that index is used to render your appropriate widget.
_widgetOptions.elementAt(_selectedIndex)
Navigator.push on the other hand is just pushing a new route on top of the navigation stack. You are not getting an AppBar or BottomNavigationBar since you don't have them on PageTwo. What I would recommend you is to create a callback function in PageTwo and call that function on button tap. You can now use that callback in MyStatefulWidget to change the index with setState. Here is an example
Declare a final like below in your pages.
final void Function(int index) pageChanged;
In the onTap event of your button, call this function.
widget.pageChanged(1); // PageTwo
In MyStatefulWidget, when you are creating pages, pass the function.
PageTwo(pageChanged:(index){
setState(){_selectedIndex = index;}
});

Not able to use items property of BottomNavigationBar in flutter

I am trying to use BottomNavigationBar in my flutter project and I want to supply items to it. And for that, I have to use items property. But I am not able to find the items property in the BottomNavigationBar. Please see the attached picture.
And here is complete code:
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance
// as done by the _incrementCounter method above.
// The Flutter framework has been optimized to make rerunning
// build methods fast, so that you can just rebuild anything that
// needs updating rather than having to individually change
// instances of widgets.
return new Scaffold(
appBar: new AppBar(
// Here we take the value from the MyHomePage object that
// was created by the App.build method, and use it to set
// our appbar title.
title: new Text(config.title),
),
bottomNavigationBar: new BottomNavigationBar(
currentIndex: 0,
onTap: (value){
},
),
// a style that looks nicer for build methods.
);
}
}
Are you sure you have the latest version of flutter. As far a i can tell, destination labels were switched to items in a commit in dec 2016:
https://github.com/flutter/flutter/commit/1b9939af9547513061d2e30716f182b490f5362b#diff-f907c739b721784b11a7fec0459d384f
Seems like things have changed as with the newer version of the Dart plugin. I have achieved the same thing via the following code (Note that now we have to use Map with labels property):
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'App Name',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'App Name'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var bottomBarLabels = [
new DestinationLabel(
icon: new Icon(Icons.live_tv), title: new Text("Live")),
new DestinationLabel(
icon: new Icon(Icons.date_range), title: new Text("Matches")),
];
#override
Widget build(BuildContext context) {
void _handleBottomNavigationBarTap(int newValue) {
switch (newValue) {
case 0:
print("Live Clicked");
// Scaffold.of(context).showSnackBar(new SnackBar(
// content: new Text("Live Clicked"),
// ));
break;
case 1:
print("Matches Clicked");
// Scaffold.of(context).showSnackBar(new SnackBar(
// content: new Text("Matches Clicked"),
// ));
break;
}
}
return new Scaffold(
appBar: new AppBar(
title: new Text(config.title),
),
bottomNavigationBar: new BottomNavigationBar(
labels: bottomBarLabels, onTap: _handleBottomNavigationBarTap),
);
}
}
I was able to use the items with BottomNavigationBar without facing any problems.
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
home: new MyApp()));
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Bottom Navigation"),
),
bottomNavigationBar: new BottomNavigationBar(
items: [new BottomNavigationBarItem(
icon: new Icon(Icons.account_box), title: new Text("Account")),
new BottomNavigationBarItem(
icon: new Icon(Icons.add), title: new Text("Add")),
new BottomNavigationBarItem(
icon: new Icon(Icons.close), title: new Text("Close")),
],
),
);
}
}