Invoking Auto-Layout when iPad is rotated

Auto-layout sets the size and spacing of some canvases based on the size of the iPhone or iPad screen. The code is in the Open event of the canvas. Now that we have to support all orientations of the iPad I need to re-calculate auto-layout when the iPad is changed from portrait to landscape.

After 25 years with Xojo I am embarrassed to admit I can’t figure out how to do it.

Its extremely messy.

You need to create new named constraints and apply those, and even then I don’t find it always works reliably. But I may be missing something too.

I have code like this:

if isportrait then
mycontrol.DataSource = thechart
mycontrol.Refresh
if Constraint_portrait <> nil then Constraint_portrait.active = true

else
mycontrol.DataSource = nil
mycontrol.refresh
if Constraint_portrait <> nil then Constraint_portrait.active = false
end if

constraint_portrait is a variable of type iOSLayoutConstraint

I set mine up in a screens open event like this:

try
Constraint_portrait = new  iOSLayoutConstraint(myControl, iOSLayoutConstraint.AttributeTypes.width,  iOSLayoutConstraint.RelationTypes.Equal, _
self, iOSLayoutConstraint.AttributeTypes.width,0.02,60)

me.AddConstraint Constraint_portrait
catch
end try






I haven’t had to code this case myself, but in SwiftUI this seems to work out of the box, without a single line of code to add by the developer.

1 Like

Mostly it does with Xojo too: a button or canvas which is set to cling to top, side and bottom will continue to do so when rotated.

My needs were to display a ‘normally invisible’ control when in portrait mode , and not when in landscape. If it was visible all the time, I wouldnt need to do that. Maybe that’s Tom’s need.

Theres no nice easy way to create a “set” of constraints but thats really what you want

Ones that are only active in certain orientations

So the best you can do is as JefftT notes

Make one bunch for landscape and another bunch for portrait an d then you can activate & deactivate them based on the orientation

Unfortunately size and orientation “sets of constraints” dont exist but it would sure be handy if they did for exactly this

You can set them up in the IDE with names OR at runtime

It is nothing what I understand that apple is not providing an API to set the orientation. Sometimes that is really needed. It’s here the case. Android provides this in it’s api and with:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
you can set it to Landscape and with _PORTRAIT you can set it to portrait. But apple has no interest programmers being able to set a fixed orientation.

I have the same problem in some applications. Only possible way is: configuring the orientation fixed or providing two screen formats for portrait and landscape.

Your answers inspired me to keep trying. I have found a way to re-apply auto-layout when the iPad is rotated.

First thing is the simulator (26.0) does not fire the MobileScreen.OrientationChanged event reliably. For me it fires at startup and never again. I will have to build and test on a real iPad to determine if the problem is simply the simulator.

But the MobileScreen.Resized event does fire reliably when I rotate from portrait to landscape so I used that event to re-invoke auto-layout.

I have always had defined auto-layout parameters and a set of sizes and spacings for each iPad screen size. Just had to add new screen sizes for the landscape orientation. Here is some code:

SetColorSqrSize (scrnWidth as Integer, ByRef w as iOSLayoutConstraint, ByRef h as iOSLayoutConstraint, ByRef l as iOSLayoutConstraint)
select case scrnWidth
case 744 //Mini6Gen
h.Offset=56
w.Offset=56
l.Offset=kPadLeft25
case 768
h.Offset=60
w.Offset=60
l.Offset=23

Here is the code called by the Resized event:

dim reOrient as Boolean
dim w as iOSLayoutConstraint
dim h as iOSLayoutConstraint
dim l as iOSLayoutConstraint

//first save pCurrentOrientation for comparison
dim previousOrient as integer=app.pCurrentOrient
//now set new orientation
app.SetCurrentOrientation
select case app.pCurrentOrient
case 0
//do nothing
case 1
if previousOrient<>1 then
reOrient=true
end if
case 2
if previousOrient<>2 then
reOrient=true
end if
end select

if reOrient then
dim wArray() as string=Array(“clrSqr0Width”,“clrSqr1Width”,“clrSqr2Width”,“clrSqr3Width”,“clrSqr4Width”,“clrSqr5Width”,“clrSqr6Width”,“clrSqr7Width”,“clrSqr8Width”)
dim hArray() as string=Array(“clrSqr0Height”,“clrSqr1Height”,“clrSqr2Height”,“clrSqr3Height”,“clrSqr4Height”,“clrSqr5Height”,“clrSqr6Height”,“clrSqr7Height”,“clrSqr8Height”)
dim lArray() as string=Array(“clrSqr0Left”,“clrSqr1Left”,“clrSqr2Left”,“clrSqr3Left”,“clrSqr4Left”,“clrSqr5Left”,“clrSqr6Left”,“clrSqr7Left”,“clrSqr8Left”)
dim i as integer
for i=0 to 8
w=self.Constraint(wArray(i))
h=self.Constraint(hArray(i))
l=self.constraint(lArray(i))
SetColorSqrSize(self.Size.Width,h,w,l)
next
end if

The secret here is the “self.contraint” knows which canvas is referred to by the constraint name.

1 Like

See, you developed the solution :slight_smile:. Congratulations.