Wrong View appearing when iPad screen is tipped back a certain angle - ios

I have an issue in one of my applications that I just discovered once I got the app onto an actual iPad, it isn't possible to see in the simulator. The issue is when I hold the iPad in landscape orientation, if I tip the iPad back to a certain angle the iPad stays in landscape mode but the view switches to my portraitView while still in landscape mode. In my code I have a function called screenRotated() that is an observer of UIDeviceOrientationDidChangeNotification. My function screenRotated() has the following code:
let interfaceOrientation: UIDeviceOrientation = UIDevice.currentDevice().orientation
if UIDeviceOrientationIsLandscape(interfaceOrientation) {
//does some stuff and then sets self.view = landscapeView
} else {
//does some stuff and then sets self.view = portraitView
}
How do I keep my app from going into the wrong view when in landscape orientation?

You issue will be that you are not handling device orientation notifications for orientations UIDeviceOrientationFaceUp and UIDeviceOrietationFaceDown. These are neither Portrait or Landscape and your code always picks Portrait when the orientation is not Landscape.
Hence as you are tipping back, it goes to orientation face up and your code picks Portrait as it is not landscape but face up.
So add code to detect faceup/down and ideally keep to the orientation last set until you see it actually go from Portrait to Landscape or the other way around.
The following should work:
if UIDeviceOrientationIsLandscape(interfaceOrientation) {
//does some stuff and then sets self.view = landscapeView
} else if UIDeviceOrientationIsPortrait(interfaceOrientation) {
//does some stuff and then sets self.view = portraitView
}
else{
// Do nothing
}

Related

Landscape Segue Between Two Portrait UIViewControllers

I am only allowing Device Orientation portrait for UIViewControllers being viewed on iPhones through the following code:
- (BOOL)shouldAutorotate
{
NSString *device = [UIDevice currentDevice].model;
return [device rangeOfString:#"iPhone"].location != NSNotFound ? NO : YES;
}
This works fine - when I rotate my iPhone while looking at ViewController A, the view does not rotate. Similarly, when I rotate my iPhone while looking at ViewController B, the view does not rotate. However, when I rotate my iPhone while looking at ViewController A, tap a button that presents ViewController B modally, the show segue animation (Flip Horizontal) is landscape, and ViewController B appears in landscape.
How can I force the segue to be portrait as well and not rotate ViewController B?
In my tests I've found that shouldAutorotate is only one part of the things you have to do to prevent rotation of the device. shouldAutorotate tells the system if it should rotate all the views as soon as someone rotates the device to a different allowed orientation.
My suggestion would be to prevent more orientations other than Landscape (which allows LandscapeLeft and LandscapeRight). And by that I mean you should override supportedInterfaceOrientations in both ViewControllers and tell the app that it should only allow landscape orientations instead of the default (which allows all but upside-down orientation).

shouldAutorotate is not locking the screen orientation

I ma trying to lock screen orientation to only landscape orientation when a certain image is still visible, then when the image is hidden, unlock all orientations (targeting iOS 6):
-(BOOL)shouldAutorotate{
if (self.splashImageView.hidden == NO) {
return UIInterfaceOrientationMaskPortrait;//gets called when image is visible
}else{
return UIInterfaceOrientationMaskAll;//gets called when image is hidden
}
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[self shouldAutorotate];
}
As you may notice, shouldAutorotate is called properly but the screen is always supporting landscape orientation even when the image is still visible, is there something missing?
P.S: Please note I am trying to get that to work on a tabbar view controller (a UIViewController subclass).
In your appdelegate you have those two methods.but do you have setting like in your project settings -> go to summary tab and see if orientation is set to only landscape or all.Just try to set those.

Why does UIView (on iPad) default to portrait even if set to landscape in storyboard

This topic has come up before (iPad modal view controller acting in portrait even though it's landscape) but I haven't found a clear answer - so I don't know if this is a duplicate or not.
In new single view project, I set the main view to landscape in xcode:
And the Property Inspector confirms this (as well as how the view is displayed in the storyboard):
And the ViewController orientation property is set to landscape:
Yet when I check the view frame in 'viewDidLoad' it reports portrait mode:
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect theRect = self.view.frame;
NSLog(#" frame %f %f %f %f", theRect.origin.x,
theRect.origin.y,
theRect.size.width,
theRect.size.height);
}
2012-08-26 16:42:45.045 Test[2320:f803] cell 0.000000 20.000000
768.000000 1004.000000
I also force landscape in shouldAutorotateToInterfaceOrientation:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
I've encountered this many times before and have had to set the frame explicitly to landscape but I have never understood why all the storyboard settings have no effect.
Am I missing something basic here?
Every application in iOS starts in portrait mode inititally, even if you specified the supported device orientations and give the right "answers" at shouldAutorotateToInterfaceOrientation:. It will always start in portrait and will the rotate to landscape if the device. The user maybe won't see it cause its so fast.
Because of this your app has to be able to rotate via shouldAutorotateToInterfaceOrientation even if your only supported orientations are landscape ones.
So to get a landscape orientation after start you should:
set the supported interface orientations in Xcodes Interface Builder
overide shouldAutorotateToInterfaceOrientation:
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)io {
return (io == UIInterfaceOrientationLandscapeRight);
}
give the interface a chance to rotate and do your view configuration afterwards
Regarding your question about the Xcode configuration of the the viewcontroller to landscape: Notice the title of the menu in the storyboard - it says: Simulated Metrics
This means that every modification you do there is just for the purpose to simulate it in the storyboard. But unless you do the necessary modifications to get to this state in the code it will have no effect.
Add below code in your view controller with swift 4.2
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .landscapeRight
}

Monotouch - View created in landscape orientation is displayed in portrait orientation

I've created a view controller and set the orientation of the view to Landscape in XCode 4.2 (Interface Builder). However, when I add the view, the view is displayed in Portrait orientation. I've overriden ShouldAutorotateToInterfaceOrientation in all view controllers to return true, and I've attempted to rotate the view manually using the following code:
this.View.Transform.Rotate (3.14f * .5f);
I have also tried to set the frame to a landscape frame (i.e. 480 X 320), though the frame of the view is already set correctly.
Just to clarify, the vast majority of my views are in Portrait. I would like to load the landscape view in a landscape orientation, irrespective of what orientation the device is actually in. Is this possible? If so, what am I missing?
Thanks in advance for any assistance on this matter!
UPDATE: I'm noticing that ShouldAutorotateToInterfaceOrientation is only called once when the view is loaded. It is not called when the device is rotated. Is this normal behavior?
ShouldAutorotateToInterfaceOrientation is called every time the device orientation changes.
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
Console.Out.WriteLine(toInterfaceOrientation.ToString());
// Return true for supported orientations
// This particular screen is landscape only!
return (toInterfaceOrientation == UIInterfaceOrientation.LandscapeLeft || toInterfaceOrientation == UIInterfaceOrientation.LandscapeRight);
}
this code will only allow the view to orient itself in either landscapeleft or landscaperight mode, and writes the new device orientation to the console every time.
when you load the view, and push it onto (for instance) a UINavigationController however, it's still in portrait mode (and ShouldAutorotateToInterfaceOrientation is not called.)
From Objective-C, it's fairly easy to force a device orientation, but in MonoTouch, there appears to be no direct mapping.
the solution ;
Send a message to the objective-c runtime, specifying which orientation we want.
you can easily do this by adding the following to a view controller:
Selector orientationSetter;
private void SetOrientation (UIInterfaceOrientation toOrientation)
{
if (orientationSetter == null)
{
orientationSetter = new Selector ("setOrientation:");
}
Messaging.void_objc_msgSend_int (UIDevice.CurrentDevice.Handle,
orientationSetter.Handle, (int)toOrientation);
}
you can now manually change the orientation of the entire device.
What's more, is that if you use a UINavigationController, the orientation will return back to normal once this view is popped off the stack.
I think that for the Landscape view that you always want to display in Landscape Orientation, you need to return False within ShouldAutorotateToInterfaceOrientation or remove the override altogether. This will prevent the view from auto-rotating when the device is in portrait mode.

UIView rotation text manipulation

I have a view that consists of a bunch of UILabels. As of right now the view is only configured to work when the device's orientation is portrait, however I would like to make it so that when the device is rotated one specific UILabel's location is changed and text size is magnified. When the device's orientation is reverted to portrait, I'd like for it to return to its original state.
How should I go about doing this?
Implement this method in your ViewController and do the changes accordingly.
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
// do something in landscape orientation
} else {
// do something in portrait orientation
}
}

Resources