Layout of text and form get messed up when changing orientation

I’m new to Solar2D and have picked up someone else’s work. I have what I thought was a good framework but on my simple scene where the user enters a host to connect to, a username, and a password, the layout gets messed up when I change orientation. When I arrive at the scene in any orientation, it looks good but when I change, it doesn’t.

Has anyone come cross this? Is there sample code to point me to that demonstrates the correct way to lay out my text and form fields?

Are you able to share a few screenshots of how it looks when it’s correct, and how it appears after rotating?
My guess (without having seen your current layout) is that your app draws its UI elements based on the screen dimensions at startup, but that there is currently no listener in place to re-draw everything when the app rotates. So you rotate from portrait to landscape, and the UI layout stays in portrait aspect ratio.

If that’s the case you need to add an “orientation” listener (or better still a “resize” listener to account for devices that have an on-screen native UI bar that causes the screen dimensions to change when the device is rotated), and in that listener you would need to either move your UI elements around or simply destroy the scene and recreate it:

local function onResize( event )
    if system.orientation == "portrait" or system.orientation == "portraitUpsideDown" then
        --redraw your scene in portrait mode
    else
        --redraw your scene in landscape
    end
end
  
Runtime:addEventListener( "resize", onResize )

Yes, and thank you for your response. I’m a new user here and this site won’t let me place more than one embedded screen capture at a time. I’ll attempt to upload four screen captures one at a time then.

  1. Badly-formatted portrait: Home button should be further in the corner and all form elements should be just below “SETTINGS”.
  2. Well-formatted landscape
  3. Badly-formatted landscape: the Password label and field are at the top of the screen, labels and fields are far apart, and there are messages that appear based on validation of form input that are out of place, too.
  4. Well-formatted portrait

At the moment, I’m not explicitly adjusting the layout when the orientation is changed. My impression is that the engine would do that.

I’ll try your suggestion, though. Thanks again!

An example of my attempt to redraw an element is as follows, but it doesn’t appear to work. What’s the correct approach?

titleText.x, titleText.y = 800, 100
relayout.add(titleText)

You are using absolute positions. Try using relative positions like

	display.contentCenterY
	display.contentCenterX

Also, show us the code for the form field please.

Thank you for your response!

I’ll show how I’m setting up the label and form element for the password, which is getting messed up when I rotate.

local topInset, leftInset, bottomInset, rightInset = display.getSafeAreaInsets()
local _W = (display.contentWidth - ( leftInset + rightInset ))/ 2

PasswordText = display.newText("Password: ", 0, 0, native.systemFont, 48)
PasswordText.x, PasswordText.y = _W * 0.5 - 375, 700
[...]
local PasswordField = native.newTextField( display.contentWidth, display.contentHeight, 610, 64 )

As @sporkfin has said, we’d need to see a bit more of the code to work out what is going wrong.
There’s no context for exactly what is happening here:
relayout.add(titleText)
That’s not a built-in Solar2D function, so presumably the person who made the project before you has set that up.

Also, would I be correct in guessing that in your screenshots:

Screenshot 2 was where the app was opened in landscape, and then screenshot 1 was after rotating to portrait.
Screenshot 4 is where the app was opened in portrait, and then 3 is after rotating to landscape?

Yes, your guesses are correct.

This is my first foray into this platform, so please forgive the naive questions and poorly-constructed code. Relayout is loaded here:

local relayout = require('libs.relayout')

No need to apologise, your questions are written better than many I’ve seen over the years :smile:

Looking at that snippet, that’s still likely to be a custom library written by the previous coder on the project. The name would imply it’s for changing the layout, but there’s not much to go on there.
require('libs.relayout') means it’s loading a file called “relayout.lua” in a folder called “libs”, so that’s where I would look next. Hopefully the previous person added comments as they were working on the file, but that’s most likely wishful thinking.

As Sporkfin said, defining object positions/sizes with hardcoded numbers is generally bad form, because it doesn’t account for different size screens. Use fractions of the screen width/height is usually a better approach.

I had this going on in a previous iteration of my code, where I set up a function when the device was reoriented. I would base my coordinates off of these values.

  local safeX, safeY = (display.safeActualContentWidth - display.safeScreenOriginX), (display.safeActualContentHeight - display.safeScreenOriginY)

So in that example safeX and safeY are the usable width and height of the screen, rather than being used as X and Y values? If that’s the case I would personally I would call them safeW and safeH to make them reflect what they represent a bit better, but then again I’ve had more than my fair sure of ambiguously named variables in the past.

That’s the right approach though (in my opinion). Then when you set positions of objects, if for example you want the object to be 1/3 across the screen and 2/3 down the screen you would do something like:


--in main.lua
--Since these kinds of variables would get used in many places, I tend to make them global and give them short names
minX = display.safeScreenOriginX
minY = display.safeScreenOriginY
safeW = display.safeActualContentWidth - minX
safeH = display.safeActualContentHeight - minY

--in your login scene:
myTextObject.x = minX + (safeW * 0.333)
myTextObject.y = minY + (safeH * 0.666)

Then in the “resize” listener, recalculate the min/safe global values and then set the myTextObject x/y positions again.

1 Like

I had been using onOrientationChange before, rather than onResize.

In theory the “orientation” listener should be fine, but there are cases where the screen size changes without the orientation changing such as when a native Android UI bar appears on screen (depending on the UI mode). In that example screen which was previously 1080 x 1920 might then change to 1080 x 1890.
An orientation change should also trigger a resize though (because the 1080 x 1920 screen is now 1920 x 1080), so I tend to use resize just to both all of those scenarios.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.