I’m looking for a way to rotate iOS UI, without rotating the game view.
The game I’m working on supports multiple orientations, but the game view takes care of the rotation and all animation related to that orientation change and should be rendered as if it’s portrait at all times.
Currently I have the app locked to only support portrait and when the phone is rotated the game rotates. But the home bar and control center stay portrait, which is sort of ok, but I’d like the app to fully support landscape.
As it i now, I listen to orientation notifications
func ListenToRotationUpdates() {
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
NotificationCenter.default.addObserver(
self,
selector: #selector(deviceOrientationDidChange),
name: UIDevice.orientationDidChangeNotification,
object: nil
)
}
Which will set the orientation within the game
@objc func deviceOrientationDidChange() {
let orientation = UIDevice.current.orientation
if orientation == .unknown || orientation == .faceUp || orientation == .faceDown {
return
}
self.gameScene.Set(orientation: orientation)
setNeedsStatusBarAppearanceUpdate()
}
is there a way to keep a view portrait while the app rotates the OS normally?
2
Answers
Well it depends on how are rotating the game view. Do you use some external library that handles it itself? Do you recalculate view frame and bounds? So final execution of your idea really depends on these factors. Generally the most common way of handling rotation in
UIViewController
is inviewWillTransition
function, which handles all rotations animation aligned and happening at the same time. Therefore if you want to somehow recalculate the view back to portrait sizes, I recommend using this function. here is an example:One of possible solutions is to split your application to "rotating" part and "non-rotating" part using windows.
It is not an ideal choice but lately the tools that we get do not give us much options. The problem you are facing when using this procedure is that you can have some chaos when presenting new view controllers. In your case this may not be issue at all but still…
In short what you do is:
You can create all of these in code or with storyboard. But there are a few components to manage. These are all I used when validating this approach:
This is the controller at the bottom. I expect this one will host your game. You need to preserve
the rest may be changed, removed.
This controller will deal with rotating stuff. You need to preserve
which may both be set in storyboard as well. Anything you put onto this controller will rotate with your device. A nice place to put some GUI stuff for instance.
This is what I used as base class for both view controllers above. It is not much but it allows view controllers to be shown in a new window. This code was pasted from one of my older projects and could use some minor improvements. But it does works so…
These are the two subclasses to let touch events go through. A quick explanation on how this works: When event is received your system will first send this event through your view hierarchy asking "who is going to handle this event?". Returning
nil
means "not me" and default forUIView
isself
. So in this code we say: "If any of my subviews wants to handle this event (such as a button) then it may handle this event. But if none of them wants to handle them then neither I will."And
UIWindow
is a subclass ofUIView
so we need to deal with both of them.This is an example on how to use it all together. As promised, either using Storyboards or manually, both should work.
Seems like a lot of work but you need to set it up once and never look at it again.