Disable Autorotate on a Single Subview in iOS8

Disable autorotate on a single subview in iOS8

Okay after some fighting with subviews and transitionCoordinators I've finally figured it out:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
CGAffineTransform targetRotation = [coordinator targetTransform];
CGAffineTransform inverseRotation = CGAffineTransformInvert(targetRotation);

[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {

self.drawingView.transform = CGAffineTransformConcat(self.drawingView.transform, inverseRotation);

self.drawingView.frame = self.view.bounds;
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
}];
}

What I do is, I calculate the inverse of the transform applied to the view and then use it to change the transform. furthermore I change the frame with the view bounds. This is due to it being full screen.

iOS: Disable Autorotation for a Subview

Autorotation is handled by a view's UIViewController (shouldAutorotateToInterfaceOrientation:), so one approach is to arrange your hierarchy such that rotatable views are managed by one view controller, and non-rotatable views by another view controller. Both of these UIViewController's root views then need adding to the window/superview.

The subtlety here is that if you have two view controller's views on the same level (i.e. added via addSubview:), only the first view controller (usually the window's rootViewController) will receive the shouldAutorotateToInterfaceOrientation: message.

I used this approach myself to achieve a toolbar that rotates, while the main view does not.

Apple's Technical Q&A QA1688 ("Why won't my UIViewController rotate with the device?") talks a little bit about this issue.


Update for iOS 6:

Autorotation now uses UIViewController's shouldAutorotate and supportedInterfaceOrientations methods. shouldAutorotate returns YES by default, but remember that a view controller other than the rootViewController whose view is a direct subview of the window will NOT receive rotation callbacks anyway.


Sample Code for iOS 6:

Create a new project using the "Single View Application" template, and ensure "Use Storyboards" is checked. We'll use the provided ViewController class as the rotating view controller (rename it if you like!), and create a second UIViewController subclass called NonRotatingViewController. Although this view controller will never even receive the rotation callbacks, for completeness and clarity add the following code in NonRotatingViewController.m:

- (BOOL)shouldAutorotate
{
return NO;
}

In the MainStoryboard file, drag out a new view controller object and set its class to NonRotatingViewController, and set its Storyboard ID to "NonRotatingVC". While you're there, change the rotating view controller view's background color to clear (the non rotating view will be added underneath this one), and add a label to each view. In AppDelegate.m, add the following code:

#import "NonRotatingViewController.h"

// ...
// ...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
NonRotatingViewController *nonRotatingVC = [mainStoryboard instantiateViewControllerWithIdentifier:@"NonRotatingVC"];
[self.window addSubview:nonRotatingVC.view];
return YES;
}

This is just instantiating a non rotating view controller and adding its view directly to the window (N.B. at this point the window's rootViewController has already been set by the storyboard).

Run the project. Rotate the device and marvel at the sight of one label rotating while the other stays still!


Sample Code pre iOS 6:

I did this in a new project - a new View-based Application will do just fine. Add two new view controllers: RotatingViewController and NonRotatingViewController. Inside each of their nibs I just added a label to describe whether the view should rotate or not. Add the following code:

'RotatingViewController.m'

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}


'NonRotatingViewController.m'

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationPortrait) { // Or whatever orientation it will be presented in.
return YES;
}
return NO;
}


'AppDelegate.m'

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RotatingViewController *rotating = [[RotatingViewController alloc] initWithNibName:@"RotatingViewController" bundle:nil];
self.rotatingViewController = rotating;
[rotating release];

NonRotatingViewController *nonRotating = [[NonRotatingViewController alloc] initWithNibName:@"NonRotatingViewController" bundle:nil];
self.nonRotatingViewController = nonRotating;
[nonRotating release];

[self.window addSubview:self.rotatingViewController.view];
[self.window insertSubview:self.nonRotatingViewController.view belowSubview:self.rotatingViewController.view];

[self.window makeKeyAndVisible];

return YES;
}

I hope this helps.

How to disable auto-rotation for specific View Controllers inside a Navigation Controller (Swift)?

I made an example project on how to do this: GitHub repo.

While @Sidetalker's answer is correct I think it lacks a bit of explanation.

Basically you create a Custom Class for your UINavigationController and assign it to UINavigationController in Storyboard. In the custom UINavigationController class you override the shouldAutorotate function and check if the topViewController is ViewController(the class of your UIViewController in Storyboard) of the class on which you want to disable autorotate.

In custom UINavigationController:

override func shouldAutorotate() -> Bool {
if !viewControllers.isEmpty {

// Check if this ViewController is the one you want to disable roration on
if topViewController!.isKindOfClass(ViewController) {

// If true return false to disable it
return false
}
}

// Else normal rotation enabled
return true
}

iOS disable autorotate but adjust according to orientation

As suggested by comments and by browsing throw the interwebs, handling this through the accelerometer is the only possible solution.

Disabling auto rotation for a UIView

Try this:

myVideoCaptureLayer.orientationSupported = NO;

UIView not resizing when rotated with a CGAffineTransform under iOS8

This is more of a work around than a fix so it may not help everybody in similar situations. My problem was that the outer "pinned" view was being resized again after the transform was applied.

My solution was to change the constraints on the pinned view to be center vertically, center horizontally, and width and height equal a constant.

Then, in viewDidLoad, I set the height and width of the pinned view's frame to be the height of the main screen. This makes the view square so I don't care if it gets an extra rotate.

Preventing AVCaptureVideoPreviewLayer from rotating, but allow UI layer to rotate with orientation

Make sure to set shouldAutorotate to return false:

-(BOOL)shouldAutorotate{
return NO;
}

register for Notifications that orientation changed:

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];

implement the notification change

-(void)orientationChanged:(NSNotification *)notif {
UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];

// Calculate rotation angle
CGFloat angle;
switch (deviceOrientation) {
case UIDeviceOrientationPortraitUpsideDown:
angle = M_PI;
break;
case UIDeviceOrientationLandscapeLeft:
angle = M_PI_2;
break;
case UIDeviceOrientationLandscapeRight:
angle = - M_PI_2;
break;
default:
angle = 0;
break;
}

}

and rotate the UI

 [UIView animateWithDuration:.3 animations:^{
self.closeButton.transform = CGAffineTransformMakeRotation(angle);
self.gridButton.transform = CGAffineTransformMakeRotation(angle);
self.flashButton.transform = CGAffineTransformMakeRotation(angle);
} completion:^(BOOL finished) {

}];

This is how I implement the screen being locked but rotating the UI, if this works link the stacks post and I can copy it over there and you can tick it :P



Related Topics



Leave a reply



Submit