Few months ago, I encountered some difficulties in figuring out the orientation of our device. We have a screen which has rounded rectangles and can be scrolled horizontally. The sizes of these rounded rectangles are as follows:
For its width: screenWidth - (Left and Right padding)
For its height: it's computed proportional to the width
And you're right, this will only look good on iPhone portrait mode.
If we have an iPad or the devices in landscape mode, the rounded rectangles are too big, even taking up the whole screen on iPad landscape. To fix this, we want to set specific width and height for anything that's not iPhone portrait mode.
Before I add the code here, I'd like to talk about Size Classes first.
Size Classes
You don't think about orientation or device sizes when using Size Classes because the multitasking feature on iOS 9 make it possible to split the screen between different apps, and when that happens, device sizes just won't matter anymore. It helps us identify if we are in smaller or bigger space.
Based on UserInterfaceSizeClass Documentation from Apple:
SwiftUI sets the size class based on several factors, including:
The current device type.
The orientation of the device.
The appearance of Slide Over and Split View on iPad.
Here are the things you need to know about Size Classes:
Two types:
1. Horizontal (width)
2. Vertical (height)
Two traits:
1. Compact - smaller space
2. Regular - bigger space
As mentioned above, SwiftUI sets the size class based on some factors, one of which is the device type:
All iPhone devices on Portrait
Compact Width (Horizontal Class), and Regular Height (Vertical Class)
iPhone - Landscape
Compact Width (Horizontal Class), and Compact Height (Vertical Class)
But if you have and iPhone+ devices:
iPhone Plus - Portrait
Compact Width (Horizontal Class), and Regular Height (Vertical Class)
iPhone Plus - Landscape
Regular Width (Horizontal Class), and Compact Height (Vertical Class)
All iPad devices which have bigger screens, and bigger space, no matter the orientation, they will have:
Regular Width (Horizontal Class), and Regular Height (Vertical Class)
iPad Multitasking
But if you're doing multitasking on your iPad, the size classes traits will be different. And this is why I highlighted space, instead of screen. If you're running two applications, these apps are now sharing the same screen, one of which may have a bigger space than the other, or both can share equal space.
Landscape - Equal Space
Compact Width (Horizontal Class), and Regular Height (Vertical Class)
Landscape - Unequal Space
Primary App (Bigger Space)
Regular Width, and Regular Height
Secondary App (Smaller Space)
Compact Width, and Regular Height
When the apps are running in portrait mode, whether in equal or unequal space, it will have Compact Width (Horizontal Class), and Regular Height (Vertical Class)
Portrait - Un/equal Space
Compact Width (Horizontal Class), and Regular Height (Vertical Class)
Fixing the problem
Based on the problem I mentioned above, what I really need is to simply figure out if my device is an iPhone on Portrait mode. Here's how we fixed it:
private struct MyView: View {
@Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
@Environment(\.horizontalSizeClass) var horizontalSizeClass: UserInterfaceSizeClass?
var body: some View {
if horizontalSizeClass == .compact && verticalSizeClass == .regular {
// Compute rounded rectangle's size with device's width, and a height proportional to it via GeometryReader
} else {
// Set rounded rectangle's size with specific width and height
}
}
}
Comments