How can I get a UIImageView to not rotate when the user rotates their phone?
All other views in the view controller should update with auto-layout as normal, but I want the UIImageView to stay constant.
How can I accomplish this? Right now I'm rotating the image in viewWillTransitionToSize, but that looks terrible and doesn't account for LandscapeLeft vs. LandscapeRight
There's no magic flag to have a UIView not rotate, but you could rotate it back with the following code:
-(void) viewDidLoad {
[super viewDidLoad];
// Request to turn on accelerometer and begin receiving accelerometer events
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
- (void)orientationChanged:(NSNotification *)notification {
// Respond to changes in device orientation
switch ([UIDevice currentDevice].orientation)
{
case UIDeviceOrientationLandscapeLeft:
self.img.transform = CGAffineTransformMakeRotation(-M_PI/2);
break;
case UIDeviceOrientationLandscapeRight:
self.img.transform = CGAffineTransformMakeRotation(M_PI/2);
break;
case UIDeviceOrientationPortrait:
self.img.transform = CGAffineTransformMakeRotation(0);
break;
case UIDeviceOrientationPortraitUpsideDown:
self.img.transform = CGAffineTransformMakeRotation(0);
break;
case UIDeviceOrientationFaceUp:
break;
case UIDeviceOrientationFaceDown:
break;
case UIDeviceOrientationUnknown:
break;
}
}
-(void) viewDidDisappear {
// Request to stop receiving accelerometer events and turn off accelerometer
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
}
Related
I want to change the orientation of specific ViewController in Xcode.
I make a,b,cViewController and change the orientation only cViewController to LandscapeRight. (a and b's orientation are Portrait)
But if I change the orientation on cViewController and move ViewController from c to b, b's orientation is also changed to LandscapeRight.
(screen transition is push)
code:
a and bViewController's DidLoad
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
cViewController's DidLoad
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
How can I change the orientation only cViewController?
step-1
create the one bool property in your appdelegate like , this
#property () BOOL restrictRotation;
and call the function
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if(self.restrictRotation)
return UIInterfaceOrientationMaskLandscape ;
else
return UIInterfaceOrientationMaskPortrait;
}
step-2
and import the appdelegate #import "AppDelegate.h" in C VC
on your C VC View Will appear, call like
-(void)viewWillAppear:(BOOL)animated{
// for rotate the VC to Landscape
[self restrictRotationwithNew:YES];
}
(void)viewWillDisappear:(BOOL)animated{
// rotate the VC to Portait
[self restrictRotationwithNew:NO];
[super viewWillDisappear:animated];
}
-(void) restrictRotationwithNew:(BOOL) restriction
{
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.restrictRotation = restriction;
}
Choice 2
on your C VC check the Orientation using the delegate function of UIDeviceOrientationDidChangeNotification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
- (void)orientationChanged:(NSNotification *)notification{
[self adjustViewsForOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
}
- (void) adjustViewsForOrientation:(UIInterfaceOrientation) orientation {
UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];
switch (deviceOrientation) {
case UIDeviceOrientationPortrait:
NSLog(#"orientationPortrait");
;
break;
case UIDeviceOrientationPortraitUpsideDown:
NSLog(#"UIDeviceOrientationPortraitUpsideDown");
break;
case UIDeviceOrientationLandscapeLeft:
NSLog(#"OrientationLandscapeLeft");
break;
case UIDeviceOrientationLandscapeRight:
NSLog(#"OrientationLandscapeRight");
break;
default:
break;
}
}
I have my app in portrait mode.
When video player enters full screen mode, I want to play that video in both landscape and portrait orientation.
moviePlayer = [[MPMoviePlayerController alloc]initWithContentURL:url];
[moviePlayer.view setAutoresizingMask:(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth)];
[moviePlayer setScalingMode:MPMovieScalingModeFill];
moviePlayer.view.frame = CGRectMake(0, 0, self.videoPlayerView.frame.size.width, self.videoPlayerView.frame.size.height);
[self.videoPlayerView addSubview:moviePlayer.view];
and I am playing it on one button.
For you question i would like to give the below Reference
Portrait video to landscape
and
Allow video on landscape with only-portrait app
Enable your Landscape Device Orientation in Deployment Info. Then, add these methods in your ViewController:
- (BOOL) shouldAutorotate {
return NO;
}
- (NSUInteger) supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
Try to add a canvas view as superview to your player and apply transformation to the canvas view.
- (void)initialize{
self.canvas = [[UIView alloc] initWithFrame: self.view.bounds];
[self.view addSubview:self.canvas];
// init moviePlayer
moviePlayer = [[MPMoviePlayerController alloc]initWithContentURL:url];
...
[self.canvas addSubview: moviePlayer.view];
// Add observers
...
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(deviceOrientationDidChange)
name: UIDeviceOrientationDidChangeNotification
object: nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
}
- (void)deviceOrientationDidChange{
// Apply rotation only in full screen mode
if (self.isFullScreen) {
UIDeviceOrientation currentOrientation = [UIDevice currentDevice].orientation;
[UIView animateWithDuration: 0.3
animations: ^{
CGAffineTransform transform = CGAffineTransformMakeRotation(0);
switch (orientation) {
case UIDeviceOrientationLandscapeLeft:
transform = CGAffineTransformMakeRotation(M_PI_2);
break;
case UIDeviceOrientationLandscapeRight:
transform = CGAffineTransformMakeRotation(M_PI + M_PI_2);
break;
default:
break;
};
self.canvas.transform = transform;
self.canvas.frame = self.canvas.superview.bounds;
}];
}
}
I'm using this observer: UIDeviceOrientationDidChangeNotification to detect when user is changing the device orientation. When the orientation changed to landscape I present a new UIViewController or dismiss this UIViewController when he changes it back to portrait.
My problem starts when the user start rotating the device number of times and fast, then the application goes crazy until I get this error:
Warning: Attempt to present on whose view is not in the window hierarchy!`.
What is the best possible way to wait until the animation is over and then change the rotation?
This is what I'm using on the Presenting view controller:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self beginDeviceOrientationListener];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)beginDeviceOrientationListener
{
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]];
}
- (void)orientationChanged:(NSNotification *)notification
{
UIDevice *device = notification.object;
switch (device.orientation)
{
case UIDeviceOrientationLandscapeLeft:
case UIDeviceOrientationLandscapeRight:
{
TheViewControllerToPresent *viewController = [[TheViewControllerToPresent alloc] init];
[self presentViewController:viewController animated:YES completion:nil];
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationLandscapeRight] forKey:#"orientation"];
[[UIApplication sharedApplication] setStatusBarOrientation:[[[UIDevice currentDevice] valueForKey:#"orientation"] integerValue] animated:YES];
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
}
break;
default:
break;
}
}
This is what I'm using on the Presented view controller:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self beginDeviceOrientationListener];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)beginDeviceOrientationListener
{
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]];
}
- (void)orientationChanged:(NSNotification *)notification
{
UIDevice *device = notification.object;
switch (device.orientation)
{
case UIDeviceOrientationPortrait:
{
[self dismissViewControllerAnimated:YES completion:nil];
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationPortrait] forKey:#"orientation"];
[[UIApplication sharedApplication] setStatusBarOrientation:[[[UIDevice currentDevice] valueForKey:#"orientation"] integerValue] animated:YES];
}
break;
default:
break;
}
}
The most simplest solution that I am using myself is stopping the user from making any changes while the animation is in progress.
This is done by adding the following code when the animation starts:
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
and to the completion handler:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
The user can rotate the device but the events won't be generated during the animation so the animations won't collide. However, when the animation ends, you should explicitly check the orientation:
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
to see whether you should start another animation or not.
My app running only in landscape mode, but i want display one View in portrait mode. So i have created project using Unified storyboards (Xcode 6). My project is running only which are targeted in Deployment Info.
and my view controller
What I do wrong? Help me.
I faced the same issue few weeks ago. I created new UIViewController with portrait orientation. Later I realised that changing orientation is not enough, then I used this below code to change the orientation.Use the below code to change orientation.
-(void)viewWillAppear:(BOOL)animated
{
[self willAnimateRotationToInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation duration:.2];
[self awakeFromNib];
}
-(void)viewWillDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification
object:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
if(is_iPad)
{
return YES;
}else
{
return (UIInterfaceOrientationIsPortrait(toInterfaceOrientation));
}
}
- (void)awakeFromNib
{
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
delegate->isShowingLandscapeView=NO;
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
- (void)orientationChanged:(NSNotification *)notification
{
if (is_iPad) {
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) &&
!delegate->isShowingLandscapeView)
{
yourPotraitViewController *ypvc =[[yourPotraitViewController alloc] initWithNibName:#"yourPotraitViewController" bundle:nil];
[self.navigationController pushViewController:objHomeLandscape animated:YES];
delegate->isShowingLandscapeView=YES;
// isShowingLandscapeView = YES;
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) &&
delegate->isShowingLandscapeView)
{
[self.navigationController popViewControllerAnimated:YES];
delegate->isShowingLandscapeView=NO;
}
}
}
I have seen multiple copies of the same question.but it has not supported my cause.
i have tried subclassing the navigationController adding category for the navigation controller and when i tried all these the methods shouldAutoRotate and supportedInterfaceOrientations gets invoked for Both the navigationcontroller and view controller but the device stays in portrait view only.
#import "UINavigationController+Rotation.h"
#implementation UINavigationController (Rotation)
- (BOOL)shouldAutorotate {
BOOL result = self.topViewController.shouldAutorotate;
return result;
}
- (NSUInteger)supportedInterfaceOrientations {
NSUInteger result = self.topViewController.supportedInterfaceOrientations;
return result;
}
#end
Is some thing that i do wrong?
Call this method form viewdidload:
-(void)rotateCameraView {
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver: self selector: #selector(deviceOrientationDidChange:) name:
UIDeviceOrientationDidChangeNotification object: nil];
}
When you rotate device this method will call automatically
-(void)deviceOrientationDidChange:(NSNotification *)notification {
//Obtaining the current device orientation
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
//Ignoring specific orientations
if (orientation == UIDeviceOrientationFaceUp
|| orientation == UIDeviceOrientationFaceDown || orientation ==
UIDeviceOrientationUnknown) { return; }
if ((UIDeviceOrientationIsPortrait(orientation)
||UIDeviceOrientationIsPortrait(orientation)) ||
(UIDeviceOrientationIsLandscape(orientation) ||
UIDeviceOrientationIsLandscape(orientation))) {
//still saving the current orientation
currentOrientation = orientation; } [self
performSelector:#selector(orientationChangedMethod) withObject:nil
afterDelay:0];
}
-(void)orientationChangedMethod
{
switch (currentOrientation) {
case UIDeviceOrientationPortrait:
if (isOrientationEffect==YES)
{
appDelegate.imagePickerController.cameraViewTransform = CGAffineTransformMakeRotation(M_PI);
// if (!isPurchased)
// {
//
// [self buttonFrameWithIad];
// }
// else
// {
// [self buttonFrameWithoutIad];
// }
[self MakeTransformRotation];
}
[UIView beginAnimations:#"rotateView" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:0.35f];
camDefaultImg.transform = CGAffineTransformMakeRotation(0);
[UIView commitAnimations];
break;
case UIDeviceOrientationLandscapeLeft:
if (isOrientationEffect==YES)
{
}
}