How Control
s are positioned
There are three intended ways to position a Control
in Godot:
Placed in a Container
. In this case the Container
will control position and sizing of the child Control
, taking into account "Size Flags".
See also Using Containers, and Containers.
By anchors (anchor_*
) and margins (margin_*
). They determine the position of the edges of the Control
. The anchors are factors, and the margins are offsets.
For example, the leftmost part of the Control
will be positioned at anchor_left * parent_width + margin_left
, relative to the parent Control
.
You will find presets in the "Layout" menu that appears in the tool bar when you have a Control
selected.
See also Size and anchors.
By rect_position
and rect_size
. These are relative to the top left corner of the parent Control
.
Ultimately the other ways to position the Control
are changing these. And you can also change these even if you positioned the Control
by other means… Which is not intended, but supported (because it is useful to add animations to the UI among other things).
Regardless of which one you use, Godot will respect rect_min_size
. And yes, there is also rect_rotation
and rect_scale
which throw a wrench on the above explanation, but they works as you would expect.
And yes, it is not the easier to use system. Because of that, the designer is being improved for Godot 4 (currently on Alpha 3 at the time of writing).
To answer the question the title: If your stretch mode is set to disabled
, and your UI is anchored to the top left (which is the default), you would resize the window and the UI would not scale or adapt to that change. I don't think you don't want the UI to adapt.
Making a top and bottom bars with containers
You can use a VBoxContainer
, since we will have three bars stacked one on top of the other, vertically. And yes, the second one is a spacer.
First of all, you want the VBoxContainer
to take the whole screen. So set it to the Layout preset "Full Rect". So, yes, we are placing the Container
by anchors and margins.
And second, we want the spacer to take as much space as possible. To archive this we set "Expand" flag on size_flags_vertical
of the spacer. This is what Size Flags are for.
And, of course, what you place inside the Container
might or might not be more Container
s.
Making a top and bottom bars with anchors and margins
Give the top bar the "Top Wide" preset. It will set the margins and anchors to have it stay at the top, take the full width, and take its minimum height.
And give the bottom bar the "Bottom Wide" preset. It will set the margins and anchors to have it stay at the bottom, take the full width, and take its minimum height.
You would need no spacer.
And, by the way, I remind you that anchors are margins are relative to the parent. So you can nest this approach. And yes, Control
s that are not containers can also have children Control
s
About stretch modes
As you know you have a choice between:
viewport
: All the sizes will be computed with the original resolution, and then the resulting sizes are scaled to the resolution of the device.
2D
: will also compute all the sizes with the original resolution, but instead of scaling the resulting sizes, it renders at that size and scales the image.
disabled
: It will compute all the sizes with the actual resolution of the device. No scaling will happen.
Since both viewport
and 2D
, the size of the UI will not be computed with the actual resolution of the device. This makes the approaches I described to have the UI adapt less effective (less useful or less necessary, depending how you look at it). And thus, if we want to use those approaches effectively we will want the stretch mode set to disabled
.
And, of course, there is also the aspect setting.
See also Multiple resolutions and Support multiple form factors and screen sizes.
Designing for small resolution
You can test on the editor how the UI adapts to the resolution, either by resizing the window, or by setting the Test Width and Test Height in Project Settings. You can, of course, also test on an actual smartphone. For instance, I often launch the game in my Android from the Godot editor when developing mobile games.
Circling back to the stretch modes, this is what happens with the text:
disabled
: The text stays the same size. This means that the UI can become too small for the text.
viewport
: the text scales. This means that the text can become too small to be legible.
2d
: the text scales too… except since it is a image scaling it can become blurry, even harder to read.
If we only consider the text, there is no good option. Now, either design the UI for the specific target resolution… Or make one that can adapt. And for one that can adapt, I believe disabled
is the best stretch mode as I was arguing above.
And of course you can script it
If you need to run some code when the resolution changes, you can connect to the "size_changed"
signal of the root Viewport
. And if you need to figure out if the device is in landscape or portrait mode you OS.screen_orientation
, and if you really have to, you can create a custom Container
.