Increase width and height of Checkbox in CheckboxListTile - flutter

I am using CheckboxListTile. I just want to increase the size of the Checkbox, without affecting the size of overall CheckboxListTile. If it were Checkbox only widget, I would have used Transform.scale to increase the widget size.
Is it possible to achieve what I want? Or i would have to use Checkbox?
Thanks

As mentioned here (https://api.flutter.dev/flutter/material/CheckboxListTile-class.html#instance-properties) there is no any property or method provided by CheckboxListTile to control size of Checkbox. So, having a custom tile with checkbox makes more sense here.
Something like in code below:
Row(
children: [
Transform.scale(
scale: 1.5,
child: Checkbox(value: mail, onChanged: (value) {}),
),
Text(
"Check Me",
)
],
),
Also wrapping the row in Inkwell with onTap changing state similar to that of onChanged in Checkbox will have almost same experience as CheckboxListTile where tapping on any part of tile checks or unchecks the box.
You can even use a ListTile with a CheckBox. The source code for CheckboxListTile (https://github.com/flutter/flutter/blob/52b3dc25f6/packages/flutter/lib/src/material/checkbox_list_tile.dart#L124) exactly does that. Be sure to use on tap with handlechange as done in the source to get the effect of value change on tapping anywhere in the tile.

Related

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.

Collapsing an ExpansionTile when clicking on another ExpansionTile in a ListView that also contains ListTiles

I am currently trying to create a behavior for my drawer. I have a ListView with ExpansionTiles and normal ListTiles in-between the ExpansionTiles. If the user clicks an ExpansionTile it will open but when they select another ExpansionTile from the list, I would like it to collapse the previously open ExpansionTile. I know that ExpansionPanel.radio can be used to create this effect but it doesn't allow for regular ListTiles to be in the list as well. Anybody ever achieved this and can provide tips?
Simplified code:
bool newsExpanded = false;
bool weatherExpanded = false;
ExpansionTile(
initiallyExpanded: weatherExpanded,
textColor: Colors.black,
iconColor: Colors.grey,
backgroundColor: Colors.white38,
title: Text(
'Weather',
style: TextStyle(
fontSize: 16.0, fontWeight: FontWeight.bold),
),
onExpansionChanged: (onChanged) {
if (onChanged) {
setState(() {
newsExpanded = false;
weatherExpanded = true;
});
}
},
Both ExpansionTiles are the same code but with different bools.
Create a list of booleans for each one of your ExpansionTiles that holds whether the tile is open or not, start with all set to false and then whenever one of the tiles are open set the associated index in the list to true and all other to false.
After reading many SO posts and answers on this particular topic after facing this problem myself today it seems like there currently is no direct way to achieve this.
There are two workarounds that I have seen in the different answers:
The approach you also wanted to use. However, the problem is that initiallyExpanded is actually only called once when the ExpansionTile is built the very first time in the build method. So even if you change the bools for newsExpanded and weatherExpanded using setState(), initiallyExpanded is not called a second time. You can however cause initiallyExpanded to be triggered again by building a new ExpansionTile as replacement for the original one. This can be achieved by adding key: GlobalKey() to the ExpansionTile. The downside however, is that you lose the animation for the Widget because instead of changing its state you replace it with a new Widget that already renders as fully expanded.
You can also build your own ExpansionTile as a StatefulWidget. Thus you can assign a state to it and trigger expansion updates. The code behind this concept is quite extensive for what you want to achieve. If you're interested in using this approach you can find more informations and the neccessary code in this SO post.
I hope a functionality for this might be added in the future. Until then I'd consider thouroughly whether the functionality is really integral to your application.

Dynamic height of a column's child

Let's say I have this Column:
Column(
children: [
Flexible(
flex: 2,
child: Card(
child: Text("Card")
)
),
Flexible(
flex: 3,
child: Column(
children: [
// Buttons
]
)
)
]
)
What I want to achieve is that the Card always has a flex of 2, and only gets smaller if the screen (or parent) is too small to render both the card and the buttons. However, with the code above, the card gets scaled down to its minimum size to contain the text, although there is space at the end of the screen.
Replacing the card's Flexible widget with an Expanded widget would fix this, but as I already said, it will never get smaller then, which will end up in a bottom overflow if the screen gets smaller (or the buttons get bigger).
Is there any way to achieve what I want? Or is this just a limitation of Flutter's rendering system?
Edit: I want to avoid making the screen scrollable.
As you probably already know, Flexible allows its child to expand, but it does not force to do so. Viceversa, we use Expanded to force a child to occupy the remaining column/row.
Here's your options:
Use a Flexible Widget, and exploit its fit property: set it to FlexFit.tight to force it to fill the space (default is FlexFit.loose: the child can be at most as large as the available space, but is allowed to be smaller);
Use an Expanded Widget, since I sense that you want to occupy all the available space, a priori;
Mix these two approaches (Flexible on your Card, Expanded on your Buttons, or vice-versa)
In both cases, if some smaller screens are giving you trouble, consider making some elements scrollable: I don't know how big your Card is, but you could wrap it inside a SingleChildScrollView. Or, if you want try something else, you could make the whole screen scrollable with the same approach (you have to pay attention to that Column, though, as there is infinite height...)

Remove default Materiel design paddings

Basically all Material Design Widget have a default minimum padding, as per their documentation.
Is there a way to remove this padding ? For example, a TextFormField while have its label very close to its content, but I haven't found a way to do the same for a DropDownButton, which is annoying since it break the pattern in a form having TextFormFields and DropDownButtons in it.
Many thanks.
Edit :
This question provides the widget I need, which doesn't seem to be well known : DropdownButtonFormField. It adds components like a label, which answers my immediate need.
Are you looking for this ?
TextField(
decoration:InputDecoration(
contentPadding: const EdgeInsets.all(0.0),
isDense:true,
),
EdgeInsetsGeometry contentPadding : The padding for the input decoration's container. [...]
bool isDense : Whether the InputDecorator.child is part of a dense form (i.e., uses less vertical space). default is false

Shrink TextFormField to fit only text

How can I shrink a TextFormField to fit only the text inside it and its associated prefix/suffix icons?
I'm trying to display a prefix (dollar) icon next to my number input. I want the field to align the the right of the screen. My TextFormField is inside a row:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('TITLE'),
Expanded(
TextFormField(
textAlign: TextAlign.end,
decoration: InputDecoration(
prefixText: '\$',
),
...
),
),
],
),
While this displays the numbers to the right, the TextFormField is expanding to fill all available space, and putting the prefix text on the left:
TITLE$_____________1000
I would like to add a spacer between the title and the form field, and let the form field occupy only the space needed to show its numbers:
TITLE<----spacer---->$1000
My attempts so far have only resulted in the spacer sharing spacing with the form field:
TITLE<--spacer-->$____1000
I want to style the prefix text differently than the field text, so I can't use an inputFormatter to add my prefix. There doesn't seem to be any way to tell the form field to draw the prefix text next to the field text. I suspect my issue with the prefix text is related to this bug: https://github.com/flutter/flutter/issues/18788
If there's a way to tell the form field to occupy the minimum amount of space needed, I can work around the prefix text bug.
I don't think you can shrink a TextFormField to fit only the text inside. Not easily anyway. I don't have the answer but maybe some pointers could also help ya.
First: you'd have to know what font you are using and calculate how long the text would be if you rendered it on the screen with the exact same font style as the input's. Once you have that, in theory, it should be possible to programmatically calculate the width of the input field.
Flutter uses RenderObject's to keep track of sizes. In fact, RenderBox is a child class of RenderObject. You can retrieve them by via GlobalKey.
If I remember correctly the API:
final gk = GlobalKey();
RenderBox box = gk.currentContext.findRenderObject();
Curious what solution you'll find. If you figure this out, please drop a response :)