Preventing Avcapturevideopreviewlayer from Rotating, But Allow UI Layer to Rotate with Orientation

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

How to handle autorotation in AVCaptureVideoPreviewLayer?

In my implementation I have subclassed the UIView for my view which I want to rotate and something like viewController for this view which is just a subclass of NSObject.

In this viewController I do all the the checks related to changes of orientation, make decision if I should change orientation of my target view, and if yes, then I call method of my view for changing its orientation.

First of all we need to fix the orientation of whole application interface to Portrait mode, so that our ACCaptureVideoPreviewLayer always stays still.
This is done in the MainViewController.h:

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation`
{
return interfaceOrientation==UIInterfaceOrientationPortrait;
}

It returns NO to all orientations except Portrait.

In order to our custom viewController be able to track the changes of device orientation we need to make it an observer of corresponding notifications:

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

I put these lines in the (void)awakeFromNib method of my viewController.
So each time the device orientation is changed, the viewController's method orientationChanged will be called.

Its purpose is to check what is the new orientation of device, what was the last orientation of device and decide if to change it. Here is the implementation:

if(UIInterfaceOrientationPortraitUpsideDown==[UIDevice currentDevice].orientation ||
lastOrientation==(UIInterfaceOrientation)[UIDevice currentDevice].orientation)
return;
[[UIApplication sharedApplication]setStatusBarOrientation:[UIDevice currentDevice].orientation animated:NO];

lastOrientation=[UIApplication sharedApplication].statusBarOrientation;
[resultView orientationChanged];

If the orientation is the same as before or in PortraitUpsideDown then do nothing.
Else it sets the status bar orientation to the proper one, so that when there is an incoming call or ossification, it will appear on the proper side of the screen. And then I call also method in the target view where all the corresponding changes for new orientation are done, like rotating, resizing, moving the other elements of interface in this view corresponding to the new orientation.

Here is the implementation of the orientationChanged in target view:

Float32 angle=0.f;
UIInterfaceOrientation orientation=[UIApplication sharedApplication].statusBarOrientation;

switch (orientation) {
case UIInterfaceOrientationLandscapeLeft:
angle=-90.f*M_PI/180.f;
break;
case UIInterfaceOrientationLandscapeRight:
angle=90.f*M_PI/180.f;
break;
default: angle=0.f;
break;
}
if(angle==0 && CGAffineTransformIsIdentity(self.transform)) return;

CGAffineTransform transform=CGAffineTransformMakeRotation(angle);

[UIView beginAnimations:@"rotateView" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:0.35f];

self.transform=transform;

[UIView commitAnimations];

Of course here you can add any other changes like translation, scaling of different views of your interface that need to respond to new orientation and animate them.

Also you may not need the viewController for this, but do all just in the class of your view.
Hope that the general idea is clear.

Also don't forget to stop getting notification for orientation changes when you don't need them like:

[[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
[[UIDevice currentDevice]endGeneratingDeviceOrientationNotifications];

Force Rotate iOS Even When Device's Portrait Orientation Lock is ON

So after few days, I have solved the problem!!! I'm still wondering though what was the reason behind in down voting my question. I have found this tutorial/blog:

Detect Device Rotation Even When Rotation Lock Is ON

So basically, the alternative way is to use CoreMotion. I hope someone who is having the same question in mind finds this answer. Cheers!

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.



Related Topics



Leave a reply



Submit