ButtonStyle padding different from container padding - flutter

Why is it that a ButtonStyle's padding property is not equivalent to a Container's padding property in terms of pixels?
I would expect the TextButton and Container text to be aligned when placed together here:
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextButton(
style: ButtonStyle(
padding: MaterialStateProperty.all(EdgeInsets.all(24)),
),
onPressed: () => print('pressed!'),
child: Text('My Button'),
),
Container(
padding: EdgeInsets.all(24),
child: Text('Some other text'),
)
],
);
Both the TextButton and Container theoretically have taken the same padding amount, and yet the texts do not line up. Note the "S" from the Container text does not line up with the "M" from the TextButton, despite them both having the same amount of padding:
Note that the Column's crossAxisAlignment has been set to "start" such that both widgets should align to the left-most side.
Am I missing something about the ButtonStyle's padding property?
Update
I can confirm that iOS and Android does not have the same issue. This issue seems to be isolated to Web and Desktop (macOS/Linux). I have not tested Windows.

So it seems that this is a bug and has been tracked here on GitHub.
As per the comments, a fix was pushed to the master channel of releases in March and I presume will be available in the next 2.3.0 stable release.
For those who want to switch to the latest master to double check that it's working as it should; run:
$ flutter channel master
$ flutter upgrade
You may also need to reinstall any packages before running.

Related

Should i use less complex widgets for best flutter performance?

I prefer to use a Column with SizedBox to build space layout ! But my boss keep saying that i should use a Container with padding because container is less complex widget and should perform better. He always says that i should avoid stack widget because is a complex widget. But i think i remember from a flutter video that doesn't matter which widgets you choose, because flutter optimizes it when it builds the three trees ! Is that true ? should i spend time optimizing my widgets with less complex widgets as possible ?
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(height: 24),
Text(
text,
),
],
);
Container(
padding: EdgeInsets.only(top: 24),
child: Text(
text,
),
);
In Flutter padding desing discussion they said that doesn't matter if you use container with padding or specific padding widget. But i'm still in doubt if i should use less complex widget in general.

Why does Flutter need to have a "child: null" line of code when text button is used in a children[] widget?

New to flutter. I'm currently working through a flutter course where I practice adding packages to play sounds by building a xylophone. When adding multiple buttons for each sound file, flutter was telling me "The parameter 'child' is required" and has me insert it at the end of the TextButton with a null property. The code worked fine without it on there but dart analysis kept giving me a warning. Sample code after inserting child listed below.
children: [
TextButton(
onPressed: () {
final player = AudioCache();
player.play('note1.wav');
},
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(Colors.red),
), child: null,
I cannot seem to find why this was warning me but reading the documentation it looks like maybe because it was expecting text for text button? Can anyone explain or point to why it does this?
Thanks in advance.
EDIT
As user #Saddan says, the TextButton class includes box constraints, meaning it will still have a size even without a child.
The real reason why you need a child widget is a bit more boring: There are very few reasons why you would want to have a TextWidget without a child, and even if you did, as I mention later in my answer, a more common approach to this is to use Container, which can be understood as an empty widget, because of this, the child property is considered required on the text widget (with null-safety, you get a compile-time error and without it, you get a lint warning like in the question).
The reason why child: null is added automatically is that flutter doesn't know what you want as your TextButton's child, but I believe you are meant to replace null with whatever else.
ORIGINAL ANSWER
A TextButton should always have a child because if it doesn't it will not display anything, a text button can't size itself so it will always have the same size as its child, you need to put something on the child property or the text button will not know what to look like.
Now, you are passing null as the child, I will have to admit, I didn't think that was possible, I also don't think flutter likes this idea very much (If you activate null-safety, this code will throw a compile-time error). I think you should instead use Container, which is an empty-by-default widget as the child property:
TextButton(
onPressed: () {
final player = AudioCache();
player.play('note1.wav');
},
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(Colors.red),
),
child: Container(),
You can also use the container with some color, some width or some height if you want:
Container(
color: Colors.red,
width: 20,
height: 20,
);
Your assumption is quite right. Its expecting a Widget ,if specific its expecting a TextWidget which consider a label or name of your button. Probably you're using an old version of flutter framework so its accepting null value of child but as I'm using 2.5.3 it's not accepting null value and you must need to provide it.

How to dynamically theme BoxDecoration in Flutter / GetX

I am using GetX with Flutter and dynamically change Application theme via standard ThemeData. All is working great for properties within ThemeData.
However, I just implemented Drawer widget and wanted to also theme the 'decoration' property within DrawerHeader (of type BoxDecoration). I wanted to theme the color within BoxDecoration depending on selected theme but it only seems to accept constant. I have not find any way to dynamically change it based on the theme.
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: const <Widget>[
DrawerHeader(
decoration:
BoxDecoration(color: Get.isDarkMode ? Colors.red : Colors.blue),
I get the following error:
The values in a const list literal must be constants. Try removing the keyword 'const' from the list literal.
It relates to the following part:
color: Get.isDarkMode ? Colors.red : Colors.blue
Any recommendation how to do that?
Thank you.
Felipe - you are right. I spent hours of reading and testing but for some reason I completely missed the obvious thing - was always looking only at Decoration / BoxDecoration itself and not up the tree. Thank you so much for your fast answer. It works now.
Issue was with the following line:
children: const <Widget>[
after removing the const it works - solution:
children: <Widget>[
Render two different drawer headers based on Get.color, instead of rendering one drawer head with variable colors.

How to set the height of the Container of GridView to "auto" in Flutter

A recurring issue I have in my Flutter learning journey, is that GridView does require a parent container with a specified height.
What is the best practice to maximize the height so that it stretches out as much as needed without always incurring in overflow issues or unpleasant UI?
Here are a few methods I tried:
double.infinity - This one doesn't work properly, GridView doesn't show at all.
Container(
height: double.infinity,
child: GridView.builder(
....
)
MediaQuery.of(context).size.height - This one doesn't work properly either, overflow issues occur and just doesn't work completely when other elements are displayed (for example in a column).
Container(
height: MediaQuery.of(context).size.height,
child: GridView.builder(
....
)
fixed size - This one doesn't allow any flexibility at all and isn't ideal for responsiveness too.
Container(
height: 800,
child: GridView.builder(
....
)
Thank you.
Instead of using Container try to use Flexible widget.

Why does a ListView cause rendering error when used directly inside Column?

I used ListView inside Column and it causes a rendering error. When I wrapped ListView in Container or Expanded widgets, it works fine. What is the reason that causes the error?
Column(
children: <Widget>[
Expanded(
child: ListView(
children: <Widget>[
],
),
),
],
),
A ListView tries to fill all the available space given by the parent element (here column). But the column has no definite space defined.
Column's children should have a definite size. If you haven't used Expanded or shrinkWrap property of listview, it won't recognize. Hence will give you rendering error.
With Expanded, you defined that child can expand as much as it wants, giving the definite size.
Or
If you set it to shrinkwrap: true, the list will wrap its content and be as big as its children allow it to be.
So in both cases, the column will get a definite size to render.