Flutter navigation drawer hamburger icon color change - navigation-drawer

Hamburger icon color of navigation drawer is not changing. Its black by default. I want to change the this icon color in flutter, I am stuck, help me to change this icon color. here is my code.
class Test extends StatefulWidget {
#override
_TestState createState() => new _TestState();
}
class _TestState extends State<Test> {
#override
Widget build(BuildContext context) {
return new Scaffold(
drawer: new Drawer(),
appBar: new AppBar(
title: new Text("Navigation Drawer")
),
),
);
}
}

Add iconTheme to your AppBar
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: Drawer(),
appBar: AppBar(
title: Text("Navigation Drawer"),
iconTheme: IconThemeData(color: Colors.green),
),
);
}
You can also check other solutions here.

You can also use following in Theme's data property
Theme(
data: ThemeData(primaryIconTheme: IconThemeData(color: Colors.red)), // use this
child: Scaffold(),
)
Or
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.menu, color: Colors.red), // set your color here
onPressed: () {},
),
),

To change color of your icon use this
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: AppBar(title: new Text('List view example'),
leading: new Icon(Icons.menu,color: Colors.green,),
),
),
);
}
Icon(Icons.menu,color: Colors.green,) define color inside Icon

Use iconTheme in Appbar like this:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("App Bar"),
iconTheme: IconThemeData(color: Colors.black),
),
drawer: Drawer(),
);
}

This is the only solution to make the button clickable otherwise you need to openDrawer onTap.
AppBar(
iconTheme: const IconThemeData(
size: 40, //change size on your need
color: Colors.black, //change color on your need
),
),

Using The iconTheme for Appbar is not currently working with useMaterial3 = true, And all these answers defined a leading icon for the Appbar without telling how to implement it's onPress behavior, So the best way to change the Drawers icon or it's color is this :
Declare the key for Scaffold :
final scaffoldKey = GlobalKey<ScaffoldState>();
And apply it to Scaffold:
Scaffold(
key: scaffoldKey,
drawer: Drawer()
)
Then , Apply the drawer icon like below with click action:
AppBar(
title: Text("My AppBar"),
leading: IconButton(
icon: Icon(Icons.person),
onPressed: (){
if(scaffoldKey.currentState!.isDrawerOpen){
scaffoldKey.currentState!.closeDrawer();
//close drawer, if drawer is open
}else{
scaffoldKey.currentState!.openDrawer();
//open drawer, if drawer is closed
}
},
),
)

You can change it from main.dart easily this way-
return MaterialApp(
title: 'XYZ',
debugShowCheckedModeBanner: false,
theme: ThemeData(
appBarTheme: AppBarTheme(
iconTheme: IconThemeData(color: Colors.black),
actionsIconTheme: IconThemeData(color: Colors.blue),
backgroundColor: theme.backgroundColor,
elevation: 0,
),
),

Related

Flatbutton is invisible. It is not showing asset image on Flatbutton

it's a code of a main file
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("RTSPS"),
),
body: Center(
child: FlatButton(
child: Image.asset('assets/1st.png'),
onPressed:()=>HomePage(),
),
),
),
);
}
}
and here is pubspec.yaml file code in which I only made changes in assets
assets:
- assets/1st.png

Is there a way to exclude a BottomAppBar from animations in Flutter?

I tried to wrap it in a Hero widget, as that should achieve what I want. This works with BottomNavigationBar, but not with BottomAppBar, which gives this error: Scaffold.geometryOf() called with a context that does not contain a Scaffold. I tried to give it a context by using Builder, but that did not work either. Here is a sample app to showcase the behaviour:
void main() {
runApp(
MaterialApp(
home: PageOne(),
),
);
}
Widget _bottomNavigationBar() {
return BottomNavigationBar(items: [
BottomNavigationBarItem(icon: Icon(Icons.menu), title: Text('menu')),
BottomNavigationBarItem(icon: Icon(Icons.arrow_back), title: Text('back')),
]);
}
Widget _bottomAppBar() {
return BottomAppBar(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(icon: Icon(Icons.menu), onPressed: null),
IconButton(icon: Icon(Icons.arrow_back), onPressed: null),
],
),
);
}
class PageOne extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: Hero(
tag: 'bottomNavigationBar',
child: _bottomAppBar(),
),
body: Center(
child: IconButton(
iconSize: 200,
icon: Icon(Icons.looks_two),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => PageTwo()),
),
),
),
);
}
}
class PageTwo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: Hero(
tag: 'bottomNavigationBar',
child: _bottomAppBar(),
),
body: Center(
child: IconButton(
iconSize: 200,
icon: Icon(Icons.looks_one),
onPressed: () => Navigator.pop(context),
),
),
);
}
}
The problem seems to be the animation that is used with the Navigation stack. Therefore, getting rid of the animation during the page load will stop this animation. I added the PageRouteBuilder to the PageOne class in your example to get rid of the Navigation stack animation. Use the code below to replace the PageOne class from your example.
class PageOne extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: _bottomAppBar(),
body: Center(
child: IconButton(
iconSize: 200,
icon: Icon(Icons.looks_two),
onPressed: () => Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, anim1, anim2) => PageTwo(),
transitionsBuilder: (context, anim1, anim2, child) =>
Container(child: child),
),
),
),
),
);
}
}
There are additional ways to control the animation for Navigation here
(Oh, and I got rid of the Hero() widget)
I have solved this by wrapping the Row with a Hero widget in BottomAppBar. This still allows page transitions, and does not animate the BottomAppBar as intended.
BottomAppBar(
child: Hero(
tag: 'bottomAppBar',
child: Material(
child: Row(
...
),
),
),
);
However, this has laggy animations when using a CircularNotchedRectangle.

How to resize image inside of a leading property?

I am trying to add a logo before the title in the App Bar but it seems the image only takes the width and height of the leading property.
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(context){
return Scaffold(
appBar: AppBar(
title:Text('Hi, Andi Loshi'),
backgroundColor: Color.fromRGBO(230, 1, 1,1),
leading: new Image.asset("assets/images/logo.png",
fit:BoxFit.cover,
height:20.00,
width:20.00
),
),
body: Text('Body will reside here')
);
}
}
Though you can not modify size of leading you can add image before title like below in appbar, title please check below code.
import 'package:flutter/material.dart';
void main() => runApp(Home());
class Home extends StatelessWidget {
Widget build(context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Container(
child: Row(
children: [
Image.asset(
"assets/images/logo.png",
fit: BoxFit.cover,
),
SizedBox(
width: 10,
),
Text('Hi, Andi Loshi')
],
),
),
backgroundColor: Color.fromRGBO(230, 1, 1, 1),
),
body: Text('Body will reside here'),
),
);
}
}
#Mussa Kalokola you can just wrap the image in leading with padding that will make it smaller.
I think that's the easiest solution for that.
eg.
appBar: AppBar(
title: Text(_getScreenTitle(context, _selected)),
leading: const Padding(
padding: EdgeInsets.all(16.0),
child: ClipOval(
child: Image(
image: AssetImage('images/test.png'),
),
),
),
),
You can wrap your leading widget inside a Center Widget or set leadingWidth property inside AppBar.
example:
appBar: AppBar(
title: Text('Your Title'),
//leadingWidth: 38.0,
leading: Center(
child: Image(
image: AssetImage('images/test.png'),
),
),
Widgets inside an AppBar have limited size. If you want a custom one, you can implement it from scratch, this article can help you.
You can use the leadingWidth property in the AppBar.
class Home extends StatelessWidget {
Widget build(context){
return Scaffold(
appBar: AppBar(
title:Text('Hi, Andi Loshi'),
backgroundColor: Color.fromRGBO(230, 1, 1,1),
leading: new Image.asset("assets/images/logo.png",
leadingWidth: 80,
fit:BoxFit.cover,
height:20.00,
width:20.00
),
),
body: Text('Body will reside here')
);
}
}

Animate ListView item to full screen in Flutter

I would like to have my list items perform this animation (mp4) when tapped. I tried using AnimatedCrossFade but it requires its two children to be at the same level, e.g. the detail view cross-fades with the ListView not the tapped item. In fact it seems a Hero animation is the only one that can animate across widgets.
I'm having trouble using Hero. Should it wrap the list item? Does it matter if the Widget subtree is significantly different in the Hero source/destination? Also, can Hero animations be used with LocalHistoryRoutes or staggered animations?
Edit
It's now looking like what I need to do is use an Overlay, the hard part there is that I need to add the selected item to the overlay at the same position on screen where it was tapped, then the animation part would be easy. Possibly of use here is a target/follower pattern e.g. CompositedTransformTarget
You can just use Hero widget to make that kind of animation. Here's my example:
and the source code:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new FirstPage(title: 'Color Palette'),
);
}
}
class FirstPage extends StatefulWidget {
FirstPage({Key key, this.title}) : super(key: key);
final String title;
#override
_FirstPageState createState() => new _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
final palette = [
{'#E53935': 0xFFE53935},
{'#D81B60': 0xFFD81B60},
{'#8E24AA': 0xFF8E24AA},
{'#5E35B1': 0xFF5E35B1},
{'#3949AB': 0xFF3949AB},
{'#1E88E5': 0xFF1E88E5},
{'#039BE5': 0xFF039BE5},
{'#00ACC1': 0xFF00ACC1},
{'#00897B': 0xFF00897B},
{'#43A047': 0xFF43A047},
{'#7CB342': 0xFF7CB342},
{'#C0CA33': 0xFFC0CA33},
];
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Container(
child: new ListView.builder(
itemCount: palette.length,
itemBuilder: (context, index) => new Hero(
tag: palette[index].keys.first,
child: new GestureDetector(
onTap: () {
Navigator
.of(context)
.push(new ColorPageRoute(palette[index]));
},
child: new Container(
height: 64.0,
width: double.infinity,
color: new Color(palette[index].values.first),
child: new Center(
child: new Hero(
tag: 'text-${palette[index].keys.first}',
child: new Text(
palette[index].keys.first,
style: Theme.of(context).textTheme.title.copyWith(
color: Colors.white,
),
),
),
),
),
),
)),
),
);
}
}
class SecondPage extends StatelessWidget {
final Map<String, int> color;
SecondPage({this.color});
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Color'),
),
body: new Hero(
tag: color.keys.first,
child: new Container(
color: new Color(color.values.first),
child: new Center(
child: new Hero(
tag: 'text-${color.keys.first}',
child: new Text(
color.keys.first,
style:
Theme.of(context).textTheme.title.copyWith(color: Colors.white),
),
),
),
),
),
);
}
}
class ColorPageRoute extends MaterialPageRoute {
ColorPageRoute(Map<String, int> color)
: super(
builder: (context) => new SecondPage(
color: color,
));
#override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return FadeTransition(opacity: animation, child: child);
}
}
Someone wrote an amazing dart-package for just this purpose: https://pub.dev/packages/morpheus#-readme-tab-
All you then need to do is use the MorpheusPageRoute and the package handles the rest.
...
Navigator.push(
context,
MorpheusPageRoute(
builder: (context) => MyWidget(title: title),
),
);
...
I'd just cheat and wrap the whole thing in a Stack - bottom layer would be a page with the AppBar, and the top layer would be transparent until painted on.
onTap, duplicate ListTile onto the top surface, and then a Hero animation would fill the full screen. It's not very elegant, but the framework doesn't (yet) provide for covering the AppBar easily, so having a canvas ready to be painted on for other tricky animations might be resourceful.
I'm unable to comment or edit Lucas' post (new account) but you also need to provide the parentKey of the widget where the animation is to begin:
final widgetKey = GlobalKey();
...
ListTile(
key: widgetKey,
title: Text('My ListItem'),
onTap: () => Navigator.push(
context,
MorpheusPageRoute(
builder: (context) => MyNewPage(),
parentKey: widgetKey,
),
),
),
https://pub.dev/packages/morpheus

How should I customize DropdownButtons and DropdownMenuItems in Flutter?

The default DropdownButton with DropdownMenuItems returns a light-grey dropdown. How should I customize the dropdown (e.g. background color, dropdown width)? I can change the style property in both DropdownButton and DropdownMenuItem, like this:
return new DropdownButton(
value: ...,
items: ...,
onChanged: ...,
style: new TextStyle(
color: Colors.white,
),
);
but this doesn't change the dropdown's background color.
Should I copy DropdownMenu and extend it? Does Flutter plan to add customization for this widget in the near future?
You can accomplish this by wrapping the DropdownButton in a Theme widget and overriding the canvasColor.
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
State createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
int _value = 42;
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Theme(
data: Theme.of(context).copyWith(
canvasColor: Colors.blue.shade200,
),
child: new DropdownButton(
value: _value,
items: <DropdownMenuItem<int>>[
new DropdownMenuItem(
child: new Text('Foo'),
value: 0,
),
new DropdownMenuItem(
child: new Text('Bar'),
value: 42,
),
],
onChanged: (int value) {
setState(() {
_value = value;
});
},
),
),
),
);
}
}
I was able to change the background for the Dropdown by wrapping it in a Container with the color property set.
Before:
After:
Here's the code:
Define these values in the widget state:
final items = ['One', 'Two', 'Three', 'Four'];
String selectedValue = 'Four';
then use this code
Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(10)),
// dropdown below..
child: DropdownButton<String>(
value: selectedValue,
onChanged: (String newValue) =>
setState(() => selectedValue = newValue),
items: items
.map<DropdownMenuItem<String>>(
(String value) => DropdownMenuItem<String>(
value: value,
child: Text(value),
))
.toList(),
// add extra sugar..
icon: Icon(Icons.arrow_drop_down),
iconSize: 42,
underline: SizedBox(),
),
);
As Collin said, your DropdownMenuItem will follow your ThemeData class. Not only its backgroundColor will match the canvasColor in your ThemeData class, but also it will follow the same TextStyle.
So, for a quick example:
new ThemeData(
fontFamily: "Encode Sans", //my custom font
canvasColor: _turquoise, //my custom color
//other theme data)
Furthermore, if you want to control the width of the menu, you can feed its child property a new Container and add the desired width, check the following GIF, I started with width: 100.0 then hot reloaded after changing it to 200.0, notice how the width was manipulated, just make sure you use a suitable width so that you do not get overflow problems later on when you use the menu within a more complex layout.
class TestPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title:new Text ("Test"),
),
body: new Center(
child: new DropdownButton(items: new List.generate(20, (int index){
return new DropdownMenuItem(child: new Container(
child: new Text ("Item#$index"),
width: 200.0, //200.0 to 100.0
));
})
, onChanged: null)
),
);
}
}
If you want the DropdownButton to fill the space that it is in, use the property isExpanded and set it to true
DropdownButton<String>(
isExpanded: true,
)
You can do something very simple in the latest version of Flutter.
The DropdownButton class has an inbuilt variable called 'dropdownColor' which can be assigned any color you need directly, without changing any 'ThemeData'. Automatically changes the color of the dropdown menu items as well.
Use this for color
DropdownButtonFormField(
items: null,
onChanged: null,
dropdownColor: Colors.red,
),
https://api.flutter.dev/flutter/material/DropdownButton/style.html will help you to figure out some stylings.
DropdownButton(
dropdownColor: Colors.grey,
value: this.repeatType,
onChanged: (String? value) {
print(value);
setState(() {
this.repeatType = value!;
});
},
selectedItemBuilder: (BuildContext context) {
return this.repeatTypes.map((String value) {
return Text(
this.repeatType,
style: const TextStyle(color: Colors.white),
);
}).toList();
},
items: this
.repeatTypes
.map((item) => DropdownMenuItem(
child: Text(
item,
style: TextStyle(color: Colors.green),
),
value: item,
))
.toList())
You can wrap it with container like this:
Container(
margin: const EdgeInsets.all(15.0),
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.white)
),
child: DropdownButton(
dropdownColor: Colors.white,
style: TextStyle(
color: Colors.black,
backgroundColor: Colors.white,
),
value: 'ar',
items: [
DropdownMenuItem(child: Text('English'), value: 'en'),
DropdownMenuItem(child: Text('العربية'), value: 'ar'),
],
),
)
The output:
It's so simple now,
Just use the dropdownColor property inside the DropdownButton widget like this:
DropdownButton(
dropdownColor: Colors.red, // here you change the background color
value: 'Your value',
items: [ ],
)
you can use the dropdown_button2 package.
You can use the dropdownDecoration property to customize the dropdown menu appearance. This is the best package I found to fully customize a DropdownButton

Resources