I have 5 tabs currently, how do I set the a default tab when launching the app? lets say I want the account tab to be the default tab when opening the app.
How to I do that? Btw, Im using WebView plugin to display a site's content.
Below is the code of my main.dart file. Ive tried searching and all but the solutions I found wont work for me (I think im searching the wrong words. Also, I am new to flutter) Thank you very much!
import 'package:syncshop/widgets/cart_page.dart';
import 'package:syncshop/widgets/categories_page.dart';
import 'package:syncshop/widgets/home_page.dart';
import 'package:syncshop/widgets/profile_account.dart';
import 'package:syncshop/widgets/search_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return MyAppState();
}
}
class MyAppState extends State<MyApp> {
int _selectedPage = 0;
final _pageOptions = [
HomeScreen(),
CategoriesPage(),
SearchPage(),
CartPage(),
ProfileAccount(),
];
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Sync Shop',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: _pageOptions[_selectedPage],
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: _selectedPage,
onTap: (int index) {
setState((){
_selectedPage = index;
});
},
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text("Home"),
),
BottomNavigationBarItem(icon: Icon(Icons.category), title: Text("Categories"),
),
BottomNavigationBarItem(icon: Icon(Icons.search), title: Text("Search"),
),
BottomNavigationBarItem(icon: Icon(Icons.shopping_cart), title: Text("Cart"),
),
BottomNavigationBarItem(icon: Icon(Icons.account_circle), title: Text("Profile"),
),
],
),
),
);
}
}
You can override initState function of State and can put some initial codes there.
So for your example, can do this.
...
class MyAppState extends State<MyApp> {
int _selectedPage = 0;
#override
void initState() {
super.initState();
_selectedPage = 4;
}
...
When you creating BottomNavigationBar set this.currentindex to index that you want
bottomNavigationBar: BottomNavigationBar(
currentindex=1,//This line, it's default 0
type: BottomNavigationBarType.fixed,
currentIndex: _selectedPage,
onTap: (int index) {
setState(() {
_selectedPage = index;
});
},
You must use tab controller.
First you need to extend TickerProviderStateMixin in class.
class MyAppState extends State<MyApp> with TickerProviderStateMixin {
}
Then define TabController like,
_tabController = new TabController(length: _tabLength, vsync: this, initialIndex: 1);
and finally set controller in your TabBarView
controller: _tabController,
Here you initialize the default tab
int _selectedPage = 0;
You can change it to any tab you wish, If you want Profile
int _selectedPage = 4;
import 'package:flutter/material.dart';
import 'package:syncshop/widgets/cart_page.dart';
import 'package:syncshop/widgets/categories_page.dart';
import 'package:syncshop/widgets/home_page.dart';
import 'package:syncshop/widgets/profile_account.dart';
import 'package:syncshop/widgets/search_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return MyAppState();
}
}
class MyAppState extends State<MyApp> {
int _selectedPage = 4;
final _pageOptions = [
HomeScreen(),
CategoriesPage(),
SearchPage(),
CartPage(),
ProfileAccount(),
];
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Sync Shop',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: _pageOptions[_selectedPage],
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: _selectedPage,
onTap: (int index) {
setState(() {
_selectedPage = index;
});
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text("Home"),
),
BottomNavigationBarItem(
icon: Icon(Icons.category),
title: Text("Categories"),
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text("Search"),
),
BottomNavigationBarItem(
icon: Icon(Icons.shopping_cart),
title: Text("Cart"),
),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
title: Text("Profile"),
),
],
),
),
);
}
}
Related
I need to have the transactions screen and the categories screen widgets as BottomNavigationBarItems
However, i receive this error
The method 'Transactions' isn't defined for the type 'HomeState'. Try correcting the name of an existing method, or defining a method named 'Transactions'.
lib\screens\home.dart
import 'package:demo_app/screens/categories.dart';
import 'package:demo_app/screens/transactions.dart';
import 'package:flutter/material.dart';
class Home extends StatefulWidget{
const Home({super.key});
#override
State<Home> createState() => HomeState();
}
class HomeState extends State<Home> {
List<Widget> widgetOptions = [Transactions(), Categories()];
int selectedIndex = 0;
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: const Text('Logged in!'),
),
body: widgetOptions.elementAt(selectedIndex),
bottomNavigationBar: BottomAppBar(
shape: const CircularNotchedRectangle(),
notchMargin: 4,
child: BottomNavigationBar(
backgroundColor: Theme.of(context).primaryColor.withAlpha(0),
elevation: 0,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.account_balance_wallet),
label: 'Transactions'),
BottomNavigationBarItem(
icon: Icon(Icons.category),
label: 'Categories'),
BottomNavigationBarItem(
icon: Icon(Icons.logout),
label: 'Log out'),
],
currentIndex: selectedIndex,
onTap: onItemTapped,
)
)
),
);
}
void onItemTapped(int index){
if(index == 2){
}else{
setState((){
selectedIndex = index;
});
}
}
}
Simply add SizedBox() to widgetOptions list.
List<Widget> widgetOptions = [Transactions(), Categories(), SizedBox()];
Actually the code in the below had issues
screens/categories.dart';
screens/transactions.dart';
lib\screens\home.dart
Solved those and the issue is no longer there.
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,
);
}
}
I have a BottomNavigationBar that navigates to other pages when pressing an icon. This works fine, except the value of the currentIndex property in BottomNavigationBar doesn't update when the state updates, which means there is no change on the acual BottomNavigationBar. enter image description here
I'm using a vaiable (_selectedPage) to keep track of the selected index in the BottomNavigationBar, and the value changes when tapping an item, but it's not updating the currentIndex property when the state updates.. why is that?
import 'package:flutter/material.dart';
import 'package:independentproject/pages/home_page.dart';
import 'package:independentproject/pages/cook_recipe.dart';
class PageNavigationBar extends StatefulWidget {
#override
_PageNavigationBarState createState() => _PageNavigationBarState();
}
class _PageNavigationBarState extends State<PageNavigationBar> {
//default page showing in bottom navigation bar will be CookRecipe()
int _selectedPage = 1;
//all pages optional in bottom navigation bar
final List<Widget> _pageOptions = [
HomePage(),
CookRecipe(),
];
void onTapped(int pageTapped) {
setState(() {
//print(pageTapped);
_selectedPage = pageTapped;
Navigator.push(context, MaterialPageRoute(builder: (context) => _pageOptions[pageTapped]));
//print(_selectedPage);
});
}
#override
Widget build(BuildContext context) {
return BottomNavigationBar(
//TODO: currentIndex: doesn't update when the state updates, why?
currentIndex: _selectedPage,
//items showing in bottom navigation bar
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Homepage'),
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text('Search recipe'),
),
],
onTap: (int pageTapped) {
onTapped(pageTapped);
},
);
}
}
import 'package:flutter/material.dart';
import 'package:independentproject/page_navigation_bar.dart';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Home page'),
),
body: Center(
child: Text('Home page'),
),
bottomNavigationBar: PageNavigationBar(),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:independentproject/page_navigation_bar.dart';
class CookRecipe extends StatefulWidget {
#override
_CookRecipeState createState() => _CookRecipeState();
}
class _CookRecipeState extends State<CookRecipe> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Search recipe'),
),
body: Center(
child: Text('Search recipes'),
),
bottomNavigationBar: PageNavigationBar(),
),
);
}
}
I would advise you to create a widget that will contain the BottomNavigationBar and also PageView that would allow you to switch pages with PageController.
For example:
class _MainScreenState extends State<MainScreen> {
PageController _pageController;
int _page = 1;
Duration pageChanging = Duration(milliseconds: 300);//this is for page animation-not necessary
Curve animationCurve = Curves.linear;//this is for page animation-not necessary
_MainScreenState();
#override
void initState() {
super.initState();
_pageController = PageController(initialPage: 1);
}
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
physics: BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
controller: _pageController,
onPageChanged: onPageChanged,
children: <Widget>[
//here are all the pages you need:
//CookRecipe(),
],
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(
Icons.message,
),
title: Container(height: 0.0),
),
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
title: Container(height: 0.0),
),
BottomNavigationBarItem(
icon: Icon(
Icons.person,
),
title: Container(height: 0.0),
),
],
onTap: navigationTapped,
selectedItemColor: Theme.of(context).backgroundColor,
currentIndex: _page,
),
),
);
}
void navigationTapped(int page) {
_pageController.animateToPage(page,duration: pageChanging,
curve: animationCurve,);
}
#override
void dispose() {
super.dispose();
_pageController.dispose();
}
void onPageChanged(int page) {
if (this.mounted){
setState(() {
this._page = page;
});
}}
You can also do this without the PageView,and use only the controller to switch pages.
BTW-you create new instance of the navigation bar when you load a page which is bad practice
it is because PageNavigationBar is a own class, when you call there a setstate only this class updates
take a look at the Provider
a very usefull state management Package
or you can also handle your Page, when the NavBar is your Main Page and you have only one Page
return MaterialApp(
home: Scaffold(
appBar: ownAppBar(_selectedPage),
body: _bodyOptions[_selectedPage],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedPage,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Homepage'),
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text('Search recipe'),
),
],
onTap: (int pageTapped) {
onTapped(pageTapped);
},
)
),
);
final List<Widget> _bodyOptions = [
HomePage(),
CookRecipe(),
];
You don't need to use Navigator to change pages, I modified your code just try.
import 'package:flutter/material.dart';
main() {
runApp(MaterialApp(home: PageNavigationBar()));
}
class PageNavigationBar extends StatefulWidget {
#override
_PageNavigationBarState createState() => _PageNavigationBarState();
}
class _PageNavigationBarState extends State<PageNavigationBar> {
//default page showing in bottom navigation bar will be CookRecipe()
int _selectedPage = 1;
//all pages optional in bottom navigation bar
final List<Widget> _pageOptions = [
HomePage(),
CookRecipe(),
];
void onTapped(int pageTapped) {
setState(() {
//print(pageTapped);
_selectedPage = pageTapped;
// Navigator.push(context, MaterialPageRoute(builder: (context) => _pageOptions[pageTapped]));
//print(_selectedPage);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _pageOptions[_selectedPage],
bottomNavigationBar: BottomNavigationBar(
//TODO: currentIndex: doesn't update when the state updates, why?
currentIndex: _selectedPage,
//items showing in bottom navigation bar
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Homepage'),
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text('Search recipe'),
),
],
onTap: (int pageTapped) {
onTapped(pageTapped);
},
),
);
}
}
class CookRecipe extends StatefulWidget {
#override
_CookRecipeState createState() => _CookRecipeState();
}
class _CookRecipeState extends State<CookRecipe> {
#override
Widget build(BuildContext context) {
return Center(
child: Text('Search recipes'),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Center(
child: Text('Home page'),
);
}
}
I have BottomNavigationBar in flutter & called separate widgets for each tab. For example I am having button into that widget which redirects to new screen, I want that BottomNavigationBar should be persisted in new screen as well. I have checked couple of articles but unable to understand. Below is code for BottomTabNavigationBar
import 'package:flutter/material.dart';
import 'package:timeout_dubai/fragments/HomeFragment.dart';
import 'package:timeout_dubai/fragments/MtTimeFragment.dart';
import 'package:timeout_dubai/fragments/MyLocFragment.dart';
import 'package:timeout_dubai/fragments/ThingsLoveFragment.dart';
class LoginScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _HomeState();
}
}
class _HomeState extends State<LoginScreen> {
int _currentIndex = 0;
GlobalKey globalKey = new GlobalKey(debugLabel: 'btm_app_bar');
final List<Widget> _children = [
new HomeFragment(),
new ThingsLoveFragment(),
new MyLocFragment(),
new MyTimeFragment()
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
onTap: onTabTapped,
key: globalKey,
currentIndex: _currentIndex,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home,),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.favorite),
title: Text('Things I Love'),
),
BottomNavigationBarItem(
icon: Icon(Icons.location_on),
title: Text('My Locations'),
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
title: Text('My Time Out')
),
],
),
);
}
void onTabTapped(int index) {
print("Index $index");
setState(() {
_currentIndex = index;
});
}
}
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.