Can I fix MediaQuery.of(context) to constant value? - dart

To make responsive application, I'm using MediaQuery.of(context) for every component size, but it is hard working to write for each section.
Therefore, I fixed it to constant and is it right handling?
class ScreenUtil {
static double width;
static double height;
}
void initializeConstants(BuildContext context){
ScreenUtil.width = MediaQuery.of(context).size.width;
ScreenUtil.height = MediaQuery.of(context).size.height;
CurrentPlatform.platform = Theme.of(context).platform;
}

No, this is a bad idea.
The reason why we need .of(context) is to always fetch the latest object so we can ensure that the widget correctly updates itself when the inherited value changes.
The MediaQuery.of(context).size is not a constant. Instead it will dynamically update itself when the user rotate the screen, for example, from portrait mode to horizontal mode, and in that scenario its width and height would get flipped.
It is not a good idea in general to strip any of the .of(context) off and assuming they are constants. The time complexity of calling this method is O(1) according to Flutter's in-code dartdoc:
Calling this method is O(1) with a small constant factor, but will
lead to the widget being rebuilt more often.

Related

Resize `xterm.js` height to fit contents automatically

I'd like to use an xterm.js session that perfectly fits the height of the current contents. So every time a line is added, the size would adjust to fit that new height. The height would never be bigger than it needs to be but a scrollbar would never be shown.
I can't figure out a way to either use the fit plugin to accomplish this or to check the contents of the current xterm.js session to manually resize the row count as needed.
Beside what I wrote in the comment above, you might get away with a simpler solution by doing the following schematically (untested):
const MAX_ROWS = 20; // test upfront, as it depends on font metrics etc.
let visibleRows = 1; // start with one visible row
const term = new Terminal({
// setting scrollback is important to not lose data early
scrollback: MAX_ROWS - visibleRows,
rows: visibleRows,
...
});
// when data comes in, use the write callback to adjust terminal height
term.write(data, () => {
// get current buffer length (visible rows + rows in scrollback)
const bufferLength = term.buffer.active.length;
if (bufferLength > visibleRows) {
// resize will pull scrollback lines back into visible area
// since we have MAX_ROWS in place, bufferLength will never
// exceed your supported area (everything else is discarded)
term.resize(some_cols, bufferLength);
visibleRows = bufferLength;
// adjust scrollback to stay within (MAX_ROWS - visibleRows) constraint
// drops to 0 once we hit MAX_ROWS
term.options.scrollback = MAX_ROWS - bufferLength;
// finally adjust your container height
adjustContainerHeight();
}
});
function adjustContainerHeight() {
// can be implemented by reversing FitAddon.proposeDimensions
// maybe easier: test upfront and do a rows -> px_height mapping
...
}
Downside of this simpler approach - it might give you ugly resizing artifacts during incoming data, esp. the terminal height might jump in between and show a scrollbar for a short amount of time. If thats a showstopper for you - the double terminal approach should avoid the in between jumps and scrollback flickering.
Furthermore both ways rely on term.resize, which might trigger cmdline apps on a real PTY to resend data. This cannot be avoided, the terminal interface is meant to work that way (the application decides that on its own).
Maybe this helps.

Autoresize Text to fit in Container vertically

I want to create an app, that shows sometimes shorter, somertimes longer text in a Container. This container should not change in size, after the widget is build to fit with the size of the screen. The text itself comes from a database and I don't know, how long it can be.
When I print the text in the container, sometimes it fits, sometimes there is many space above and below, when the text is short, or sometime the text overflows and is not visible.
I want, that the text size is automatically changed to fit into the container. Container with overflow
The flutter package Auto-Size-Text is not working for me, because I only could resize the text to fit the width or set the maximum line, which I don't know either.
This is my code simplified:
AutoSizeText autotext = AutoSizeText(text, style: style, textAlign: TextAlign.center, presetFontSizes: [25.0,22.0,20.0,18.0], semanticsLabel: text);
Container(
child: autotext
);
TL;DR:
Your AutoSizeText widget is probably provided with unbounded constraints.
This can be the case if it's wrapped in a Column, Row, ListView or something similar.
To counter this issue, wrap it in an Expanded widget.
In order to answer that question, we need to understand how Flutter performs the layout.
Basically, the top widget's height and width (called its "dimensions") are requested by the framework, which provides a min and max width and height (called "constraints").
In order to calculate its dimensions, the widgets ask their children what dimensions they want to have based on some constraints.
So, every widget gets told constraints and returns concrete dimensions within these constraints.
Widgets like ListView or Column don't want to influence their children's dimensions too much - they should simply be as small as possible.
In order to communicate that, they are given a maximum width/height of double.infinity, telling them that they should default to their "natural"/default dimensions. A constraint of this type is called "unbounded".
Here's a Google Tech Talk video about Flutter's rendering pipeline, where all of this is described in greater detail.
With this process in mind, let's have a look at how your widgets perform during layout:
In a comment to your post, you said there's a Column widget, so I assume there's a Column containing a Container, which in turn contains the AutoSizeText widget.
If instead of a Column, there's a Row or ListView or something similar, the process is basically the same.
The Column wants its children to be as small as possible, so it passes unbounded constraints to all of its children.
Being one of those children, the Container receives those unbounded constraints.
Because the Container itself is just a wrapper class, it simply passes these constraints on to its child, the AutoSizeText.
The AutoSizeText receives unbounded constraints.
Looking at its source code, we can see that it starts with a default text size and checks if it fits (calling _checkTextFits).
If it doesn't fit, the text size is decreased and this process is repeated until the text is small enough to fit into the given constraints.
Because in your case, the constraints are unbound, the text fits on the first try - that means the widget simply uses the default size.
Having determined the text size, it can calculate the text's dimensions and returns them up the tree.
The Container receives those dimensions.
Because it's just a wrapper class, it simply returns them to its parent in turn.
Finally, the Column receives the dimensions and sizes itself around that (probably adding the dimensions of other children).
Solution
You don't want to pass unbounded constraints to an AutoSizeText widget, because that defeats the purpose of the widget in the first place - fitting text into bounded constraints.
You can confirm this is the problem by hardcoding the Container's width and height, that should make the AutoSizeText widget adjust the text size properly.
If the Container is placed inside a Column or something similar, you can always bound the constraints by wrapping it in an Expanded.
Why the solution works
The Column checks which of its children are Expanded widgets.
It first lays out all the other widgets.
Only then, it divides the remaining space among the Expanded widgets according to their flex factors (that's a whole other topic for itself).
That means the Expandeds' children will receive bounded constraints.
If you wrap your Container in an Expanded and it's the only expanded in the Column, it should take all the remaining space, and fit the text perfectly within itself.

Method signature and compiler disagree on struct-return-edness [duplicate]

I have run into a very strange behaviour I can’t make sense of. I have a Texture class with contentWidth property of type int. This class is wrapped in a Image class that has a width property of type int. The width of an Image is computed simply as the contentWidth of the underlying texture:
- (int) width
{
return texture.contentWidth;
}
Now the Image is used by a Button class (by composition, not inheritance) that wants to read the image size:
// image is of type ‘id’
int width = [image width];
int height = [image height];
The problem is that the height variable gets set just fine, whereas the width variable contains NaN (–2147483648). I have checked the dimensions – they are about 200×100 or so, nowhere near the int limit. Also the Xcode debugger tooltip shows both properties in the Texture correctly, only after the width gets through the two accessors the number gets garbled. The objects are not freed. What am I missing?
Update: I have expanded the accessor in the Image class to see where the problem originates:
- (int) width
{
const int w = texture.contentWidth;
return w;
}
Now when I break on the first line, the w gets set correctly. I step over, the execution returns to the calling function:
- (void) foo
{
int bar = [image width];
}
…and now the bar contains NaN.
Update: Mhm, got it:
int foo = [image width]; // image is id, returns NaN
int bar = [(Image*) image width]; // correct value
The image is declared as id, which is the point here. Could somebody explain this? I have got a feeling I am not calling the right width method, but what exactly is going on here? I always type my variables as strictly as possible, but here the id type is handy. I had no idea it could result in such a bug.
Oh well. If you are interested in why this situation happens, see the Objective-C Programming Guide, chapter 8, Return and Argument Types:
In general, methods in different
classes that have the same selector
(the same name) must also share the
same return and argument types. This
constraint is imposed by the compiler
to allow dynamic binding. Because the
class of a message receiver (and
therefore class-specific details about
the method it’s asked to perform),
can’t be known at compile time, the
compiler must treat all methods with
the same name alike. When it prepares
information on method return and
argument types for the runtime system,
it creates just one method description
for each method selector.
However, when a message is sent to a
statically typed object, the class of
the receiver is known by the compiler.
The compiler has access to
class-specific information about the
methods. Therefore, the message is
freed from the restrictions on its
return and argument types.
Here’s a bug report in the GCC bugzilla (and a corresponding blog post). The behaviour is not a bug, but it isn’t very friendly either, because the compiler does not warn you (at least not with the default warning settings).
Shouldn't your accessor be:
- (int) width
{
return [texture contentWidth];
}
Is texture an instance variable? If it is, did you make super to initialize it in the init method or your wrapper class?

Farseer Create Rectangel Width Height

In Farseer XNA4.0 C# Physics engine based on Box2D
if i use BodyFactory.CreateRectangle(world, w, h, density, new Vector2(x, y)); method to create a body
how can i get the width and height back from the body?
currently im saving the width and height but im wondering if it can be retrieved from a fixture or shape or something. have made some attempts but to no avail. it would save me two floats per entity that im creating.
thanks for any help.
Ill preface this by saying i've never used Farseer, but looking at the class definitions, it doesn't look like there's a simple way to get what you want. If you look at the BodyFactory.CreateRectangle method, it doesn't store directly the Height or Width values:
public static Body CreateRectangle(World world, float width, float height, float density, Vector2 position,
object userData)
{
if (width <= 0)
throw new ArgumentOutOfRangeException("width", "Width must be more than 0 meters");
if (height <= 0)
throw new ArgumentOutOfRangeException("height", "Height must be more than 0 meters");
Body newBody = CreateBody(world, position);
Vertices rectangleVertices = PolygonTools.CreateRectangle(width / 2, height / 2);
PolygonShape rectangleShape = new PolygonShape(rectangleVertices, density);
newBody.CreateFixture(rectangleShape, userData);
return newBody;
}
Instead, it creates a set of vertices that it assigns to the shape of the body (in this case a rectangle), however, it doesn't appear from a cursory glance that there is a way to get at these vertices.
So long answer short, there isn't a direct method that I can find that will give you the straight float value of the height or width of your rectangle. You might be able to get at the vertices in some way and calculate it back out, but this would require you taking the Body and parsing through its fixture list and figuring out which one is your rectangle.
At the end of the day, if you need to get directly at your Height and Width, I would recommend just creating a custom class and storing the body together with the float values, and using getters/setters. It's likely to be a less expensive operation than looping through every fixture on your objects and trying to determine which is your rectangle and then calculating it back out.

How to layout fields correctly

I've been trying to layout fields in blackberry and when I think I have it working I try another simulator and my field's are laid out differently.
If I call setPositionChild(field, 0, 100); I would expect on all phone resolutions that
the fields would be positioned at position x=0, y=100. This is not the case.
Reading the RIM doc for setPositionChild, the y parameter is - "y - Offset of the top of the field in its manager." The y offset returned by field.getTop is consistently 0, so position should be consistent across screens? Maybe a good explanation of how setpositionChild works would suffice.
Thank you.
I suspect your variable results are from extending MainScreen. That class contains separators etc that will be offsetting your 0,100 to something else.
Either try using FullScreen which is a single VerticalFieldManager
Or override sublayout on your MainScreen and set its width and height to the full size of the display.

Resources