I'm working on an iOS Application which is created using older X-Code version, so it has window in MainWindow.xib.
Recently when I run this project in iOS8 Beta version, I got a problem: window is not rotating in landscape orientation. So I have added another window in MainWindow.xib. I made if condition to check OS Versions, for older iOS version I'm using previously created window but for iOS8 I'm using newly added window for landscape orientation. I have solved the problem. The entire application is working properly except the camera.
Below are screen shots.
In LandscapeMode(It's working properly):
In PortraitMode(Once camera is loaded, i have rotated it,Here other controls are rotating properly, but camera overly is not rotating properly):
Once Camera is loaded in landscape mode I have rotated device, the controls are rotating properly but the camera screen is not rotating, it is still in portrait mode.
This may be due to window in Appdelegate.
Any solution for this?
Thanks in advance.
I am having the same issue.
I was tryed to use the cameraViewTransform.
Below
#import "MyUIImagePickerController.h"
#implementation MyUIImagePickerController
bool rotateFlg = false;
UIInterfaceOrientation startupOrientation;
-(id)init{
startupOrientation = [[UIApplication sharedApplication] statusBarOrientation];
return [super init];
}
-(NSUInteger)supportedInterfaceOrientations {
// iOS 8
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) {
float lotate[4];
if (startupOrientation == UIInterfaceOrientationLandscapeRight || startupOrientation == UIInterfaceOrientationLandscapeLeft) {
lotate[0] = 90.0f;
lotate[1] = -90.0f;
lotate[2] = 180.0f;
lotate[3] = 0.0f;
} else {
lotate[0] = 0.0f;
lotate[1] = 180.0f;
lotate[2] = 90.0f;
lotate[3] = -90.0f;
}
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if(orientation ==UIInterfaceOrientationPortrait ){
CGAffineTransform __rotation = CGAffineTransformMakeRotation(lotate[0] * M_PI / 180.0f);
self.cameraViewTransform = __rotation;
rotateFlg = true;
}
else if(orientation == UIInterfaceOrientationPortraitUpsideDown){
CGAffineTransform __rotation = CGAffineTransformMakeRotation(lotate[1] * M_PI / 180.0f);
self.cameraViewTransform = __rotation;
rotateFlg = true;
} else if(orientation == UIInterfaceOrientationLandscapeLeft){
if (rotateFlg) {
CGAffineTransform __rotation = CGAffineTransformMakeRotation(lotate[2] * M_PI / 180.0f);
self.cameraViewTransform = __rotation;
rotateFlg = false;
}
}else if(orientation == UIInterfaceOrientationLandscapeRight){
if (rotateFlg) {
CGAffineTransform __rotation = CGAffineTransformMakeRotation(lotate[3] * M_PI / 180.0f);
self.cameraViewTransform = __rotation;
rotateFlg = false;
}
}
}
return UIInterfaceOrientationMaskAll;
}
#end
It seems to work
But the source is not beautiful ...
Have posted what I believe is a solution, over at; https://stackoverflow.com/a/26934067/782533
Looks like the same issue? Not sure if I'm supposed to link or copy/paste, so here it is anyway;
I had the same issue and after getting back to basics and creating a new project which actually worked.. I tracked it down to;
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
// Had forgot to call the following..
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}
Hope it helps.
According to this thread on Apple Dev forums rotation in iOS8/XCode6 has some problems when using XIBs but not when using Storyboards.
Related
I am developing an Application where I am capturing image in landscape mode when device orientation is OFF. I am using GPUImageStillCamera for capturing image. But I'm getting issue in rotation of image. Issue is, When I capture image in landscape mode with device rotation OFF and save in gallery, then turning device rotation ON and image must rotate with device orientation. But the image is in landscape when holding device in portrait mode and If holding device in landscape, the image rotation is UpsideDown
.
Note
Image rotation works perfect when captured with device rotation ON.
Issue is only with image in landscape mode when device rotation OFF.
I have tried many solutions like this one. But didn't work for
me.
Any help will be appreciated. Thanks
I got solution to this problem . I tried to detect the accelerometer's rotation to get the rotation even when device orientation is OFF. Add CoreMotion.framerwork to your project. Then import CMMotionManager.h in your viewController. In viewDidLoad, add the following code :
self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.accelerometerUpdateInterval = 1;
if ([self.motionManager isAccelerometerAvailable])
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[self.motionManager startAccelerometerUpdatesToQueue:queue withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
float xx = -accelerometerData.acceleration.x;
float yy = accelerometerData.acceleration.y;
float angle = atan2(yy, xx);
// could fire a custom shouldAutorotateToInterfaceOrientation-event here.
if(angle >= -2.25 && angle <= -0.75)
{
if(_deviceOrientation != UIInterfaceOrientationPortrait)
{
_deviceOrientation = UIInterfaceOrientationPortrait;
}
}
else if(angle >= -0.75 && angle <= 0.75)
{
if(_deviceOrientation != UIInterfaceOrientationLandscapeRight)
{
_deviceOrientation = UIInterfaceOrientationLandscapeRight;
}
}
else if(angle >= 0.75 && angle <= 2.25)
{
if(_deviceOrientation != UIInterfaceOrientationPortraitUpsideDown)
{
_deviceOrientation = UIInterfaceOrientationPortraitUpsideDown;
}
}
else if(angle <= -2.25 || angle >= 2.25)
{
if(_deviceOrientation != UIInterfaceOrientationLandscapeLeft)
{
_deviceOrientation = UIInterfaceOrientationLandscapeLeft;
}
}
});
}];
} else
NSLog(#"not active");
I am not able to reposition my uiview in ios8 programatically.The following code seems to be working perfectly fine in ios7.1 but is not working in ios8.
This code is inside layoutSubview function of the view.
for (UIView *child in self.subviews)
{
if((self.removeOnHide == YES && child.hidden == NO) || self.removeOnHide == NO) {
top += self.spacing;
switch (self.hAlignment)
{
case UIControlContentHorizontalAlignmentLeft:
left = self.leftMargin;
break;
case UIControlContentHorizontalAlignmentRight:
left = self.frame.size.width - self.rightMargin
- child.frame.size.width;
break;
default: // center
left = baseline - child.frame.size.width / 2;
break;
}
CGRect rect = child.frame;
child.frame = CGRectMake(left, top, child.frame.size.width,
child.frame.size.height);
rect = child.frame;
top += child.frame.size.height;
}
}
I am using code from this git repos https://github.com/tazihosniomar/LayoutManager. The code use to work perfectly fine in ios7.1 but is not working in ios8.0
I am using the following code to launch the image picker in my iPad app (which uses Cocos2D) :
UIImagePickerController * imagePickerController = [[UIImagePickerController alloc] init];
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePickerController.showsCameraControls = YES;
imagePickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
imagePickerController.delegate = self;
imagePickerController.cameraDevice = UIImagePickerControllerCameraDeviceFront;
[self.view addSubview:imagePickerController.view];
[self presentModalViewController:imagePickerController animated:YES];
}
I want it to launch in the portrait mode all the time, but it always launches like this :
The image appears in portrait and the image picker UI is in landscape mode. But When I capture the image, it get's rotated 90 degrees clockwise.
I want the image picker UI and the taken image, both to be in portrait mode. How can I fix this ?
There are three things you need to do:
Tell the viewController that is presenting the imagePicker to only
support portrait orientation.
Tell the imagePicker to not to rotate the live camera feed.
Un-rotate captured images.
The imagePicker receives notifications of device orientation changes directly. To keep the live camera feed from rotating with the device you can stop it from receiving these notifications by telling UIDevice to endGenerating the orientation notifications after the imagePicker is presented via:
while ([currentDevice isGeneratingDeviceOrientationNotifications])
[currentDevice endGeneratingDeviceOrientationNotifications];
The reason why you put it in a loop is because the imagePicker beginsGeneratingDeviceOrientationNotifications, and then ends its when it is dismissed, bringing the notification count on a normal device from 1 to 2 back to 1.
After the imagePicker is dismissed, you can call:
while (![currentDevice isGeneratingDeviceOrientationNotifications])
[currentDevice beginGeneratingDeviceOrientationNotifications];
so that your ViewControllers can continue to receive orientation change notifications.
Unfortunately, even after turning this off, the images will still be saved with the correct imageOrientation of the camera on capture, so before you save the image or do anything with it, you'll have to remove the applied orientation transformation by manually countering it:
-(UIImage *)turnMeAround:(UIImage *)image{
CGAffineTransform transform = CGAffineTransformIdentity;
CGFloat scale = [[UIScreen mainScreen] scale]; //retina
CGSize size = CGSizeMake(image.size.width*scale,image.size.height*scale);
switch (image.imageOrientation) {
case UIImageOrientationUp:
return image;
case UIImageOrientationDown:
size = CGSizeMake(size.height,size.width);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationLeft:
transform = CGAffineTransformRotate(transform, -M_PI_2);
break;
case UIImageOrientationRight:
transform = CGAffineTransformRotate(transform, M_PI_2);
break;
}
CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, CGImageGetBitsPerComponent(image.CGImage), 0, CGImageGetColorSpace(image.CGImage), CGImageGetBitmapInfo(image.CGImage));
CGContextConcatCTM(context, transform);
CGContextDrawImage(context, CGRectMake(0,0,size.width,size.height), image.CGImage);
CGImageRef ref = CGBitmapContextCreateImage(context);
UIImage *upsideRight = [UIImage imageWithCGImage:ref];
CGContextRelease(context);
CGImageRelease(ref);
return upsideRight;
}
Thanks so much guys for all the help, but what worked for me is as follows :
So I found out that it was Xcode's Cocos2D template which was the culprit. It had generated the following code in the RootViewController :
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
//
// There are 2 ways to support auto-rotation:
// - The OpenGL / cocos2d way
// - Faster, but doesn't rotate the UIKit objects
// - The ViewController way
// - A bit slower, but the UiKit objects are placed in the right place
//
#if GAME_AUTOROTATION==kGameAutorotationNone
//
// EAGLView won't be autorotated.
// Since this method should return YES in at least 1 orientation,
// we return YES only in the Portrait orientation
//
return ( interfaceOrientation == UIInterfaceOrientationPortrait );
#elif GAME_AUTOROTATION==kGameAutorotationCCDirector
//
// EAGLView will be rotated by cocos2d
//
// Sample: Autorotate only in landscape mode
//
if( interfaceOrientation == UIInterfaceOrientationLandscapeLeft ) {
[[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeRight];
} else if( interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
[[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeLeft];
}
// Since this method should return YES in at least 1 orientation,
// we return YES only in the Portrait orientation
return ( interfaceOrientation == UIInterfaceOrientationPortrait );
#elif GAME_AUTOROTATION == kGameAutorotationUIViewController
//
// EAGLView will be rotated by the UIViewController
//
// Sample: Autorotate only in landscpe mode
//
// return YES for the supported orientations
return ( UIInterfaceOrientationIsLandscape( interfaceOrientation ) );
#else
#error Unknown value in GAME_AUTOROTATION
#endif // GAME_AUTOROTATION
// Shold not happen
return NO;
}
In the above code I changed this :
return ( UIInterfaceOrientationIsLandscape( interfaceOrientation ) );
To this :
return ( UIInterfaceOrientationIsPortrait( interfaceOrientation ) );
And that fixed it.
Currently I'm workign on a drawing app for the iPad. I need to reposition and rotate the toolbar in the app when it is put into a different orientation while keeping the the drawing area in the same place.
I found a method here for doing this. It uses the NSNotificationCenter to monitor for rotation changes. This calls a custom didRotate: method that will rotate and reposition my toolbar based on the UIDeviceOrientation.
This part works fine. However, whenever the side switch on the iPad is engaged to lock the orientation, the toolbar repositions to the location is was at launch.
For example: If I start the application in landscape left and rotate it to portrait, the toolbar will reposition to the bottom of the screen. However as soon as I engage the slide switch, it moves to the side of the screen for the landscape left orientation.
The methods I'm using for this are all below.
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
- (void)didRotate:(NSNotification *)notification {
UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];
UIInterfaceOrientation interfaceOrientation;
bool orientationFound = YES;
if (deviceOrientation == UIDeviceOrientationPortrait) {
interfaceOrientation = UIInterfaceOrientationPortrait;
} else if (deviceOrientation == UIDeviceOrientationPortraitUpsideDown) {
interfaceOrientation = UIInterfaceOrientationPortraitUpsideDown;
} else if (deviceOrientation == UIDeviceOrientationLandscapeLeft) {
interfaceOrientation = UIInterfaceOrientationLandscapeRight;
} else if (deviceOrientation == UIDeviceOrientationLandscapeRight) {
interfaceOrientation = UIInterfaceOrientationLandscapeLeft;
} else {
orientationFound = NO;
}
if (orientationFound) {
[self.toolbar changeToOrientation:interfaceOrientation withDuration:.25];
[self.tutorialOverlay changeToOrientation:interfaceOrientation];
}
}
- (void)changeToOrientation:(UIInterfaceOrientation)orientation withDuration:(float)duration {
float angle;
CGPoint origin;
if (orientation == UIInterfaceOrientationPortrait) {
angle = portraitAngle;
origin = self.portraitOrigin;
} else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
angle = portraitUpsideDownAngle;
origin = self.portraitUpsideDownOrigin;
} else if (orientation == UIInterfaceOrientationLandscapeLeft) {
angle = landscapeLeftAngle;
origin = self.landscapeLeftOrigin;
} else if (orientation == UIInterfaceOrientationLandscapeRight) {
angle = landscapeRightAngle;
origin = self.landscapeRightOrigin;
}
[UIView animateWithDuration:duration animations:^{
self.transform = CGAffineTransformMakeRotation(angle);
CGRect rect = self.frame;
rect.origin = origin;
self.frame = rect;
}];
}
I'd strongly recommend against using this notification-based approach. Note that the name of the notification is UIDeviceOrientationDidChangeNotification; the device orientation is not the same as the interface orientation, and it leads to lots of little issues like this. (The device orientation, for example, includes UIDeviceOrientationFaceDown, which is never associated with an interface orientation.)
I'd suggest letting your view controller automatically rotate itself; this will place the toolbar, etc, for you. You can then override - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration to put the drawing area back to the orientation you want to maintain. (You'd use similar code to your changeToOrientation method above, but for the drawing area instead, and you don't need to create your own animation block. Also, the angles would all be negated, because you're undoing the change the view controller made.)
I just answered a similar question here.
Basically just allow the interface to rotate, but rotate the view you don't want to rotate 'back' in willRotateToInterfaceOrientation:duration:.
I'm developing this application on the iPad. My MainWindow contains a Split View Controller which loads the RootViewController and DetailViewController.
I have this image that is placed at the bottom-right of the DetailViewController.
My application allows different orientations, therefore i want the image to appear at different positions for different orientations.
This is my code in DetailViewController:
- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
myImage.frame = CGRectMake(183.0f, 257.0f, 548.0f, 447.0f);
}
else if(toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
myImage.frame = CGRectMake(244.0f, 518.0f, 548.0f, 447.0f);
}
}
When i launch my application and my iPad is at portrait orientation, the image will be correctly placed at (X:244, Y:518) which is at the bottom right.
But when i launch my application and my iPad is at landscape orientation, the image will not be shown and i suspect that it is still at the position for portrait orientation. Only when i rotate my iPad to portrait orientation and then back to landscape orientation, then the image will appear at (X:183, Y:257) which is correct.
What i tried to do is to place these codes in my DetailViewController's 'viewWillAppear' method:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if(self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft || self.interfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
myImage.frame = CGRectMake(183.0f, 257.0f, 548.0f, 447.0f);
}
else if(self.interfaceOrientation == UIInterfaceOrientationPortrait || self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
myImage.frame = CGRectMake(244.0f, 518.0f, 548.0f, 447.0f);
}
}
But when i launch my application, it still has the same problem.
What can i do so that when i first launch my application in landscape orientation, it will be correctly placed at (X:244, Y:518) ?
You might want to try putting your resizing logic in didRotateFromInterfaceOrientation instead of willRotateToInterfaceOrientation.
My custom layout code only worked when I called it after the rotation had completed it, rather than before.
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
NSLog(#"didRotateFromInterfaceOrientation");
float width;
float height;
if ((fromInterfaceOrientation == UIInterfaceOrientationLandscapeRight) ||
(fromInterfaceOrientation == UIInterfaceOrientationLandscapeLeft))
{
width = [[UIScreen mainScreen] applicationFrame].size.width;
height = [[UIScreen mainScreen] applicationFrame].size.height;
NSLog(#"Changing to portrait: %f x %f", width, height);
}
else
{
width = [[UIScreen mainScreen] applicationFrame].size.height;
height = [[UIScreen mainScreen] applicationFrame].size.width;
NSLog(#"Changing to landscape: %f x %f", width, height);
}
NSLog(#"Changed orientation: %f x %f", width, height);
// Call my custom layout function to setFrame on all my UI controls
[self doLayout:width height:height];
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
}
If your app shows the status bar then you probably need to call self.view.frame.size.width instead of getting the size from the applicationFrame.
Make sure that you're overriding
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation; // Override to allow rotation. Default returns YES only for UIInterfaceOrientationPortrait
To return YES for each UIInterfaceOrentation that you want to support, otherwise willRotateToInterfaceOrientation and didRotateToInterfaceOrientation wont get called.
Try calling this early in your applicationDidFinishLauching:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
Since the detailViewController wouldn't sometimes know its orientation, I solved this issue by having a shared variable in the appDelegate that would store the device orientation throughout the app. You can initialize it in the splitViewController with its orientation so when the detailViewController loads it can read it from there.