Flutter global BottomAppBar with different AppBars in each Page - android

I want a global BottomAppBar which I want to define in my MaterialApp.
My current MaterialApp:
return MaterialApp(
initialRoute: '/overview',
routes: {
'/overview': (context) => OverViewPage(),
'/summary': (context) => SummaryPage(),
'/record': (context) => RecordPage(""),
'/calendar': (context) => Calendar(),
'/piechart': (context) => PieChartPage()
},
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: lightTheme,
home: OverViewPage(),
);
In every Route is a own Scaffold because I need to specify my AppBar actions and the FloatingActionButton individually for each page. But when I wrap the home in a Scaffold and make the body of the Scaffold to each page, I have two Scaffolds stacked in each other, which is not possible.
So basically I need an BottomAppBar in my Material App, but need to override the AppBar and the FloatingActionButton in each page.

You have to have a common screen that has BottomAppBar and doesn't declare its child pages into routes, then you can declare Appbar on each of child page.
For ex,
class BottomNavigation extends StatelessWidget{
// add child pages in _widgetOptions
static List<Widget> _widgetOptions = <Widget>[
FeedTab(),
ChatTab(),
Marketplace(),
Profile(),
];
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
child: Scaffold(
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
showUnselectedLabels: true,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.menu),
title: Text(
'Feed',
style: tabTextStyle,
),
),
BottomNavigationBarItem(
icon: Icon(Icons.forum),
title: Text('Chat', style: tabTextStyle),
),
BottomNavigationBarItem(
icon: Icon(Icons.explore),
title: Text('Market Place', style: tabTextStyle),
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
title: Text('My Profile', style: tabTextStyle),
),
],
// type: BottomNavigationBarType.fixed,
currentIndex: _selectedIndex,
unselectedItemColor: AppColors.colorHint,
selectedItemColor: AppColors.themeColor,
onTap: _onItemTapped,
),
),
),
if (!isConnectedToInternet)
_showInternetStatus('No Internet Connection', AppColors.colorRed),
// if (isConnectedToInternet && isConnectionWidgetVisible)
// _showInternetStatus('Connected to Internet', AppColors.colorGreen)
],
);
}
}
Then you can have Appbar on each page like this,
class FeedTab extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.person_pin),
onPressed: () {
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text("My Followers Post")));
},
),
.......

Related

Can't change color of a "Leading Icon" of a ListTile in Flutter

I have a Drawer with a ListView, inside that I have the ListTiles. In every ListTile there is a leading element, the Icon. I want to change the color of all Icons inside ListTiles from my ThemeData. I tried however it doesn't work.
Here is my current code (the class only):
class _UniversalConverter extends State<UniversalConverter> {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
iconTheme: const IconThemeData(color: Colors.blue),
),
home: Scaffold(
appBar: AppBar(
title: const Text("Universal Converter"),
),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
child: Text('Drawer Header'),
),
ListTile(
title: const Text('Home'),
leading: const Icon(Icons.home),
onTap: () {},
),
ListTile(
title: const Text('Angle'),
leading: const Icon(Icons.block),
onTap: () {},
),
],
),
),
));
}
}
As you can see I have the iconTheme: const IconThemeData(color: Colors.blue), but it doesn't do anything.
Any help would be appreciated,
Thanks!
Try using ListTileTheme
listTileTheme: ListTileThemeData(
iconColor: Colors.blue
),
or
ListTile(
title: const Text('Angle'),
leading: const Icon(Icons.block, color: Theme.of(context).iconTheme.color),
onTap: () {},
),
Icon itself having a property called color. Consider below code snippet.
ListTile(
title: Text('Hi'),
leading: Icon(Icons.block,
color : Colors.orange,
),
onTap: () {
// To do
},
),

How to get Bottom Navigation Functionality with FAB in Flutter

I have this design where when we open the app, it first goes to the Home Screen by default and I have two Bottom Navigation Bar Items.
I am unable to get it working because I want it to behave how Bottom Navigation Bar works but I want default screen to be the home. And when you click on Cart or Profile, it should highlight that tab but when you click on home, it should remove highlighting from it.
Here is a simple workaround or try search for bottomnavigation packages
check this persistent_bottom_nav_bar pacakge it allows to show bottom navigation in all pages with navigator,In other packages you have to do it yourself all the things.
if you want use persistent_bottom_nav_bar check this example for persistent_bottom_nav_bar
Top 16 Flutter Navigation Libraries
flutter-bottomappbar-navigation-with-fab
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
appBar: AppBar(title: Text('Title')),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton:
FloatingActionButton(child: Icon(Icons.add), onPressed: () {}),
bottomNavigationBar: BottomAppBar(
shape: CircularNotchedRectangle(),
child: Container(
height: 56,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(icon: Icon(Icons.home), onPressed: () {}),
IconButton(icon: Icon(Icons.search), onPressed: () {}),
SizedBox(width: 40), // The dummy child
IconButton(icon: Icon(Icons.notifications), onPressed: () {}),
IconButton(icon: Icon(Icons.message), onPressed: () {}),
],
),
)),
),
);
}
}
you can try with this persistent_bottom_nav_bar
Here is the Code for Bottom TabBar in Flutter
class TabView extends StatefulWidget {
const TabView({Key? key}) : super(key: key);
#override
_TabViewState createState() => _TabViewState();
}
class _TabViewState extends State<TabView> with SingleTickerProviderStateMixin {
late TabController tabController;
#override
void initState() {
super.initState();
// TODO: CHANGE LENGTH
tabController = TabController(length: 2, vsync: this);
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
tabController.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: Container(
height: 50,
child: TabBar(
unselectedLabelColor: Colors.grey,
labelColor: kPrimaryColor,
indicatorColor: kPrimaryColor,
labelStyle: TextStyle(fontSize: 11, fontWeight: FontWeight.w500),
tabs: [
Tab(
icon: Icon(Icons.home, size: 25.0,),
text: "Tab1",
iconMargin: EdgeInsets.zero,
),
Tab(
icon: Icon(Icons.person, size: 25.0),
text: "Tab2",
iconMargin: EdgeInsets.zero,
),
],
controller: tabController,
),
),
body: TabBarView(
controller: tabController,
children: [
Tab1(),
Tab2()
],
),
);
}
}

Flutter : Staying inside wrapper when navigating with AppBar

I have a bottom navigation bar, that lets me navigate between pages, while keeping the Bottom Navigation bar in place (Using Persistent Bottom Navigation bar package)
I also want to have a extra navigation button, that sends me to another page not listed on the Bottom Navigation bar, but all the different ways I have tried, it pushes me to another page, that is not inside the wrapper.
How could I navigate to another page from AppBar (Page is not listed on the bottom navigation bar) without losing the Navigation bar?
Attatching wrapper code
class Wrapper extends StatefulWidget {
final BuildContext menuScreenContext;
Wrapper({Key key, this.menuScreenContext}) : super(key: key);
#override
_WrapperState createState() => _WrapperState();
}
class _WrapperState extends State<Wrapper> {
final AuthService _auth = AuthService();
PersistentTabController _controller;
bool _hideNavBar;
#override
void initState() {
super.initState();
_controller = PersistentTabController(initialIndex: 0);
_hideNavBar = false;
}
List<Widget> _buildScreens() {
return [
HomePage(
hideStatus:_hideNavBar,
),
Page1(),
Page2(),
Page3(),
Page4(
hideStatus:_hideNavBar,
),
];
}
List<PersistentBottomNavBarItem> _navBarsItems() {
return [
PersistentBottomNavBarItem(
icon: Icon(Icons.home),
title: "Home",
activeColor: Colors.blue,
inactiveColor: Colors.grey,
),
PersistentBottomNavBarItem(
icon: Icon(Icons.search),
title: ("Search"),
activeColor: Colors.teal,
inactiveColor: Colors.grey,
),
PersistentBottomNavBarItem(
icon: Icon(Icons.add),
title: ("Add"),
activeColor: Colors.deepOrange,
inactiveColor: Colors.grey,
),
PersistentBottomNavBarItem(
icon: Icon(Icons.settings),
title: ("Settings"),
activeColor: Colors.indigo,
inactiveColor: Colors.grey,
),
PersistentBottomNavBarItem(
icon: Icon(Icons.settings),
title: ("Settings"),
activeColor: Colors.indigo,
inactiveColor: Colors.grey,
),
];
}
#override
Widget build(BuildContext context)
{
final user = Provider.of<NUser>(context);
if(user==null){
return Authenticate();}
else {
return Scaffold
(
drawer: Drawer(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>
[
TextButton
(child:Text('hey'), onPressed: ()
{
pushNewScreenWithRouteSettings(
context,
settings: RouteSettings(name:'/home'),
screen: HomePage());
}
),
ElevatedButton.icon(
onPressed: () async {await _auth.signOut();},
icon: Icon(Icons.person),
label: Text('Logout'),
),
],
),
),
),
appBar: AppBar(
actions: [
IconButton(iconSize: 150,icon: Image.asset("assets/BUTTON.png", color: Colors.black,height: 1000,width: 1000,), onPressed: ()
{
Navigator.push(context, MaterialPageRoute(builder: (context) => Profile()));
}),
ButtonTheme(
minWidth: 100.0,
height: 100.0,
child: TextButton(
onPressed: () {},
child: Text(" 4444 "),
),
),
],
),
body: PersistentTabView.custom
(
context,
controller: _controller,
screens: _buildScreens(),
confineInSafeArea: true,
itemCount: 5,
handleAndroidBackButtonPress: true,
resizeToAvoidBottomInset: false,
stateManagement: true,
hideNavigationBar: _hideNavBar,
screenTransitionAnimation: ScreenTransitionAnimation(
animateTabTransition: true,
curve: Curves.ease,
duration: Duration(milliseconds: 200),
),
customWidget: CustomNavBarWidget
(
items: _navBarsItems(),
onItemSelected: (index) {
setState(() {
_controller.index = index; // THIS IS CRITICAL!! Don't miss it!
});
},
selectedIndex: _controller.index,
),
),
);
}
}
}
class Profile extends StatefulWidget {
Profile({Key key}): super(key: key);
#override
_ProfileState createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:Text('sample'),
),
);
}
}
I tried creating a class for the page in wrapper, but no luck. Other pages are individual files. I am trying to navigate with the AppBar Button

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(),
),

Flutter navigate to page with default Material Drawer

What is the best why to navigate to a page in flutter using the default Material Drawer.
I'm still learning how to work with Flutter.
In Android we used to anvigate to a fragment page, but how does this work in Flutter ?
I just want to understand how to navigate to an drawer item without without using bloc's.
class MdDrawer extends StatelessWidget {
final String title;
MdDrawer({Key key, this.title}) : super(key: key);
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Text('MyPage'),
),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
UserAccountsDrawerHeader(
accountName: const Text(_AccountName),
accountEmail: const Text(_AccountEmail),
currentAccountPicture: CircleAvatar(
backgroundColor: Colors.brown,
child: Text(_AccountAbbr),
),
),
ListTile(
leading: Icon(Icons.lightbulb_outline),
title: Text('Notes'),
onTap: () => _alertOnListTileTap(context),
),
Divider(),
...
],
),
),
);
}
_alertOnListTileTap(BuildContext context) {
Navigator.of(context).pop();
showDialog(
context: context,
child: AlertDialog(
title: const Text('Not Implemented'),
actions: <Widget>[
FlatButton(
child: const Text('OK'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
);
}
}
Doing this without using bloc will make your code difficult to manage as it scales unless you just need an app prototype without any business logic.
Nonetheless, you can do it without bloc as follows;
Place all you screen in the body: as a list which displays the appropriate screen by indexing. like
body: [
Expenses(),
Inspiration()
Personal(),
Work(),
More(),
].elementAt(selectedIndex),
drawer: MdDrawer(onTap: (int val){
setState(() {
this._selectedIndex=val;
});
}
,)
Now you can push the desired body to display by providing the index as the return value of the Navigator.of(context).pop(index) or a callback function into MdDrawer. We will to do the callback function method. The index return will be used to update the state using setState.
class MdDrawer extends StatelessWidget {
final String title; final Function onTap;
MdDrawer({Key key, this.title, this.onTap}) : super(key: key);
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Text('MyPage'),
),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
UserAccountsDrawerHeader(
accountName: const Text(_AccountName),
accountEmail: const Text(_AccountEmail),
currentAccountPicture: CircleAvatar(
backgroundColor: Colors.brown,
child: Text(_AccountAbbr),
),
),
ListTile(
leading: Icon(Icons.lightbulb_outline),
title: Text('Notes'),
onTap: () => _alertOnListTileTap(context, 0),
),
ListTile(
leading: Icon(Icons.lightbulb_outline),
title: Text('Expenses'),
onTap: () => _alertOnListTileTap(context, 1),
),
Divider(),
...
],
),
),
);
}
_alertOnListTileTap(BuildContext context, int index ) {
onTap(indext);
Navigator.of(context).pop();
}
}
I hope this helps

Categories

Resources