My google mapView is not rotating according to my device orientation. Wondering how can I make it rotate accordingly?
I'm using the following to detect orientation changes. The landscape is being detected but I want to be able to make the map rotate too. Any help is appreciated, thanks!
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
#objc func rotated() {
if UIDevice.current.orientation.isLandscape {
print("Landscape orientation")
} else {
print("Portrait orientation")
}
}
Related
I'm done with the auto-layout stuff in my iOS universal App, and it's working perfectly in portrait. However, I want the user to be able to rotate the device and play the game in landscape mode. The problem I'm facing is that I don't want the layout to change at all, and only change the controls of the game (sliding up the screen should make the player go up in both orientations).
Thing is, I don't know how to prevent orientation from changing the layout and at the same time be able to change behaviour based on the orientation. Do you guys have any idea how I could manage that?
Did found a way to do, for future reference, when an orientation is disabled, we still can access device orientation (and not interface orientation), and register a notification to act upon change.
class ViewController: UIViewController {
var currentOrientation = 0
override func viewDidLoad() {
super.viewDidLoad()
// Register for notification about device orientation change
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
NotificationCenter.default.addObserver(self, selector: #selector(deviceDidRotate(notification:)), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
// Remove observer on window disappears
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
if UIDevice.current.isGeneratingDeviceOrientationNotifications {
UIDevice.current.endGeneratingDeviceOrientationNotifications()
}
}
// That part gets fired on orientation change, and I ignore states 0 - 5 - 6, respectively Unknown, flat up facing and down facing.
func deviceDidRotate(notification: NSNotification) {
if (UIDevice.current.orientation.rawValue < 5 && UIDevice.current.orientation.rawValue > 0) {
self.currentOrientation = UIDevice.current.orientation.rawValue
}
}
}
Currently my App looks like this in portrait mode:
but when my iPad is in landscape mode I want my Icons look like this:
By now it looks like that in landscape mode:
I know how to rotate the icons but I don't know where I have to paste the code. I just want to look my app in landscape mode like the 2nd pic.
EDIT
It should look like this one:
you need to set observer using NSNotificationCenter following code
NSNotificationCenter.defaultCenter().addObserver(self, selector: "deviceOrientationChnaged", name: UIDeviceOrientationDidChangeNotification, object: nil)
in AppDelegate didFinishedLaunching method.
And in observer method you check for orientation
if(UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation))
{
print("landscape")
}
if(UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation))
{
print("Portrait")
}
You should manage it from Assets if your deployment target is equal or greater than 8.0. You can set different images for different size class. For example for Portrait mode in iphone you can set assset forCompact width Regular Height size class and for iphones in landscape you can set asset for Any width Compact Height size class.
Refer apple documentation for Customizing Assets for Size Classes
You need to rotate your yourimageview by 90 degree in landscape mode -
In AppDelegate.swift inside the "didFinishLaunchingWithOptions" function I put:
NSNotificationCenter.defaultCenter().addObserver(self, selector: "rotated", name: UIDeviceOrientationDidChangeNotification, object: nil)
and then inside the AppDelegate class I put the following function:
func rotated()
{
if(UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation))
{
print("landscape")
//Rotate 90 degrees clockwise:
yourimageview1.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
//Rotate 90 degrees counterclockwise:
yourimageview2.transform = CGAffineTransformMakeRotation(CGFloat(-M_PI_2))
}
if(UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation))
{
print("Portrait")
}
}
Hope this helps anyone else!
Try as following in your ViewController.m
-(void)viewDidLoad
{
NSNotificationCenter.defaultCenter().addObserver(self, selector: "deviceOrientationChnaged", name: UIDeviceOrientationDidChangeNotification, object: nil)
}
- (void) deviceOrientationChnaged:(NSNotification *) notification
{
if(UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation))
{
print("landscape")
yourimageview.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
//OR Rotate 90 degrees counterclockwise:
yourimageview.transform = CGAffineTransformMakeRotation(CGFloat(-M_PI_2))
}
if(UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation))
{
print("Portrait")
}
}
Hope this will help.
EDIT:
Please check my this question: LINK
How can I just rotate the buttons when my device is in portrait or landscape mode? I know something like that:
button.transform = CGAffineTransformMakeRotation(CGFloat(M_PI))
But where I have to call it up in my code?
I don't want to set my device in landscape mode, I just want to rotate the icons when it should be in landscape mode.
Thanks in advance!
You should override func
viewWillTransitionToSize(_ size: CGSize, withTransitionCoordinator coordinator:UIViewControllerTransitionCoordinator)
And call transform there
Don't forget to assign CGAffineTransformIdentity when rotated back
More about rotation: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIContentContainer_Ref/index.html#//apple_ref/occ/intfm/UIContentContainer/viewWillTransitionToSize:withTransitionCoordinator:
The best way to do this is viewDidLoad add this line of code bellow:
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(rotate), name: UIDeviceOrientationDidChangeNotification, object: nil)
and then in function rotate in case of device orientation do some code like this:
func rotate(){
if UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation) {
//your code here in landscape mode
}
if UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation){
//your code in portrait mode
}
}
this solution is simple and really easy to do.
I guess you know how to "rotate" the buttons already, so I'll just tell you how to know that the device has rotated.
In a view controller, override willRotateToInterfaceOrientation:
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
}
In the method body, you can check the value of toInterfaceOrientation to know which orientation the device is rotating to. For example:
switch toInterfaceOrientation {
case Portrait:
// some code here...
default:
break
}
Previously if one presented a keyboard on one's own app one would embed everything in a UIScrollView and adjust the contentInset to keep content from being obscured by the keyboard.
Now with split view multitasking on iOS 9 the keyboard may appear at any moment and stay visible even while the user is no longer interacting with the other app.
Question
Is there an easy way to adapt all view controllers that were not expecting the keyboard to be visible and without start embedding everything in scrollviews?
The secret is to listen to the UIKeyboardWillChangeFrame notification that is triggered whenever the keyboard is shown/hidden from your app or from another app running side by side with yours.
I created this extension to make it easy to start/stop observing those events (I call them in viewWillAppear/Disappear), and easily get the obscuredHeight that is usually used to adjust the bottom contentInset of your table/collection/scrollview.
#objc protocol KeyboardObserver
{
func startObservingKeyboard() // Call this in your controller's viewWillAppear
func stopObservingKeyboard() // Call this in your controller's viewWillDisappear
func keyboardObscuredHeight() -> CGFloat
#objc optional func adjustLayoutForKeyboardObscuredHeight(_ obscuredHeight: CGFloat, keyboardFrame: CGRect, keyboardWillAppearNotification: Notification) // Implement this in your controller and adjust your bottom inset accordingly
}
var _keyboardObscuredHeight:CGFloat = 0.0;
extension UIViewController: KeyboardObserver
{
func startObservingKeyboard()
{
NotificationCenter.default.addObserver(self, selector: #selector(observeKeyboardWillChangeFrameNotification(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
}
func stopObservingKeyboard()
{
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
}
func observeKeyboardWillChangeFrameNotification(_ notification: Notification)
{
guard let window = self.view.window else {
return
}
let animationID = "\(self) adjustLayoutForKeyboardObscuredHeight"
UIView.beginAnimations(animationID, context: nil)
UIView.setAnimationCurve(UIViewAnimationCurve(rawValue: (notification.userInfo![UIKeyboardAnimationCurveUserInfoKey]! as AnyObject).intValue)!)
UIView.setAnimationDuration((notification.userInfo![UIKeyboardAnimationCurveUserInfoKey]! as AnyObject).doubleValue)
let keyboardFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey]! as AnyObject).cgRectValue
_keyboardObscuredHeight = window.convert(keyboardFrame!, from: nil).intersection(window.bounds).size.height
let observer = self as KeyboardObserver
observer.adjustLayoutForKeyboardObscuredHeight!(_keyboardObscuredHeight, keyboardFrame: keyboardFrame!, keyboardWillAppearNotification: notification)
UIView.commitAnimations()
}
func keyboardObscuredHeight() -> CGFloat
{
return _keyboardObscuredHeight
}
}
Having a hell of a time fitting my app on a 4s, my strategy is that the user will select a picker, then when they type in the text field, the picker will disappear (the value having been selected and stored) and the textfields (inside "topView") pop up where the picker was to make room for the keyboard. I can see my topView try to pop, but it doesn't go anywhere. Can I do this? or is the picker's position above it stopping me, i.e. even though it's hidden, it's space is still there?
#IBOutlet weak var topHalfView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
countyPicker.delegate = self
countyPicker.dataSource = self
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}
func keyboardWillShow(sender: NSNotification) {
countyPicker.hidden = true
self.topHalfView.frame.origin.y += 150
}
func keyboardWillHide(sender: NSNotification) {
countyPicker.hidden = false
self.topHalfView.frame.origin.y -= 150
}
Turns out auto layout was what was preventing my view from popping. I'm not that comfortable having auto layout off, so if anyone knows a way to make it work with auto layout still on, please let me know.