Why does a newly added widget have no allocation? - gtk

I want to add a widget to the bottom of a scrolled window, then scroll to the bottom of that window. However, the window thinks it is already at the bottom, because the widget has still not been allocated. I.e., this returns -1:
widget.get_allocation().y
Why is this? Is there any way to force the widget to be allocated immediately, so I can adjust the window accordingly? Or is there a better solution?

The better solution is to hook up to the widget's size-allocate signal and defer your scrolling calculation until then.

I'm not 100% sure I understand what you're trying to do, but still: At a minimum, you need to realize the widget to get it to compute those things. But see the note in the linked-to documentation, and investigate if those ways don't work better.

Related

Manage Device Sizes MediaQuery Globally

What is the proper way to handle device size globally. The idea is not to have a [MediaQuery.of(context).size.width] on each screen of the app. There is already a question and answer about it, but the only answer is out of date because there was no null safety yet.
The answer suggests creating a constants.dart file, like in the image below:
1
And initialize in the build of the first widget of the application:
2
The problem is that for it to be constant it must have a value, and not wait for the first build. It is also true that the value canchange based on device orientation and I would like to handle this as well.
I have doubts about it. if someone can help me
You cannot save the screen dimensions as a constant, because they will change if the device is rotated, or when the screen is resized, such as for desktop and web apps.
Instead you should be pushing your cutpoint decisions as low as possible, using LayoutBuilder.
LayoutBuilder seems preferable over every use of MediaQuery for sizing a viewport (either the whole screen, or the space left in a column or other layout).
LayoutBuilder also works hard to avoid rebuilding its child if the size doesn't change and the parents haven't had to re-layout.
The builder function is called in the following situations:
The first time the widget is laid out.
When the parent widget passes different layout constraints.
When the parent widget updates this widget.
When the dependencies that the builder function subscribes to change.
The builder function is not called during layout if the parent passes the same constraints repeatedly.
And you don't have to think about "the height of the appbar" ever again, because you're getting the space left, not the total space on the screen.
Check it out: https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html

Is there a way to know the dimensions of a widget before laying it out on the screen?

I'm trying to implement a breadcrumb widget in my Flutter app and I would like to achieve the following behavior:
Let's say the red outlined area is the space I have for my breadcrumb and that each element of the breadcrumb has a different width. The breadcrumb should be responsive, i.e. it should show elements as long as there is enough space to show them, otherwise, remove some of the elements and add that '...' button in the middle. Clicking on that button shows an overlay that contains the removed elements.
Now, I want to know how much space each breadcrumb element will take before it is laid out on the screen. Only then, I can decide whether there is enough space for it to be shown in the breadcrumb or it should be part of the '...' button.
I tried to use CustomMultiChildLayout which gives you information about how much space a widget takes after laying it out. It also needs to layout each child once, which makes it unuseful in my use case.
P.S: Think about the breadcrumb used in the apple documentation. That's the same behavior I want to achieve.
Short answer, you can't.
You were already using CustomMultiChildLayout, that's good, it shows me that you should have some basic understanding of how flutter rendering pipeline works. Then it should be clear to you of the 3 steps: parent passes down constraints, child reports its size, parent decides where to place the child. So in short, again, you cannot get children's size before layout.
Now move on to the thing you want to achieve. I agree CustomMultiChildLayout cannot achieve what you want to do, but not for the reason you listed. The main problem is CustomMultiChildLayout forces you to layout each child once, and then position them. You must position each child, you cannot skip a child if you don't like it (too big), and you cannot fabricate new stuff that's not your children. If you could achieve these 2 things, then getting children's size after layout isn't going to be a problem.
To achieve those, the easiest way is to use CustomPaint, if everything you need to do, are text-based or just simple shapes. Use TextPainter to layout a text, get its size, then decide whether to paint that text, or paint "..." (skip a child and fabricate your own) instead. You can search on how to do these things easily, but mostly search on TextPainter.
If you want to paint other widgets as your children, and optionally skip some of them while fabricating others, you should write your own RenderObject. That is one level lower than "widgets-level". If you have never done that before, you can research on that topic as well.

How can you know when user scroll to next widget in list flutter (widget before not visible anymore)

I have a ScrollablePositionedList and want to do stuff when the next Widget in the List is scrolled to. How can I detect that? I have tried with NotificationListener and ScrollUpdateNotification but only saw the option to use the height of each widget which is flexible and it would be kinda ugly to do it like this. Is there a better way? Like see the pixel height of a widget or is there a function I could use?
You should be able to monitor what items are visible on screen with:
itemPositionsListener.itemPositions.addListener(() => ...);
Then, based on this. you can see whenever there is a change, whenever a new item is scrolled to / appears in the list. then make whatever changes you want
Here is the documentation for more info

How to check visibility of a Flutter widget even when covered by another

I'm trying to find a way to check the visibility of a Flutter widget when it's either off screen or when it's obscured by another, for example Drawer, Dialog or BottomSheet.
visibility_detector helps with checking whether it's on the screen or not but does not work with the second use case (known limitation).
Is there a lower lever api that I can use to check whether a widget is actually visible to the user?
My use case: I'm adding a widget to the Overlay when something external happens (similar to Tooltip but not on long press). If the user opens for example the Drawer, the widget will appear on top. I want to detect that the child is not visible and delay or cancel the action.
Do I understand your problem?
You have a widget you want to always be on top?
You want the user to interact with that widget first before doing other things?
Use design patterns to make coding easier, your users will thank you.
You can show a Dialog on-top of other widgets with the showGeneralDialog or showDialog functions. Because Dialogs are a design-pattern used in many apps, users will already know how to use them.
Define app behavior with explicit state.
It is too hard to derive app behavior from rendered UI, not all devices are the same size and shape. This means you should try to write a variable that describes your situation and then write the code you need to make that variable's value correct. It sounds like you want a variable like bool overlayIsShowing.

how to "dark out" widgets in the background?

I want to "dark out" all widgets, except a special widget which the user is working with.
This special widget should be on a predefined position. Everything else should be "darked out".
Is there an easy way to acchieve a result like this?
What I did is:
- put on every element an overlay except one element
The problem is that this overlay is not laying over the whole screen (you see it ends on the top of my picture and I think this solution is not the cleanest as it is very complicated to control:
What you describe sounds like modal barrier color, and modal barrier behavior. The easiest way to achieve that is by using showDialog function.