how to put icons in drawer flutter - flutter

i want to put icons in the left hand side of drawer's children like this photo
is there any specific widgets to do something like this?
my drawer code is this
Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text('Drawer Header'),
decoration: BoxDecoration(
color: Colors.blue,
),
),
ListTile(
title: Text('forms'),
onTap: () { //and rest of the code

Use leading property of ListTile widget to add an Icon.
ListTile(
onTap: () {},
leading: Icon(Icons.add),
title: Text('Add'),
);

Related

Flutter - Overlay drawer icon over WebView

I want to show the drawer icon in front of the WebView page with no AppBar.
Here is my Implementation so far:
Scaffold(
body: const SafeArea(
child: WebView(
initialUrl: "https://sohozeto.com/",
javascriptMode: JavascriptMode.unrestricted)),
drawer: Drawer(
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
decoration: BoxDecoration(
color: Colors.transparent,
),
child: Text('Drawer Header'),
),
ListTile(
title: const Text('Item 1'),
onTap: () {},
),
ListTile(
title: const Text('Item 2'),
onTap: () {
// Update the state of the app.
// ...
},
),
],
),
),
);
for the overlay, use a Stack
const SafeArea(
child:
Stack(children: [
..., // Webview, etc.
Icon(your_icon),
])

Add a main drawer to a button in flutter

I am new to flutter and I need to add the main drawer of the app to a button as you can see in the below picture(This is the upper section of the UI of the app)
Any ideas of having the main drawer apply to a button instead of having it normally assign it to the app bar. (This mobile app doesn't have an app bar)
#override
Widget build(BuildContext context) {
var mediaQuery = MediaQuery.of(context);
return Scaffold(
key: scaffoldKey,
body: Stack(
children: <Widget>[
_buildWidgetAlbumCover(mediaQuery),
getMainContentWidget(mediaQuery),
_buildWidgetMenu(mediaQuery),
_buildWidgetFloatingActionButton(mediaQuery),
Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text('Drawer Header'),
decoration: BoxDecoration(
color: Colors.blue,
),
),
ListTile(
title: Text('Item 1'),
onTap: () {
},
),
ListTile(
title: Text('Item 2'),
onTap: () {
},
),
],
),
),
],
),
);
}
Widget _buildWidgetMenu(MediaQueryData mediaQuery) {
return Padding(
padding: EdgeInsets.only(
left: 2.0,
top: mediaQuery.padding.top + 2.0,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
Icons.menu,
color: Colors.white,
size: 25,
),
padding: EdgeInsets.all(2.0),
// onPressed: () => scaffoldKey.currentState.openDrawer(),
),
],
),
);
}
enter image description here
This is output which I get after having this code. This drawer can't even change or as it is fixed one. I want the normal drawer which is also attached to the _buildWidgetMenu instead of the app bar drawer.
If youre using a sacffold it has a drawer property that you can make use of eg cookbook
return Scaffold(
appBar: AppBar(title: Text(title)),
body: Center(child: Text('My Page!')),
drawer: Drawer(...
opening your drawer from button clicks
var scaffoldKey = GlobalKey<ScaffoldState>();
//required key
Scaffold(
key: scaffoldKey,
drawer: new Drawer(
child: new ListView(
padding: EdgeInsets.zero,...
body:Center(..
IconButton(
icon: Icon(Icons.menu),
//open drawer
onPressed: () => scaffoldKey.currentState.openDrawer(),
),

Flutter Scrollable navigation drawer with one menu item aligned to the bottom

I have a navigation drawer with a bunch of items and I want the logout item aligned to the very bottom of the drawer.
return Drawer(
child: Column(
children: [
DrawerAccountHeader(UserType.worker),
DrawerNavigationItem(
"Home",
Icons.home,
),
new ListTile(
title: new Text('Jobs', style: TextStyle(color: Colors.black54),),
dense: true,
),
DrawerNavigationItem(
"Nearby",
Icons.location_on,
),
DrawerNavigationItem(
"Applied",
Icons.check_circle_outline,
),
DrawerNavigationItem(
"Hired",
Icons.check_circle,
),
Expanded(child: Container()),
Divider(),
DrawerNavigationItem(
"Logout",
Icons.exit_to_app,
)
],
),
);
But on smaller screen I get overflow error because that topmost column height is bigger than screen height. So I tried changing the column to a ListBox and then I get an exception "Vertical viewport was given unbounded height", because I have the Expanded() in between the items to make that gap so that Login buttons sticks to the bottom of the list.
Is there any way to achieve below?
Have the login button (and possibly a group of buttons) stick to the bottom of the screen when there's vertical space.
Make the drawer item scrollable when there's not enough vertical space.
(nice to have) The scrollable, the entire drawer can be scrolled. I.e. on a small screen the user will need to scroll the drawer to get to the logout option.
Try this,
Drawer(
child: LayoutBuilder(
builder: (context, constraint) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraint.maxHeight),
child: IntrinsicHeight(
child: Column(
children: <Widget>[
DrawerHeader(
margin: EdgeInsets.all(0.0),
child: Center(
child: Text("Header"),
),
),
ListTile(
leading: Icon(Icons.home),
title: Text("Home"),
onTap: () {},
),
new ListTile(
title: new Text(
'Jobs',
style: TextStyle(color: Colors.black54),
),
dense: true,
),
ListTile(
leading: Icon(Icons.location_on),
title: Text("Nearby"),
onTap: () {},
),
ListTile(
leading: Icon(Icons.check_circle_outline),
title: Text("Applied"),
onTap: () {},
),
ListTile(
leading: Icon(Icons.check_circle),
title: Text("Hired"),
onTap: () {},
),
const Expanded(child: SizedBox()),
const Divider(height: 1.0, color: Colors.grey),
ListTile(
leading: Icon(Icons.exit_to_app),
title: Text("Logout"),
onTap: () {},
)
],
),
),
),
);
},
),
)
Use the Align widget to position bottom
Align(
alignment: Alignment.bottomCenter, //you can set it as per your requirement
child: Container(
child: Image.asset(
"assets/drawerCycleImage.png", //or Text widget or More Any
)),
#override
Widget build(BuildContext context) {
return Scaffold(
appBar:AppBar(
title:Text('Title')),
drawer:Drawer(
child:Stack(
children:[
ListView(
shrinkWrap:true,
children: List.generate(25,(ind){
//SizedBox is to remain space for logout button !
return ind==25 ?
SizedBox(height:60)
: ListTile(title:Text('Item $ind'));
})
),
Align(
alignment:Alignment.bottomCenter,
child: Container(
height:60,
color:Colors.black,
child: ListTile(
leading:Icon(Icons.exit_to_app),
title:Text('Logout')
),
),
)
]
)
),
body: Container(
alignment:Alignment.center,
child: Text('Hello !')
),
);
}

How to make onTap only respond on Actual Text not whole ListTile width

Illustrations
I have the following problem:
The title and subtitle components of ListTile expand fully even when there only is text in some smaller area.
Usually, this is not a problem as you could just color the background of the title the same as the ListTie.
However, I have a problem when trying to get an onTap event working on a Row in title or subtitle:
As you can see, I have a Row in the title component with an Icon and a Text. That works fine, however, trying to add an onTap to this title will produce unwanted behavior.
I only want the onTap to trigger when I actually tap the text or icon and not when I tap somewhere else to the right. I am clueless how I would constrain the width of the title to the width of the text plus icon. It seems like nothing works. What is going on here?
Code
I created a Gist with the source code (minimal reproducible example) for both illustrations. This should help to give you an idea of the setup.
How do I only trigger onTap when the actual children of the Row are tapped and not the whole title area that apparently expands no matter what I do?
Notes
I could probably just add an InkWell to both the Text and the Icon individually, however, that is not at all what I want because I want a splash (InkWell's splash) to cover the title and icon together and they should not be visually seperated.
Please, try this code it works for me
import 'package:flutter/material.dart';
main() {
runApp(
MaterialApp(
home: Scaffold(
body: Center(
child: Container(
color: Colors.greenAccent,
child: ListTile(
dense: true,
leading: Material(child: const Text('leading')),
title: Material(
child: Row(
children: <Widget>[
InkWell(
onTap: () {},
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(Icons.format_align_left),
Text(
'title',
),
],
),
),
Container(
height: 0.0,
),
// Expanded(child: Container(
// height: 10.0,
// ),)
],
),
),
subtitle: Material(child: const Text('subtitle')),
trailing: Material(child: const Text('trailing')),
),
),
),
),
),
);
}
Use FlatButton.icon instead of using InkWell and Row.
FlatButton.icon solves your mentioned problem and serves both of your purpose to have splash effect and a Title with Icon. It reduces your code too. See below for example
title: Align(
alignment: Alignment.centerLeft,
heightFactor: 1.0,
child: FlatButton.icon(
splashColor: Colors.white,
onPressed: () {},
icon: Icon(Icons.format_align_left),
label: Text('title'))),
Full code
main() {
runApp(
MaterialApp(
home: Scaffold(
body: Center(
child: Container(
color: Colors.greenAccent,
child: ListTile(
dense: true,
leading: Material(child: const Text('leading')),
title: Material(
child: Align(
alignment: Alignment.centerLeft,
heightFactor: 1.0,
child: FlatButton.icon(
splashColor: Colors.white,
onPressed: () {},
icon: Icon(Icons.format_align_left),
label: Text('title'))),
),
subtitle: Material(child: const Text('subtitle')),
trailing: Material(child: const Text('trailing')),
),
),
),
),
),
);
}

how to make flutter web drawer responsive according to different screen size?

I'm making an admin dashboard with a flutter web that has a drawer. but when I try to access it on the mobile, drawer it can't be responsive yet ... how do I access the drawer on the mobile in the form of an icon list?.
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Row(
children: <Widget>[
Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
margin: EdgeInsets.zero,
child: Center(
child: Image(
image: ExactAssetImage("images/image.png"),
),
),
),
ListTile(
leading: Icon(Icons.location_city),
title: Text('Partner'),
onTap: () {
_setPage(ClientPage());
},
),
ListTile(
leading: Icon(Icons.multiline_chart),
title: Text('Proyek'),
onTap: () {
_setPage(ProyekPage());
},
),
],
);
),
],
),
),
this display drawer on a laptop
and this is display drawe on mobile
there is no difference: '
You can use LayoutBuilder to determine the page's screen size and update the children widgets base from the parent's dimensions. Check this similar Stack Overflow post for the sample.