I have started experimenting with SwiftUI in order to port my app from UIKit to SwiftUI. Below is the code that is one of the building blocks. Basically, I want to place a 16:9 red subview in the center of the screen if current interface orientation is .landscape with a small offset to the left(offset dependent on safeAreaInsets). If the orientation is .portrait, then the red subview has aspect ratio 9:16 and is placed in the center with a small vertical offset (determined by safeAreaInsets). I have used device.orientation in the below code but I am looking for a better solution for a reason. Reason being that in UIKit, I could programatically turn on/off autorotation or fix orientation of view controller to a configured choice. I did not therefore rely on UIDevice orientation in UIKit. It doesn't seems to be straightforward in SwiftUI. I would not want to rely on device orientation therefore.
var body: some View {
Color.black
.ignoresSafeArea()
.overlay(alignment: .center, content: {
Color.red
.aspectRatio(aspectRatio, contentMode: .fit)
.ignoresSafeArea()
.offset(x:previewHorizontalOffset, y:previewVerticalOffset)
})
.persistentSystemOverlays(.hidden)
}
var aspectRatio:CGFloat {
if !UIDevice.current.orientation.isLandscape {
return 9.0/16.0
} else {
return 16.0/9.0
}
}
var previewHorizontalOffset:CGFloat {
if !UIDevice.current.orientation.isLandscape {
return 0
} else {
return -15
}
}
var previewVerticalOffset:CGFloat {
if !UIDevice.current.orientation.isLandscape {
return 15
} else {
return 0
}
}
You can use a
GeometryReaderto read the size of theViewand decide whether or not it'slandscapebased on that size:Note that
GeometryReadergreedily takes up space. If this affects your layout in unintended ways, you may want to use something like this: https://www.fivestars.blog/articles/swiftui-share-layout-information/