Flutter - How to change IconButtons size with Theme - flutter

I have a Row with multiple IconButtons and I need to change their color and size.
I managed to change the color, but I'm not able to change the icons size.
IconTheme(
data: IconThemeData(size: 48.0, color: Colors.yellow),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
IconButton(
icon: Icon(Icons.delete),
onPressed: () => null,
),
IconButton(
icon: Icon(Icons.file_upload),
onPressed: () => _addPhoto(false),
),
IconButton(
icon: Icon(Icons.camera_alt),
onPressed: () => _addPhoto(true),
),
],
),
),
If I set the size within the IconButtons with iconSize it works, but with IconTheme it doesn't.
How can I fix it?

As defined in the official docs, link here:
This property must not be null. It defaults to 24.0. The size given here is passed down to the widget in the icon property via an IconTheme. Setting the size here instead of in, for example, the Icon.size property allows the IconButton to size the splash area to fit the Icon. If you were to set the size of the Icon using Icon.size instead, then the IconButton would default to 24.0 and then the Icon itself would likely get clipped.
Therefore, IconButton needs to be given the iconSize property as this overrides the IconTheme size property. If you want your button to have size derived from IconTheme then you should make your custom IconButton which sets the iconSize for you. For example:
class CustomIconButton extends StatelessWidget {
CustomIconButton({Key key, this.onPressed, this.icon});
final Function onPressed;
final Icon icon;
#override
Widget build(BuildContext context) {
IconThemeData iconThemeData = IconTheme.of(context);
return IconButton(
onPressed: onPressed, iconSize: iconThemeData.size, icon: icon);
}
}

Use iconTheme of ThemeData like so and all your icons will be size 35 with the below code:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
iconTheme: IconThemeData(
size: 35.0,
),
),
home: HomePage(),
);
}
}

First, check if you are in a layout area that uses the primary or default theme. Whats that? Places on a layout that uses the primary color.
ThemeData(
primaryColorLight: Colors.blueAccent[100],
primaryColor: Colors.blueAccent[200],
primaryColorDark: Colors.blueAccent[700],
accentColor: Colors.yellow[700],
iconTheme: IconThemeData(
color: Colors.yellow[700],
size: 28
),
accentIconTheme: IconThemeData(
color: Colors.yellow[700],
size: 32
),
primaryIconTheme: IconThemeData(
color: Colors.yellow[700],
size: 24
),
);
If you are on a primary area (places on a layout that uses the primary color) the accentIconTheme will be used
Otherwise the primaryIconTheme
The IconTheme I do not know for now, so anyone feels free to edit or put on a comment

The icon button was not picking the Icon Size defined in the Theme. Instead, I have to wrap the icon inside of the icon button in iconThemeData.
icon: IconTheme(
data: Theme.of(context).copyWith().iconTheme,
child: Icon(
Icons.search,
),
),
onPressed: () {},
),
This fixed the problem but it's not a good practice to wrap the Icon every time for the theme. There must be a proper solution for that.

make your raw a row of Icons (not IconButton).
then wrap your Icon with a widget that can be taped Like (InkWell or GestureDetector) to take advantage of the (onTap function) .
it’s not a good way actually but it will probably solve your problem .

Related

Error: no named parameter with the name 'color' Flutter

So I'm new to Dart & Flutter and have run across a problem. I'm trying to learn the layout and make subtle UI changes to text & button widgets. Here I'm trying to change the color of the ElevatedButton to blue
import 'package:flutter/material.dart';
class Answer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
child: ElevatedButton(
color: Colors.blue,
child: Text('Answer 1'),
onPressed: null,
),
);
}
}
When I run the code I get this error:
Error: no named parameter with the name 'color'
I thought with buttons there were color parameters that you could change. What would be the correct way of implementing this?
You can style ElevatedButton by using the styleFrom
ElevatedButton(
child: const Text('Button'),
onPressed: () {},
style: ElevatedButton.styleFrom(
primary: Colors.purple,
),
or you can use ButtonStyle class
ElevatedButton(
child: const Text('Button'),
onPressed: () {},
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.red),
),
ElevatedButton(
style: ElevatedButton.styleFrom({
Color primary, // set the background color
Color onPrimary, // foreground
}),
),
In Flutter, Some widget deal with styles and themes for general app theme purposes, because of that it doesn't allow for changing the color directly, but with style parameters:
ElevatedButton(
style: ElevatedButton.styleFrom({
Color primary: Colors.green,
Color onPrimary: Colors.white,
}),
),
For more information please visit Flutter documents ElevatedButton.styeFrom and experiment with different parameters.
Welcome to Flutter.
You can style ElevatedButton by :
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty
.all<Color>(Colors.blue),
foregroundColor: MaterialStateProperty
.all<Color>(Colors.white),
),
child: Text('your text'),
onPressed: null,
),
Update your flutter SDK. That happened as SDK is not updated.
To update your flutter SKD, open CMD from windows and command "flutter upgrade".

Create IconButton with shape Decorate give invalid constant value flutter

I'm new in flutter and I'm looking IconButton with oval background.
Here is what I'm using.
Ink(
decoration: const ShapeDecoration(
color: Theme.of(context).accentColor,,
shape: CircleBorder(),
),
child: IconButton(
icon: Icon(Icons.add),
color: Theme.of(context).primaryColor,
onPressed: () {},
),
),
Can you please let me know how I can add my Theme color in this button because I have dark mode also which changed button colors and background etc when dark mode enable by user.
As per official docs Link Here :
You should be able to set color by using IconThemeData
Defines the color, opacity, and size of icons.
Used by IconTheme to control the color, opacity, and size of icons in a widget subtree.
To obtain the current icon theme, use IconTheme.of.
Therefore, IconButton needs to be given the color property as this overrides the IconTheme size property. If you want your button to have color derived from IconTheme then you should make your custom IconButton which sets the color for you.
... in your case, I'd pass - maybe even store it in a separate variable like currentThemeColor - the current color theme and set it here:
...
IconThemeData(size: 48.0, color: currentThemeColor)
...
Also, you might need to create your custom IconButton:
class CustomIconButton extends StatelessWidget {
CustomIconButton({Key key, this.onPressed, this.icon});
final Function onPressed;
final Icon icon;
#override
Widget build(BuildContext context) {
IconThemeData iconThemeData = IconTheme.of(context);
return IconButton(
onPressed: onPressed, color: iconThemeData.color, icon: icon);
}
}
Using FlatButton you can achieve same result.
FlatButton(
onPressed: () {
},
color: Theme.of(context).hintColor.withOpacity(0.5),
shape: CircleBorder(),
child: Icon(Icons.add, color: Theme.of(context).primaryColor),
)

How can I change the size of drawer/back button icons of appbar without modifying the behavior provided by default in Flutter?

I am trying to change the size of the icons ("Back" provided by Navigator and "Drawer" provided by Scaffold) in appbar in my ThemeData, modifying iconTheme and primaryIconTheme:
ThemeData(
primarySwatch: Colors.blue,
iconTheme: IconThemeData(color: Colors.grey, size: 32),
primaryIconTheme: IconThemeData(color: Colors.grey, size: 32)
),
This lines only changes the color of the icons, but the size does not change.
I do not need to change the behavior that Flutter handles this button, only the size of them.
The AppBar widget uses a BackButton widget, so that change is not possible unless you modify it from the framework in a different branch, but the best approach is to use the Leading property and the condition ModalRoute.of(context)?.canPop to check whether the current route can be popped. For example:
AppBar(
leading: ModalRoute.of(context)?.canPop == true
? IconButton(
icon: Icon(
Icons.arrow_back,
size: 60,
),
)
: null,
title: Text(
"Example",
),
)
Luis' answer is mostly complete, but note that you will need to define the onPressed callback in the IconButton, shown below:
AppBar(
leading: ModalRoute.of(context)?.canPop == true
? IconButton(
icon: Icon(
Icons.arrow_back,
size: 60,
),
onPressed: () => Navigator.of(context).pop(),
// used onPressed here
)
: null,
title: Text(
"Example",
),
)

How to set color of all text in a specific container in flutter?

I don't want to change the text color of the whole app. Just all the text inside a container. Can I wrap it with some other widget or something for this ?
To apply certain TextStyle properties only to a subtree of your app. You can use DefaultTextStyle
DefaultTextStyle(
child: Container(child: /* your subtree */),
style: TextStyle(color: Colors.red),
),
as a comment pointed out, this replaces all defaults, not just the color. This can be mitigated by using the merge constructor:
DefaultTextStyle.merge(
child: Container(child: /* your subtree */),
style: TextStyle(color: Colors.red),
),
flutter's answer is good in my opinion. But the power of ThemeData is more than you think. Here is the official documentation about Themes for part of an application.
You could provide a Theme to wrap your container to provide a new theme. Here is two way to slove it:
1. Creating unique ThemeData
/*Not recommended, this could make a totally different If you just want a little part changed.*/
Theme(
// Create a unique theme with "ThemeData"
data: ThemeData(
textTheme: /* Your Text Theme*/,
),
child: Container(
onPressed: () {},
child: Text("Your Text Here"),
),
);
2. Extending the parent theme
Theme(
// Find and extend the parent theme using "copyWith". See the next
// section for more info on `Theme.of`.
data: Theme.of(context).copyWith(textTheme: /* Provide your theme here! */),
child: Container(
child: Text("your text here"),
),
);
You could also use existed theme with a little changed:
Theme.of(context).textTheme.copyWith(
body1: Theme.of(context).textTheme.body1.copyWith(color: Colors.red),
)
Use DefaultTextStyle.merge to keep your theme and just change the color.
DefaultTextStyle.merge(
style: TextStyle(color: Colors.grey[400]),
child: Column(...),
)
If you are using the MaterialApp widget you could use the theme property of it and set different Text themes and call them anywhere in your app. For example the following code defines 3 different text themes:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "Time Tracker",
theme: ThemeData(
textTheme: TextTheme(
headline: TextStyle(fontSize: 72.0, fontWeight: FontWeight.bold,color: Colors.blue),
title: TextStyle(fontSize: 36.0, fontStyle: FontStyle.italic,color: Colors.red),
body1: TextStyle(fontSize: 14.0, fontFamily: 'Hind',color: Colors.yellow),
),
),
home: LandingPage(),
);
}
}
You can then call a particular theme(headline) anywhere in your app like this:
Text('Home Page',style: Theme.of(context).textTheme.headline,)
Which gives you the headline TextTheme
I have functions for all my styles
TextStyle largeTextStyle() => TextStyle(fontSize: 150);
then I just do
Text("blah", style:largeTextStyle())

Custom style or theme for Expansion Tile Header, Flutter

Is there any way to apply custom theme for ExpansionTile. In my case, I want to have the different background colour for Header and children of the expansion tile but When ever the ExpansionTile is expanded, Headers background color changes to that of children?
To apply a custom Theme to any widget, just wrap it with the Theme() widget.
and then specify your custom theme in the data field of the widget.
Theme(
data: ThemeData(/*specify your custom theme here*/),
child: ExpansionTile() /*or any other widget you want to apply the theme to.*/
)
In your case, to customise the header in ExpansionTile,
when ExpansionTile is closed
the style of header text i.e. title depends on
ThemeData.textTheme.subhead (in flutter 2 it's ThemeData.textTheme.subtitle1)
whereas, the style of the arrow icon depends
on ThemeData.unselectedWidget (in flutter 2 it's ThemeData.unselectedWidgetColor)
when ExpansionTile is open
the color of both the widgets depends on ThemeData.accentColor
In a similar fashion you can customise almost any part of the expansion tile by tweaking the theme. For more details check out this link.
Since flutter is built with flexibility in mind. You can do almost anything you want. Create almost any UI you want.
Following the idea of #user3315892, you can implement your own stateful widget for the ExpansionTile, so that you can control what colours you want the header and children to be when the header is expanded or collapsed.
The following example only changes the text foreground and background colours of the header when the expansion tile is expanded or collapsed, but you can do the same for the children widgets.
class CustomExpansionTile extends StatefulWidget {
#override
State createState() => CustomExpansionTileState();
}
class CustomExpansionTileState extends State<CustomExpansionTile> {
bool isExpanded = false;
#override
Widget build(BuildContext context) {
return ExpansionTile(
title: Container(
child: Text(
"HEADER HERE",
style: TextStyle(
color: isExpanded ? Colors.pink : Colors.teal,
),
),
// Change header (which is a Container widget in this case) background colour here.
color: isExpanded ? Colors.orange : Colors.green,
),
leading: Icon(
Icons.face,
size: 36.0,
),
children: <Widget>[
Text("Child Widget One"),
Text("Child Widget Two"),
],
onExpansionChanged: (bool expanding) => setState(() => this.isExpanded = expanding),
);
}
}
I found another way to do it. I don't know if this is the best way but it's simpler for me.
To change the ExpansionTile color, you can wrap it with a Container and give it a color. This will change the entire color of the ExpansionTile, both collapsed and expanded.
But if you want a different color for the children, you can also wrap them with a Container and set another color there. However, keep in mind that you have to "expand" that Container to occupy all the available space (you can do it by setting width and height parameters properly).
Btw, that doesn't change the arrow color.
Widget expansionTileTest(context) {
return Container(
color: Colors.grey,
child: ExpansionTile(
title: Text(
"Title",
style: TextStyle(color: Colors.black),
),
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height * 0.1,
width: MediaQuery.of(context).size.width,
color: Colors.yellow,
child: Center(child: Text("Hi")),
),
],
),
);
}
Collapsed
Expanded
You can set color of header and then body/children wrap in Container and set color to that container.
I used this code to make the trailing ion color Black.
Theme(
data: Theme.of(context).copyWith(accentColor: Colors.black),
child: ExpansionTile(
backgroundColor: Colors.white,
title: Text(
'Title Exmample',
style: TextStyle(color: Colors.black),
),
leading: CircleAvatar(
backgroundColor: Colors.black.withOpacity(.07),
child: Icon(
Icons.apps_outlined,
color: Theme.of(context).primaryColor,
)),
children: _buildTiles(Theme.of(context).primaryColor, Colors.black.withOpacity(.07), context),
),
);
If you want the ExpansionTile title to remain the same color whether closed or expanded, you can set it's style:
ExpansionTile(
title: Text('HEADER HERE', style: TextStyle(color: Colors.red)),
...
),
Additional styling for ExpansionTile is an open feature request:
Feature request: More styling of ExpansionTile #15427