Edit: I think my descirption wasn't all too clear. I need the heigth between app bar und nav bar as a double so I can size other things with that.
I'm done coding the logic for my app and have just started with implementing the design someone made for me. A lot of the elements in my app are scaled according to the available height. The problem, I'm not quite sure how to get that reliably. So...how do I get the height indicated by the red line in the screenshot (taken from the design):
My approach:
availableHeight = MediaQuery.of(context).size.height - appBarHeight - BottomNavHeight - ?
Questions:
Is there a way to figure out the height of the bottom navigation? I have the appBarHeight as I control it manually.
And what else has to be substracted from the total height? Are there default paddings or anything else?
What is the effect, if I wrap everything in a SafeSpace widget? How do I account for that? (Nor sure, if I will yet).
It looks like you are just trying to get the available area for you to use.
In that case, just use LayoutBuilder widget. It will give you the area available at the spot where you use it.
For example:
return Scaffold(
appBar: AppBar(title: const Text('LayoutBuilder Example')),
body: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
print(constraints.maxWidth);
return FlutterLogo();
},
),
);
i think u wanna to try get remainder layout between appbar-navbar, it's automatically fully using so nothing difficult
Related
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.
I am now working with the infinite scroll down widget of flutter. The problem is every child(item) widget's height should be different between each other.
In PagedGridView, there is a property called childAspectRatio.
This is a double type value by default 1.0
I want to make the each child widget's height would be flexible according to its original size. Is there a good way to set the childAspectRatio dynamically according to the item's original size?
If this is an impossible way, is there any other approach without using infinite scroll loading package that implements each item's height-flexible grid view with scroll loading?
How to do this?
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
final double itemWidth = size.width / 2;
double itemHeight = 0.0;
_displayItem (BuildContext context, Widget item, int index) {
double itemHeight = MediaQuery.of(context).size.height;
print(itemHeight);
return item;
}
return PagedGridView<int, Widget>(
showNewPageProgressIndicatorAsGridChild: true,
showNewPageErrorIndicatorAsGridChild: true,
showNoMoreItemsIndicatorAsGridChild: true,
pagingController: _pagingControllerForDummy,
builderDelegate: PagedChildBuilderDelegate<Widget>(
itemBuilder: (context, item, index) => _displayItem(context, item, index),
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: itemWidth / itemHeight,
crossAxisCount: 2,
),
);
}
I would suggest you use an existing package like the flutter_staggered_grid_view because you certainly don't want to mess with the complexity of the layout. Then you choose a state management solution (I recommend the BLoC pattern). The key is to assign a ScrollController to check whether the user has scrolled to the bottom of the grid view. In this case you tell your state management solution to fetch new items from the API which triggers a rebuild of your grid view with the new amount.
Here is an example using StatefulWidget:
flutter_staggered_grid_view infinite scroll from api feed
My friend made a pub package that looks similar to what you want to achieve, and supports infinite scrolling: waterfall_flow
He also made a live demo using Flutter Web, you can play with the demo before you decide if it's suitable for your needs.
(Above picture is taken from simple live web demo.)
(Above picture is taken from complex live web demo.)
If you have any further questions you can direct comment here (and I can ask him to answer) or reach out to him through GitHub, or join our QQ discussion group listed in the package description - we are highly active there and will answer any questions you have regarding this package, other packages or just Flutter questions in general.
I find a way to set aspect ratio of biggest child to our Grid view dynamicly. how it work ? First please Look at this answer for . how we can find size of a widget during the build with overlayEntery
How to get a height of a Widget?
after that we set the right aspect ratio (Measured with overlayEntery ) to our Grid View in childAspectRatio.
Make two listviews and connect the scrollControls. When a new element is added, you can find out which one is shorter by looking at the maxScrollExtends values of the listviews.
I build my app homeScreen that contains multiple part of widget and most of the is basically a listView with different size, and I put them all inside column widget.
the problem is this listView is actualy come from streamBuilder so the content inside the list is dynamic (come from firebase) so there is gonna be a time it will contain 5 items for example or 0 items.
And as far as I know when I use streambuilder or listview in general I need to warp this widget in something like container with predefined height and if the listview items only 1 and I predefined the height to be for 5 items then it will show a big white space of nothing (since the container is for 5 items but to that user, he/she only have 1 items)
Container(
height: screenHeight * 0.4,
child: StreamBuilder<List<Place>>(
stream: database.placesStream(),
builder: (context, snapshot) {
return ListItemsBuilderNoScroll<Place>(
snapshot: snapshot,
itemBuilder: (context, place) => _buildPlaceList(screenWidth, screenHeight, place),
);
},
),
),
So how to fix this issue or am I using the wrong widget for this situation?
This seems to be a legit problem, but more of a logic problem than design. Instead of directly building the listview by default, you may check of data being available on the stream you are listening to. Set a flag or something on the basis of which you decide whether to build the listview to display or not.
Additionally, once the get the list you need to display on the list view, you may also change the size of the container by the checking the list length.
Anyway, this is a seven-month-old question, hopefully, you have found the solution to your problem.
Happy Coding!
GS
I have a weird extra spacing when clicking into a textfield in Flutter, that above the normal iOS keyboard some extra grey box appears. Can anyone help me where this comes from and how to get rid of it? The video shows how it appears.
Thanks!
Found it, thanks for the help!
I have a setup with tabs at the bottom and had in from former tests these 2 properties set to false in the scaffold setup:
child: Scaffold(
// resizeToAvoidBottomPadding: false, <-- caused the extra space
// resizeToAvoidBottomInset: false, <-- caused the extra space
body: buildTabs(context),
This is happens when you have a scaffold that is a child of another scaffold and one of them has backgroundColor: property set to a value. You can set scaffoldBackgroundColor: property in your theme and remove color properties in the scaffold itself and this should fix your issue!
This issue happens when you nest a Scaffold inside another Scaffold.
I added the following property to the outer Scaffold to solve the issue:
Scaffold(
...
resizeToAvoidBottomInset: false,
)
In my case I had this structure which cased the whitespace:
Scaffold(child: PageView(children: [//some containers, Container(child: SingleChildScrollView( child: Column(children: [//some children widgets])))]));
then I moved the SingleChildScrollView from wrapping the column to wrap the first container and that fixed the issue
Scaffold(child: PageView(children: [//some containers, SingleChildScrollView( Container(child: Column(children: [//some children widgets])))]));
This happen because we use white color in scaffold property backgroundColor
which cause an issue.
Remove Color property from Parent Scaffold widget and if you want to use color in parent widget so you can use theme property scaffoldBackgroundColor.
When I start to think about those two components I find myself arguing about why should I use one instead of the other. Some questions that come to my mind:
What are the differences between a Container and SizedBox?
I understand that Container can have other parameters like padding or decoration, but if I will not use those, why should I use a SizedBox instead of a Container?
There are performance differences between them?
Small Update: When used for whitespace, there is now even a linter warning to prefer SizedBox instead of Container. The main advantage seems to be that SizedBox can be const and won't even create a new instance during runtime.
Thanks to the magic of open source, you don't have to guess too much.
Container is basically just a convenience widget which sometimes saves you to nest 4 other widgets. If you pass width/height into the Container:
constraints =
(width != null || height != null)
? constraints?.tighten(width: width, height: height)
?? BoxConstraints.tightFor(width: width, height: height)
: constraints,
Which will result in:
if (constraints != null)
current = ConstrainedBox(constraints: constraints, child: current);
And the ConstrainedBox in effect is pretty much the same as a SizedBox, just more flexible.
A SizedBox will do:
#override
RenderConstrainedBox createRenderObject(BuildContext context) {
return RenderConstrainedBox(
additionalConstraints: _additionalConstraints,
);
}
BoxConstraints get _additionalConstraints {
return BoxConstraints.tightFor(width: width, height: height);
}
ie. It is effectively the same. If you only use Container for width/height there might be a very minor minor negligible performance overhead. but you most certainly will not be able to measure it.. But I would still recommend SizedBox because it's way clearer. imho.
I'd like to add that SizedBox is not only simpler, but it also can be made const, while Container cannot. This may or may not be something you need.
If you need a box with color you cannot use SizedBox. But https://pub.dev/packages/assorted_layout_widgets has the Box widget, which is something between a SizedBox and a Container: You can have color and it can be made const. Note I am the author of this package.
SizedBox() is a widget for giving some constant height or width between two widgets. It does not contain any decorative properties just like color, borderRadius etc.
On the other hand Container() is a widget that any person can modify according to his/her needs.
Just go through properties of both widgets you will see a huge difference between them.
SizedBox and Container creates a RenderObject. The RenderObject lives in the render tree and some computations are performed on it, even if it paints nothing on the screen.
We can do better, we can have a widget which does not create a RenderObject, while being still valid. The Nil widget is the minimal implementation for this use case. It only creates an Element and does nothing while it's building. Because the optimal way to use it, is to call const Nil(), it also comes with a nil constant that you can use everywhere (which is a const Nil()).