a different navigation bar in flutter - android

Is it possible for me to open a page with icons when I click on the place I drew in red in the picture, like the bottomnavbar on Instagram, but I want mine to be like in the picture

What you have to do is:
add a drawer to your scaffold
add a GlobalKey to your Widget which you will use to open the Drawer
Remove the AppBar Menu button if you don't want it there
Add a the button and Position it in your body
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final appTitle = 'Drawer Demo';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: appTitle,
home: MyHomePage(title: appTitle),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
//Add GlobalKey which you will use to open the drawer
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
MyHomePage({Key? key, required this.title}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
//Set GlobalKey
key: _scaffoldKey,
appBar: AppBar(title: Text(title),
//This will remove the AppBar menu button
automaticallyImplyLeading: false,),
body:
Center(child:
Container(
width: double.infinity,
alignment: Alignment.centerLeft,
child: InkWell(
//This function will open the Side Menu
onTap: ()=> _scaffoldKey.currentState?.openDrawer()
,
child: Icon(
Icons.menu,
size: 20,
),
),
),
),
//Add Drawer to your Scaffold
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Text('Drawer Header'),
),
ListTile(
title: Text('Item 1'),
onTap: () {
Navigator.pop(context);
},
),
ListTile(
title: Text('Item 2'),
onTap: () {
Navigator.pop(context);
},
),
],
),
),
);
}
}

Related

Duplicate GlobalKey detected in widget tree - The key [LabeledGlobalKey<ScaffoldMessengerState>#ab7de] was used by multiple widgets

I am creating TabBar using Getx but getting the error Duplicate GlobalKey detected in the widget tree. So whenever I am going to the second Tab app doesn't show any content. How I solve the issue whenever I am using stateful widget it works but whenever trying Getx to create the TabBar using the stateless widget.
TabBar Class:
class Page2 extends StatelessWidget {
const Page2({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final GetxTab getxTab = Get.put(GetxTab());
return MaterialApp(
home: Scaffold(
appBar: AppBar(
bottom: TabBar(
controller: getxTab.tabController,
tabs: getxTab.appTabs,
),
),
body: TabBarView(controller: getxTab.tabController, children: [
PageTabs1(),
GetxExample(),
])),
);
}
}
class GetxTab extends GetxController with SingleGetTickerProviderMixin {
late TabController tabController;
final List<Tab> appTabs = <Tab>[
Tab(
icon: Icon(
Icons.share,
),
text: ("Bottom Sheet")),
Tab(
icon: Icon(
Icons.share,
),
text: ("Getx")),
];
#override
void onInit() {
// TODO: implement onInit
super.onInit();
tabController = TabController(length: appTabs.length, vsync: this);
}
#override
void onClose() {
// TODO: implement onClose
super.onClose();
tabController.dispose();
}
}
First Page:
Updated: Problem solved I just figure out I make a mistake adding GetMaterialApp, Scaffold
both of my Parent and child class. Which conflicts one with another.
So I just remove the child GetMaterialApp( home: Scaffold(
class PageNav3 extends StatelessWidget {
const PageNav3({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.center,
child: Text(
"Nav1",
style: TextStyle(color: Colors.red),
),
),
);
}
}
Second Page:
This page causes the Issue
class GetxExample extends StatelessWidget {
GetxExample({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
bool value = true;
return GetMaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: GestureDetector(
child: Container(
width: double.infinity,
height: 45,
child: My_Button(
ButtonText: "Change",
Backcolors: Colors.black,
FontColors: Colors.white,
padBot: 5,
padTop: 5,
padRight: 5,
padLeft: 5),
),
onTap: () {
value = !value;
Get.bottomSheet(
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
color: Colors.blueGrey,
),
child: Wrap(
children: [
AddListTittle(
Tittle: "Camera",
des: "Add Photo by clicking Camera",
iconss: Icons.camera,
Index: 0,
reqIndex: ImageSource.camera,
),
AddListTittle(
Tittle: "Gallery",
des: "Add Photo from Gallery",
iconss: Icons.storage,
Index: 1,
reqIndex: ImageSource.gallery,
),
],
),
),
);
},
),
),
),
);
}
}
If you are using the scaffold keys to display snackbar, remove them and use the overlay support package, it offers a simpler implementation

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

How to open this type of alert dialog in flutter

I wanted to show dialog in my application. How can i achieve this using flutter
You can use a PopupMenuButton (https://api.flutter.dev/flutter/material/PopupMenuButton-class.html) to achieve this in flutter.
See example code below:
PopupMenuButton<int>(
itemBuilder: (context) => [
const PopupMenuItem(
value: 1,
child: Center(
child: Icon(
Icons.download_outlined,
size: 30.0,
),
),
),
const PopupMenuItem(
value: 2,
child: Center(
child: Icon(
Icons.link,
size: 30.0,
),
),
),
const PopupMenuItem(
value: 2,
child: Center(
child: Icon(
Icons.share,
size: 30.0,
),
),
),
],
icon: const Icon(
Icons.more_horiz,
size: 40.0,
),
offset: const Offset(150, -150),
);
The above example popups a list of Icons when the PopupMenuButton is pressed.
You can adapt this to your use-case above.
Finally I found a Solution thanks enfinity. Here how i solve the problem.
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: new MyHomePage(),
);
}
}
/// An arbitrary widget that lives in a popup menu
class PopupMenuWidget<T> extends PopupMenuEntry<T> {
const PopupMenuWidget({ Key key, this.height, this.child }) : super(key: key);
#override
final Widget child;
#override
final double height;
#override
bool get enabled => false;
#override
_PopupMenuWidgetState createState() => new _PopupMenuWidgetState();
}
class _PopupMenuWidgetState extends State<PopupMenuWidget> {
#override
Widget build(BuildContext context) => widget.child;
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
actions: <Widget>[
new PopupMenuButton<String>(
onSelected: (String value) {
print("You selected $value");
},
itemBuilder: (BuildContext context) {
return [
new PopupMenuWidget(
height: 40.0,
child: new Row(
children: [
IconButton(
icon: Icon(
Icons.remove,
color: Colors.green,
),
onPressed: () {
print("Remove");
}),
Text("1"),
IconButton(
icon: Icon(
Icons.add,
color: Colors.green,
),
onPressed: () {
print("Add");
}),
],
),
),
];
}
),
],
),
);
}
}

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