How can I use same navigation route I used for bottomnavigationbar in drawer widget in flutter? - android

I already have a bottom navigation bar which navigates to different pages.
then I add a drawer which I want it to change the widget in the body only, but the issue is that I made the drawer in another page and I called it, so it is not responding or I'm not calling it perfectly as I should.
Below is the navigation for the bottomnavigationbar, I have imported all necessary files
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int currentTab = 0;
final tabs = [
IndexPage(),
Save(),
Invest(),
Wallet(),
Cards(),
];
#override
Widget build(BuildContext context) {
return MaterialApp(
color: Colors.grey[900],
debugShowCheckedModeBanner: false,
title: 'Flochristos App',
theme: ThemeData(),
home: Scaffold(
backgroundColor: Colors.black,
resizeToAvoidBottomPadding: false,
resizeToAvoidBottomInset: false,
key: _scaffoldKey,
appBar: AppBar(
backgroundColor: Colors.grey[900],
title: Text(
'PettySave',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.brightness_7_outlined),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.keyboard_arrow_down_sharp),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.account_circle_rounded),
onPressed: () {},
),
],
//shadowColor: Colors.grey,
),
body: tabs[currentTab], //this is where I want to change the pages
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
bottomNavigationBar: BottomNavigationBar(
onTap: (int index) {
setState(() {
currentTab = index;
});
},
currentIndex: currentTab,
backgroundColor: Colors.grey[900],
unselectedIconTheme: IconThemeData(color: Colors.grey),
selectedItemColor: Colors.green,
unselectedItemColor: Colors.grey,
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home_filled),
// ignore: deprecated_member_use
title: Text(
"Home",
),
),
BottomNavigationBarItem(
icon: FaIcon(FontAwesomeIcons.pagelines),
// ignore: deprecated_member_use
title: Text(
"Save",
),
),
BottomNavigationBarItem(
icon: Icon(Icons.trending_up),
// ignore: deprecated_member_use
title: Text(
"Invest",
),
),
BottomNavigationBarItem(
icon: Icon(Icons.account_balance_wallet_outlined),
// ignore: deprecated_member_use
title: Text(
"Wallet",
),
),
BottomNavigationBarItem(
icon: Icon(Icons.credit_card),
// ignore: deprecated_member_use
title: Text(
"Cards",
),
),
],
),
),
);
}
}
}
that's the main.dart code
body: tabs[currentTab], //this is where I want to change the pages
then I created another page for drawer which I called all appropriate pages
from one of the list style in the slidedrawer.dart , I'm trying to set currentTab to any index I want.... but it's not working.
ListTile(
contentPadding: EdgeInsets.fromLTRB(30, 0, 0, 0),
leading: Icon(
Icons.trending_up,
color: Colors.grey[500],
),
title: Text(
'Investments',
style: TextStyle(
color: Colors.grey[300],
fontWeight: FontWeight.bold,
),
),
onTap: () {
setState(() {
currentTab = 1;
});
},
),
I want the index to turn to Save()

List<Widget> tabs = [
IndexPage(),
Save(),
Invest(),
Wallet(),
Cards(),
];

There are many ways to add a drawer to an app, but the most common one is to use the drawer property thats within the Scaffold() Widget.
e.x.
Scaffold(
appBar: AppBar(
...
),
drawer: Drawer() // This is where you call the new Widget(class) that you made the drawer in
body: tabs[currentTab],
);
This is how I understood your question, correct me if I misunderstood it.
This is an example how I used a navigation tab bar in one of my projects.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../../providers/auth.dart';
import '../../../widgets/auth/admin/main_drawer.dart';
import '../../auth/profile_screen.dart';
import '../../home_screen.dart';
import './../projects_screen.dart';
class AdminTabBarScreen extends StatefulWidget {
static const routeName = 'auth-tab-bar-view';
#override
_AdminTabBarScreenState createState() => _AdminTabBarScreenState();
}
class _AdminTabBarScreenState extends State<AdminTabBarScreen>
with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
_tabController = TabController(length: 3, vsync: this);
super.initState();
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
final auth = Provider.of<Auth>(context);
return Scaffold(
// appBar: AppBar(
// title: Text('SHTEGU'),
// ),
extendBody: true,
drawer: MainDrawer(), // this is where I called my drawer
body: Container(
// color: Colors.blueAccent,
child: TabBarView(
children: <Widget>[
HomeScreen(),
ProjectsScreen(),
ProfileScreen(),
// LoginScreen(),
],
controller: _tabController,
),
),
bottomNavigationBar: Container(
padding: EdgeInsets.all(16.0),
child: ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(50.0),
),
child: Container(
color: Colors.black26,
child: TabBar(
labelColor: Color(0xFFC41A3B),
unselectedLabelColor: Colors.white,
labelStyle: TextStyle(fontSize: 13.0),
indicator: UnderlineTabIndicator(
borderSide: BorderSide(color: Colors.black54, width: 0.0),
insets: EdgeInsets.fromLTRB(50.0, 0.0, 50.0, 40.0),
),
//For Indicator Show and Customization
indicatorColor: Colors.black54,
tabs: <Widget>[
Tab(
text: 'Home',
),
Tab(
text: 'Projects',
),
Tab(
text: 'Profile',
),
// Tab(
// text: 'Login',
// ),
],
controller: _tabController,
),
),
),
),
);
}
}
Here is how I called the class above to check if admin
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../screens/auth/admin/admin_tab_bar_screen.dart';
import '../../screens/auth/user_tab_bar_screen.dart';
import '../../providers/auth.dart';
class AuthTabBarScreen extends StatelessWidget {
static const routeName = 'auth-tab-bar-view';
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: Provider.of<Auth>(context, listen: false).isAdmin(),
builder: (context, snapshot) => snapshot.hasData
? snapshot.data
? AdminTabBarScreen()
: UserTabBarScreen()
: CircularProgressIndicator(), // while you're waiting for the data, show some kind of loading indicator
);
}
}
And here is my drawer:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../../screens/auth/admin/register_user_screen.dart';
import '../../../screens/auth/auth_tab_bar_screen.dart';
import '../../../screens/tab_bar_screen.dart';
import '../../../providers/auth.dart';
class MainDrawer extends StatelessWidget {
Widget buildListTile(
String title, IconData icon, Function tapHandler, BuildContext ctx) {
return ListTile(
tileColor: Color(0xffF2F7FB),
selectedTileColor: Theme.of(ctx).accentColor,
leading: Icon(
icon,
size: 26,
color: Theme.of(ctx).primaryColor,
),
title: Text(
title,
style: TextStyle(
fontFamily: 'RobotoCondensed',
fontSize: 16,
fontWeight: FontWeight.bold,
color: Theme.of(ctx).primaryColor,
),
),
onTap: tapHandler,
);
}
#override
Widget build(BuildContext context) {
final authData = Provider.of<Auth>(context, listen: false);
return Drawer(
child: SafeArea(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
buildListTile(
'Home',
Icons.home_rounded,
() {
Navigator.of(context)
.pushReplacementNamed(AuthTabBarScreen.routeName);
},
context,
),
buildListTile(
'Add user',
Icons.person_add_alt_1_rounded,
() {
// Navigator.of(context).pop();
Navigator.of(context)
.pushReplacementNamed(RegisterUserScreen.routeName);
},
context,
),
buildListTile(
'Sign Out',
Icons.exit_to_app_rounded,
() {
authData.signOut();
},
context,
),
],
),
),
),
);
}
}
Hope this is at least of help to you :D

Related

the return type 'future<bool>' isn't a 'Future<bool>', as required by the closure context

I'm building my quiz app and my quizpage is taking solid shape but here's a problem i have. I added a Willpopscope just so that my users can't go back to the beginning when the quiz has started and it brings up a dialog box. Here's the code:
import 'dart:convert';
//import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class GetJson extends StatelessWidget {
const GetJson({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: DefaultAssetBundle.of(context).loadString("assets/python.json"),
builder: (context, snapshot) {
var mydata = jsonDecode(snapshot.data.toString());
if (mydata == null) {
return Scaffold(
body: Center(
child: Text(
"Loading",
),
),
);
} else {
return QuizPage();
}
},
);
}
}
class QuizPage extends StatefulWidget {
QuizPage({Key? key}) : super(key: key);
#override
_QuizPageState createState() => _QuizPageState();
}
class _QuizPageState extends State<QuizPage> {
Widget choicebutton() {
return Padding(
padding: EdgeInsets.symmetric(
vertical: 10.0,
horizontal: 20.0,
),
child: MaterialButton(
onPressed: () {},
child: Text(
"option 1",
style: TextStyle(
color: Colors.white,
fontFamily: "Alike",
fontSize: 16.0,
),
maxLines: 1,
),
color: Colors.indigo,
splashColor: Colors.indigo[700],
highlightColor: Colors.indigo[700],
minWidth: 200.0,
height: 45.0,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
),
);
}
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]);
return WillPopScope(
onWillPop: () {
return showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(
"Quizstar",
),
content: Text("You Can't Go Back At This Stage"),
actions: [
// ignore: deprecated_member_use
FlatButton(onPressed: () {
Navigator.of(context).pop();
},
child: Text(
"Ok",
),
)
],
)
);
},
child: Scaffold(
body: Column(
children: [
Expanded(
flex: 3,
child: Container(
padding: EdgeInsets.all(15.0),
alignment: Alignment.bottomLeft,
child: Text(
"This is a sample question which will be displayed?",
style: TextStyle(
fontSize: 16.0,
fontFamily: "Quando",
),
),
),
),
Expanded(
flex: 6,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
choicebutton(),
choicebutton(),
choicebutton(),
choicebutton(),
],
),
),
),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.topCenter,
child: Center(
child: Text(
"30",
style: TextStyle(
fontSize: 35.0,
fontWeight: FontWeight.w700,
fontFamily: "Times New Roman",
),
),
),
),
),
],
),
),
);
}
}
The error is in the showDialog() but i can't seem to figure it out.
Thanks a lot guys.
This might help
On your willpop scope function do this instead
onWillPop: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(
"Quizstar",
),
content: Text("You Can't Go Back At This Stage"),
actions: [
// ignore: deprecated_member_use
FlatButton(onPressed: () {
Navigator.of(context).pop();
},
child: Text(
"Ok",
),
)
],
)
);
return true;
),
child : your widget
Okay i figured it out
return WillPopScope(
onWillPop: () async {
print("Back Button Pressed");
final shouldPop = await showWarning(context);
return shouldPop ?? false;
},
Then i went ahead to define showWarning like this, then defined my dialog box inside it:
Future<bool?> showWarning(BuildContext context) async => showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: Text("Quizstar"),
content: Text("You cannot go back at this stage"),
actions: [
ElevatedButton(
onPressed: () => Navigator.pop(context, false),
child: Text("Okay"),
),
//ElevatedButton(
// onPressed: () => Navigator.pop(context, true),
// child: Text("Yes"),
//),
],
),
);
Tips: Don't forget to make the future a bool by writing inside it with it's '?'

How to change tab bar color when it tapped

I want to change background color of the tabs when it tapped ?
How can I change the color
I have this test project :
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
backgroundColor: Colors.pink,
bottom: TabBar(
labelColor: Colors.yellow,
indicatorColor: Colors.yellow,
onTap: (index) {
// Should not used it as it only called when tab options are clicked,
// not when user swapped
},
controller: _controller,
tabs: list,
),
title: Text('Tabs Demo'),
),
body: TabBarView(
controller: _controller,
children: List<Widget>.generate(3, (int index){
return Center(
child: Text(index.toString()),
);
}),
),
),
);
You can use the index property of the controller to check which tab is currently active and listen to the controller to know when it changed.
For instance by using an AnimatedBuilder around the Tab widget
These things to consider:
Use tab controller and check indexIsChanging
Wrap text inside Tab with a widget for the color change
Remove labelPadding
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
TabController tabController;
List<Color> tabBackground;
List colors = [Colors.red, Colors.green, Colors.yellow];
Random random = Random();
#override
void initState() {
super.initState();
tabController = TabController(length: 3, vsync: this);
tabBackground = [Colors.blue, Colors.pink, Colors.cyan];
tabController.addListener(() {
if (tabController.indexIsChanging) {
setState(() {
tabBackground[tabController.index] = colors[random.nextInt(3)];
});
}
});
}
#override
void dispose() {
tabController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.pink,
bottom: TabBar(
labelPadding: EdgeInsets.zero,
labelColor: Colors.yellow,
indicatorColor: Colors.black,
controller: tabController,
tabs: [
Tab(
child: Container(
alignment: Alignment.center,
constraints: BoxConstraints.expand(),
color: tabBackground[0],
child: Text(
'Tab 1',
style: TextStyle(
color: Colors.white,
),
),
),
),
Tab(
child: Container(
alignment: Alignment.center,
constraints: BoxConstraints.expand(),
color: tabBackground[1],
child: Text(
'Tab 2',
style: TextStyle(
color: Colors.white,
),
),
),
),
Tab(
child: Container(
alignment: Alignment.center,
constraints: BoxConstraints.expand(),
color: tabBackground[2],
child: Text(
'Tab 3',
style: TextStyle(
color: Colors.white,
),
),
),
),
],
),
title: Text('Tabs Demo'),
),
body: TabBarView(
controller: tabController,
children: List<Widget>.generate(3, (int index) {
return Center(
child: Text(index.toString()),
);
}),
),
);
}
}

Black-Screen with the FlatButton in the AppBar

My App contains basically 2 parts -> Appbar (with 1 Button) and BottomNavigationBar (with some buttons that works properly). The problem came when I pressed the Appbar button (goes to a black screen instead of show the "manual_page.dart")
this is the content of the 2 files (the home_page.dart and manual_page.dart):
home_page.dart
import 'package:flutter/material.dart';
import 'package:opening_a_pdf/manual_page.dart';
import 'package:opening_a_pdf/first_page.dart';
import 'package:opening_a_pdf/second_page.dart';
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _selectedPage = 0;
List<Widget> pageList = List<Widget>();
#override
void initState() {
pageList.add(FirstPage());
pageList.add(SecondPage());
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFFAFAFA),
appBar: AppBar(
backgroundColor: Colors.black,
title: const Text('Aplicación en Desarrollo'),
actions: <Widget>[
FlatButton(
textColor: Colors.white,
child: Text(
'MANUAL',
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
),
),
onPressed: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Voice()),
);
}
)
],
),
body: IndexedStack(
index: _selectedPage,
children: pageList,
),
bottomNavigationBar: BottomNavigationBar(
// type: BottomNavigationBarType.fixed,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
backgroundColor: Colors.black,
icon: Icon(Icons.compare_arrows),
title: Text('Conectividad'),
),
BottomNavigationBarItem(
backgroundColor: Colors.black,
icon: Icon(Icons.blur_on),
title: Text('Captura Datos'),
),
BottomNavigationBarItem(
backgroundColor: Colors.black,
icon: Icon(Icons.graphic_eq),
title: Text('Voz'),
),
BottomNavigationBarItem(
backgroundColor: Colors.black,
icon: Icon(Icons.list),
title: Text('Comandos'),
),
BottomNavigationBarItem(
backgroundColor: Colors.black,
icon: Icon(Icons.settings),
title: Text('Ajustes'),
),
],
currentIndex: _selectedPage,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
void _onItemTapped(int index) {
setState(() {
_selectedPage = index;
});
}
}
manual_page.dart
import 'package:flutter/material.dart';
// ignore: camel_case_types
class Voice extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sección de Órdenes por Voz"),
),
body: Stack(
fit: StackFit.expand,
children: <Widget>[
Positioned(
bottom: 0,
width: MediaQuery.of(context).size.width,
child: Center(
child: MaterialButton(
onPressed: () {},
color: Colors.red,
),
),
)
],
),
);
}
}
Try to initial the height of container in the second screen before Stack
There are no errors in the code. Works correctly. Maybe the fault is in the main () or in the emulator.
Code in main:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
I executed your code and found no problem with it:
But you can put empty Container() as the child of MaterialButton().
Corrected code:
MaterialButton(
onPressed: () {},
color: Colors.red,
child:Container(),
),

How to pass data/Images from one page to another in Bottom Navigation Bar

I wanted to send Data/images from one page to another. In the Homepage when I tap on the add Icon button image should be passed to the Cart page and if the icon is tapped again image is removed from the Cart page. But, the cart page should be accessed from bottom navigation bar.
but it is showing an error called 1 positional argument(s) expected, but 0 found.
Try adding the missing arguments.. when it calls the cart page.
HomePage.dart file
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blueGrey,
),
home: NavBar(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Dish> _dishes = List<Dish>();
List<Dish> _cartList = List<Dish>();
#override
void initState() {
super.initState();
_populateDishes();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 16.0, top: 8.0),
child: GestureDetector(
child: Stack(
alignment: Alignment.topCenter,
children: <Widget>[
Icon(
Icons.shopping_cart,
size: 36.0,
),
if (_cartList.length > 0)
Padding(
padding: const EdgeInsets.only(left: 2.0),
child: CircleAvatar(
radius: 8.0,
backgroundColor: Colors.red,
foregroundColor: Colors.white,
child: Text(
_cartList.length.toString(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 12.0,
),
),
),
),
],
),
onTap: () {
if (_cartList.isNotEmpty)
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Cart(_cartList),
),
);
},
),
)
],
),
body: _buildGridView(),
);
}
ListView _buildListView() {
return ListView.builder(
itemCount: _dishes.length,
itemBuilder: (context, index) {
var item = _dishes[index];
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 2.0,
),
child: Card(
elevation: 4.0,
child: ListTile(
leading: Icon(
item.icon,
color: item.color,
),
title: Text(item.name),
trailing: GestureDetector(
child: (!_cartList.contains(item))
? Icon(
Icons.add_circle,
color: Colors.green,
)
: Icon(
Icons.remove_circle,
color: Colors.red,
),
onTap: () {
setState(() {
if (!_cartList.contains(item))
_cartList.add(item);
else
_cartList.remove(item);
});
},
),
),
),
);
},
);
}
GridView _buildGridView() {
return GridView.builder(
padding: const EdgeInsets.all(4.0),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemCount: _dishes.length,
itemBuilder: (context, index) {
var item = _dishes[index];
return Card(
elevation: 4.0,
child: Stack(
fit: StackFit.loose,
alignment: Alignment.center,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
item.icon,
color: (_cartList.contains(item))
? Colors.grey
: item.color,
size: 100.0,
),
Text(
item.name,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subhead,
)
],
),
Padding(
padding: const EdgeInsets.only(
right: 8.0,
bottom: 8.0,
),
child: Align(
alignment: Alignment.bottomRight,
child: GestureDetector(
child: (!_cartList.contains(item))
? Icon(
Icons.add_circle,
color: Colors.green,
)
: Icon(
Icons.remove_circle,
color: Colors.red,
),
onTap: () {
setState(() {
if (!_cartList.contains(item))
_cartList.add(item);
else
_cartList.remove(item);
});
},
),
),
),
],
));
});
}
void _populateDishes() {
var list = <Dish>[
Dish(
name: 'Chicken Zinger',
icon: Icons.fastfood,
color: Colors.amber,
),
Dish(
name: 'Chicken Zinger without chicken',
icon: Icons.print,
color: Colors.deepOrange,
),
Dish(
name: 'Rice',
icon: Icons.child_care,
color: Colors.brown,
),
Dish(
name: 'Beef burger without beef',
icon: Icons.whatshot,
color: Colors.green,
),
Dish(
name: 'Laptop without OS',
icon: Icons.laptop,
color: Colors.purple,
),
Dish(
name: 'Mac wihout macOS',
icon: Icons.laptop_mac,
color: Colors.blueGrey,
),
];
setState(() {
_dishes = list;
});
}
}
Cart.dart file
import 'package:flutter/material.dart';
import 'dish_object.dart';
class Cart extends StatefulWidget {
final List<Dish> _cart;
Cart(this._cart);
#override
_CartState createState() => _CartState(this._cart);
}
class _CartState extends State<Cart> {
_CartState(this._cart);
List<Dish> _cart;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Cart'),
),
body: ListView.builder(
itemCount: _cart.length,
itemBuilder: (context, index) {
var item = _cart[index];
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 2.0),
child: Card(
elevation: 4.0,
child: ListTile(
leading: Icon(
item.icon,
color: item.color,
),
title: Text(item.name),
trailing: GestureDetector(
child: Icon(
Icons.remove_circle,
color: Colors.red,
),
onTap: () {
setState(() {
_cart.remove(item);
});
},
),
),
),
);
},
),
);
}
}
NavBar.dart file
import 'package:flutter/material.dart';
import 'package:sharewallpaper/cart.dart';
import 'package:sharewallpaper/main.dart';
class NavBar extends StatefulWidget {
#override
_NavBarState createState() => _NavBarState();
}
class _NavBarState extends State<NavBar> {
int _currentIndex = 0;
final List<Widget> _children = [
MyHomePage(),
Cart(), ** This line is throwing an error **
];
void onTappedBar(int index) {
setState(() {
_currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTappedBar,
currentIndex: _currentIndex,
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('Home')),
BottomNavigationBarItem(
icon: Icon(Icons.bookmark), title: Text('BookMark')),
],
),
);
}
}
Yep, it will throw an error because the constructor of the Cart class is expecting one parameter to be passed in. You could use a named constructor instead like this:
class Cart extends StatefulWidget {
final List<Dish> _cart;
Cart(this._cart);
That way, you can call it like so:
Cart(cart: _cartList),
But if you actually need the cart list, I would recommend that you write a provider to keep track of the cart data across screens.

Changing animation state in bottom navigation bar while clicking back button

I have used this bottom navigation bar library in my app and it works perfectly. But i want to maintain a back navigation with the back button in android phones like for example in the Google Play Store bottom navigation where if we navigate through the bottom navigation the animation changes and also if we navigate back through the back button the animation changes the way before.
I have tried this article which is somewhat doing what i want but the animations are not working.
This is my stateful widget where my bottom nav bar is,
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int currentIndex;
final PageStorageBucket bucket = PageStorageBucket();
#override
void initState() {
// TODO: implement initState
super.initState();
currentIndex = 0;
}
void changePage(int index) {
setState(() {
currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey.shade300,
resizeToAvoidBottomInset : false,
body:
new Stack(
children: <Widget>[
new Offstage(
offstage: currentIndex != 0,
child: new TickerMode(
enabled: currentIndex == 0,
child: new MaterialApp(home: new HomePage()),
),
),
new Offstage(
offstage: currentIndex != 1,
child: new TickerMode(
enabled: currentIndex == 1,
child: new MaterialApp(home: new StayPage()),
),
),
new Offstage(
offstage: currentIndex != 2,
child: new TickerMode(
enabled: currentIndex == 2,
child: new MaterialApp(home: new TravelPage()),
),
),
new Offstage(
offstage: currentIndex != 3,
child: new TickerMode(
enabled: currentIndex == 3,
child: new MaterialApp(home: new MorePage()),
),
),
],
),
floatingActionButton: Visibility(
visible: _isVisible,
child: Container(
height: 100.0,
width: 85.0,
// margin: EdgeInsets.only(bottom: 5.0),
child: FittedBox(
child: FloatingActionButton.extended(
onPressed: () {
setState(() {});
},
elevation: 20.0,
icon: Icon(Icons.add),
label: Text(
"Plan",
style: TextStyle(
fontFamily: "OpenSansBold",
),
),
backgroundColor: Colors.red,
),
),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
bottomNavigationBar: Visibility(
visible: _isVisible,
child: BubbleBottomBar(
hasInk: true,
fabLocation: BubbleBottomBarFabLocation.end,
opacity: .2,
currentIndex: currentIndex,
onTap: changePage,
elevation: 15,
items: <BubbleBottomBarItem>[
BubbleBottomBarItem(
backgroundColor: Colors.red,
icon: Icon(
Icons.home,
color: Colors.black,
),
activeIcon: Icon(
Icons.home,
color: Colors.red,
),
title: Text(
"Home",
style: TextStyle(
fontFamily: "OpenSans",
),
)),
BubbleBottomBarItem(
backgroundColor: Colors.deepPurple,
icon: Icon(
Icons.hotel,
color: Colors.black,
),
activeIcon: Icon(
Icons.hotel,
color: Colors.deepPurple,
),
title: Text(
"Stay",
style: TextStyle(
fontFamily: "OpenSans",
),
),
),
BubbleBottomBarItem(
backgroundColor: Colors.indigo,
icon: Icon(
Icons.card_travel,
color: Colors.black,
),
activeIcon: Icon(
Icons.card_travel,
color: Colors.indigo,
),
title: Text(
"Travel",
style: TextStyle(
fontFamily: "OpenSans",
),
),
),
BubbleBottomBarItem(
backgroundColor: Colors.green,
icon: Icon(
Icons.more,
color: Colors.black,
),
activeIcon: Icon(
Icons.more,
color: Colors.green,
),
title: Text(
"More",
style: TextStyle(
fontFamily: "OpenSans",
),
),
),
],
),
),
);
}
}
It is not necessary that i have to use this library, i just want to implement a bottom navigation bar and when navigating back through using the android back button the animations must work.
Any kind of help would be appreciated! Thanks!
Solved my problem. I used the medium post by Swav Kulinski which i pointed out in my question earlier.
The code is as follows,
class NavBar extends StatefulWidget {
#override
_NavBarState createState() => _NavBarState();
}
class _NavBarState extends State<NavBar> {
final navigatorKey = GlobalKey<NavigatorState>();
int currentIndex;
final PageStorageBucket bucket = PageStorageBucket();
#override
void initState() {
// TODO: implement initState
super.initState();
currentIndex = 0;
}
void changePage(int index) {
navigatorKey.currentState.pushNamed(pagesRouteFactories.keys.toList()[index]);
setState(() {
currentIndex = index;
});
}
Future<bool> _onWillPop() {
if(currentIndex == 3){
changePage(2);
} else if(currentIndex == 2){
changePage(1);
} else if(currentIndex == 1){
changePage(0);
} else if(currentIndex == 0){
return Future.value(false);
}
return Future.value(true);
}
final pagesRouteFactories = {
"/": () => MaterialPageRoute(
builder: (context) => Center(
child: Text("HomePage",style: Theme.of(context).textTheme.body1,),
),
),
"takeOff": () => MaterialPageRoute(
builder: (context) => Center(
child: Text("Take Off",style: Theme.of(context).textTheme.body1,),
),
),
"landing": () => MaterialPageRoute(
builder: (context) => Center(
child: Text("Landing",style: Theme.of(context).textTheme.body1,),
),
),
"settings": () => MaterialPageRoute(
builder: (context) => Center(
child: Text("Settings",style: Theme.of(context).textTheme.body1,),
),
),
};
#override
Widget build(BuildContext context) {
return MaterialApp(
home: WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
body: _buildBody(),
bottomNavigationBar: _buildBottomNavigationBar(context),
),
),
);
}
Widget _buildBody() =>
MaterialApp(
navigatorKey: navigatorKey,
onGenerateRoute: (route) => pagesRouteFactories[route.name]()
);
Widget _buildBottomNavigationBar(context) => BottomNavigationBar(
items: [
_buildBottomNavigationBarItem("Home", Icons.home),
_buildBottomNavigationBarItem("Take Off", Icons.flight_takeoff),
_buildBottomNavigationBarItem("Landing", Icons.flight_land),
_buildBottomNavigationBarItem("Settings", Icons.settings)
],
currentIndex: currentIndex,
onTap: changePage,
);
_buildBottomNavigationBarItem(name, icon) => BottomNavigationBarItem(
icon: Icon(icon),
title: Text(name),
backgroundColor: Colors.black45,
activeIcon: Icon(icon)
);
}
I do not know if this is the right approach though. If anyone want to suggest me better option please let me know.

Categories

Resources