I am using an UIImagePickerController within an UIPopoverController which is working perfectly with iOS6. With iOS 7 the "preview" image which is shown to capture the image is rotated, but if I take a picture it is saved correctly.
This is how I get my picker:
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.mediaTypes = [NSArray arrayWithObjects:
(NSString *) kUTTypeImage,
nil];
imagePicker.allowsEditing = NO;
And add it to a popover controller:
self.imagePickerPopOver = [[UIPopoverController alloc] initWithContentViewController:imagePicker];
[self.imagePickerPopOver presentPopoverFromRect:CGRectMake(aPosViewA.x, cameraButton_y, 100.0, 30.0) inView:self.detailViewController.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Those are calculations for the button position at a UIScrollView to show the popover at the correct position:
presentPopoverFromRect:CGRectMake(aPosViewA.x, cameraButton_y, 100.0, 30.0)
I don't think that the problem lies there as I have tried out several combinations.
I have also tried to capture the image in fullscreen-mode, but the app is only allowed to use landscape mode. If the image is taken in portrait-mode and the modal view is dismissed, the app stays in portrait mode as well. I couldn't find a way to prevent the UIImagePickerController to switch to portrait mode or to force the app back to landscape mode if the modal view was dismissed.
UPDATE
I have taken the answer from here and came a step further.
I transform the view after creating the picker and before showing the popover :
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationLandscapeLeft:
self.imagePicker.view.transform = CGAffineTransformMakeRotation(M_PI/2);
break;
case UIInterfaceOrientationLandscapeRight:
self.imagePicker.view.transform = CGAffineTransformMakeRotation(-M_PI/2);
break;
default:
break;
}
which works as long as i don't turn around the iPad. For that I am registering for the orientation changed event:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
and change the picker view:
- (void)orientationChanged:(NSNotification *)notification{
if (self.imagePicker) {
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationLandscapeLeft:
self.imagePicker.view.transform = CGAffineTransformMakeRotation(M_PI/2);
break;
case UIInterfaceOrientationLandscapeRight:
self.imagePicker.view.transform = CGAffineTransformMakeRotation(-M_PI/2);
break;
default:
break;
}
}
}
REMAINING PROBLEM:
As I wrote in the beginning, when the picture was taken, it was shown correctly to accept or dismiss it. This is now transformed as well. Somehow I need to know when the image is taken and transform it back.
AND, this is really a nasty hack and probably won't work with the next iOS Update. Has anybody an idea how to implement that in a cleaner way?
UPDATE 2
This was too nasty, I have found a cleaner solution which solves my problem but is not the answer to the initial question regarding an imagepicker in a popover controller, which is not recommended by Apple, but allowed.
I have subclassed now the UIImagePickerController like this:
#implementation QPImagePickerController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
}
#end
and I am using the imagepicker in fullscreen instead in a popover. Tested so far in iOS7.
The UIImagePickerController has a property called cameraViewTransform. Applying a CGAffineTransform to this will transform the preview image but will not transform the captured image which will therefore be correctly captured. I have the same problem that you describe and I solved it (for iOS7) by creating my camera controller and placing it in a popover as follows:
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
[imagePickerController setDelegate:self];
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
CGFloat scaleFactor=1.3f;
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationLandscapeLeft:
imagePickerController.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * 90 / 180.0), scaleFactor, scaleFactor);
break;
case UIInterfaceOrientationLandscapeRight:
imagePickerController.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * -90 / 180.0), scaleFactor, scaleFactor);
break;
case UIInterfaceOrientationPortraitUpsideDown:
imagePickerController.cameraViewTransform = CGAffineTransformMakeRotation(M_PI * 180 / 180.0);
break;
default:
break;
}
__popoverController = [[UIPopoverController alloc] initWithContentViewController:imagePickerController];
[__popoverController presentPopoverFromRect:presentationRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
I also scale the image when in Landscape so that it fills the viewfinder more than it otherwise would. To my mind this is all rather nasty, but I will hopefully be able to remove it once iOS7.1 arrives.
I've found another solution which handles the case where a device is rotated while the UIIMagePickerView is presenting based on the answer Journeyman provided. It also handles the case where the view is rotated from UIOrientationLandscapeRight/UIOrientationLandscapeLeft back to UIOrientationPortrait.
I created a subclass of UIImagePickerController:
#import <UIKit/UIKit.h>
#interface PMImagePickerController : UIImagePickerController
#end
Then registered it to receive notifications if the device orientation changes:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(fixCameraOrientation:) name:UIDeviceOrientationDidChangeNotification object:nil];
The selector fixCameraOrientation contains Journeyman's code with one extra case, wrapped in a check to make sure the sourceType is the camera:
- (void)fixCameraOrientation:(NSNotification*)notification
{
if (self.sourceType == UIImagePickerControllerSourceTypeCamera) {
CGFloat scaleFactor=1.3f;
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationLandscapeLeft:
self.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * 90 / 180.0), scaleFactor, scaleFactor);
break;
case UIInterfaceOrientationLandscapeRight:
self.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * -90 / 180.0), scaleFactor, scaleFactor);
break;
case UIInterfaceOrientationPortraitUpsideDown:
self.cameraViewTransform = CGAffineTransformMakeRotation(M_PI * 180 / 180.0);
break;
case UIInterfaceOrientationPortrait:
self.cameraViewTransform = CGAffineTransformIdentity;
break;
default:
break;
}
}
}
The important case here is the case where the device orientation goes to portrait. The overlay's view needs to be reset in this case. It's also important for the fixCameraOrientation selector to be called after the image picker view loads, in case the device is rotated:
- (void)viewDidLoad
{
[super viewDidLoad];
[self fixCameraOrientation:nil];
}
I had a similar situation in my app. However the preview was rotating correctly in iOS7 and not in iOS8. This code assumes you have more than one orientation.
The first thing is to subclass UIImagePickerController.
Starting from the top, add #import <AVFoundation/AVFoundation.h> to your .m file.
Also add a property to save the initial orientation #property (nonatomic) UIInterfaceOrientation startingOrientation; and another for a condition to remove clipping #property (nonatomic) BOOL didAttemptToRemoveCropping;.
Were going to listen to a couple of notifications.
UIApplicationDidChangeStatusBarOrientationNotification is obviously to listen for the device rotation. AVCaptureSessionDidStartRunningNotification is called right when the camera starts capturing.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(statusBarOrientationDidChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(captureSessionDidStart:) name:AVCaptureSessionDidStartRunningNotification object:nil];
In the -captureSessionDidStart: add a condition to verify the view is actually on screen and to make sure the camera is supposed to be displayed if (self.view.window && self.sourceType == UIImagePickerControllerSourceTypeCamera). If so, set the starting orientation self.startingOrientation = [UIApplication sharedApplication].statusBarOrientation;.
In the -statusBarOrientationDidChange: add the same condition as above, but this time if true, we'll update the camera transform. First we get the offset rotation based on the initial rotation. This is needed when you enter the UIImagePickerController in orientations other then portrait.
CGFloat startingRotation = ({
CGFloat rotation;
switch (self.startingOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
rotation = M_PI;
break;
case UIInterfaceOrientationLandscapeLeft:
rotation = -M_PI_2;
break;
case UIInterfaceOrientationLandscapeRight:
rotation = M_PI_2;
break;
default:
rotation = 0.0f;
break;
}
rotation;
});
Next we'll update the camera transform with the current rotation.
self.cameraViewTransform = CGAffineTransformMakeRotation(({
CGFloat angle;
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
angle = startingRotation + M_PI;
break;
case UIInterfaceOrientationLandscapeLeft:
angle = startingRotation + M_PI_2;
break;
case UIInterfaceOrientationLandscapeRight:
angle = startingRotation + -M_PI_2;
break;
default:
angle = startingRotation;
break;
}
angle;
}));
And finally we'll attempt to remove the black bars presented in either 90 degree orientation from the starting orientation. (This might only be an iOS8 issue.) In slightly more detail, if I enter the UIImagePickerController in portrait mode and then rotate to landscape, there will be black bars on the top and bottom of the preview. The solution for this is not to scale but rather to remove the clipping of a superview. We only need to make this attempt once, so first check if we have called this code. Also make sure that we only call this code if we have rotated. If its called in the initial orientation it wont work right away.
if (!self.didAttemptToRemoveCropping && self.startingOrientation != [UIApplication sharedApplication].statusBarOrientation) {
self.didAttemptToRemoveCropping = YES;
[self findClippedSubviewInView:self.view];
}
Finally in the code for -findClippedSubviewInView: we loop through all the subviews to search for a view with .clipsToBounds = YES. If thats true we make one more condition to verify one of its ancestral superviews is correct.
for (UIView* subview in view.subviews) {
if (subview.clipsToBounds) {
if ([self hasAncestorCameraView:subview]) {
subview.clipsToBounds = NO;
break;
}
}
[self findClippedSubviewInView:subview];
}
In the -hasAncestorCameraView: we simply loop up the superview chain and return true if one of the classes has CameraView in the name.
if (view == self.view) {
return NO;
}
NSString* className = NSStringFromClass([view class]);
if ([className rangeOfString:#"CameraView"].location != NSNotFound) {
return YES;
} else {
return [self hasAncestorCameraView:view.superview];
}
Thats the breakdown of code, here's it all together.
#import <AVFoundation/AVFoundation.h>
#import "GImagePickerController.h"
#interface GImagePickerController ()
#property (nonatomic) UIInterfaceOrientation startingOrientation;
#property (nonatomic) BOOL didAttemptToRemoveCropping;
#end
#implementation GImagePickerController
- (instancetype)init {
self = [super init];
if (self) {
if ([[[UIDevice currentDevice] systemVersion] intValue] >= 8) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(statusBarOrientationDidChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(captureSessionDidStart:) name:AVCaptureSessionDidStartRunningNotification object:nil];
}
}
return self;
}
- (void)dealloc {
if ([[[UIDevice currentDevice] systemVersion] intValue] >= 8) {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
}
#pragma mark - Capture Session
- (void)captureSessionDidStart:(NSNotification *)notification {
if (self.view.window && self.sourceType == UIImagePickerControllerSourceTypeCamera) {
[self updateStartingOrientation];
}
}
#pragma mark - Orientation
- (void)updateStartingOrientation {
self.startingOrientation = [UIApplication sharedApplication].statusBarOrientation;
[self updateCameraTransform];
}
- (void)updateCameraTransform {
CGFloat startingRotation = ({
CGFloat rotation;
switch (self.startingOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
rotation = M_PI;
break;
case UIInterfaceOrientationLandscapeLeft:
rotation = -M_PI_2;
break;
case UIInterfaceOrientationLandscapeRight:
rotation = M_PI_2;
break;
default:
rotation = 0.0f;
break;
}
rotation;
});
self.cameraViewTransform = CGAffineTransformMakeRotation(({
CGFloat angle;
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationPortraitUpsideDown:
angle = startingRotation + M_PI;
break;
case UIInterfaceOrientationLandscapeLeft:
angle = startingRotation + M_PI_2;
break;
case UIInterfaceOrientationLandscapeRight:
angle = startingRotation + -M_PI_2;
break;
default:
angle = startingRotation;
break;
}
angle;
}));
if (!self.didAttemptToRemoveCropping && self.startingOrientation != [UIApplication sharedApplication].statusBarOrientation) {
self.didAttemptToRemoveCropping = YES;
[self findClippedSubviewInView:self.view];
}
}
- (void)statusBarOrientationDidChange:(NSNotification *)notification {
if (self.view.window && self.sourceType == UIImagePickerControllerSourceTypeCamera) {
[self updateCameraTransform];
}
}
#pragma mark - Remove Clip To Bounds
- (BOOL)hasAncestorCameraView:(UIView *)view {
if (view == self.view) {
return NO;
}
NSString* className = NSStringFromClass([view class]);
if ([className rangeOfString:#"CameraView"].location != NSNotFound) {
return YES;
} else {
return [self hasAncestorCameraView:view.superview];
}
}
- (void)findClippedSubviewInView:(UIView *)view {
for (UIView* subview in view.subviews) {
if (subview.clipsToBounds) {
if ([self hasAncestorCameraView:subview]) {
subview.clipsToBounds = NO;
break;
}
}
[self findClippedSubviewInView:subview];
}
}
#end
iPad with Camera - don't display in a popover. Instead, present in a modal view controller, like you would on the iPhone. (at least starting with iOS 7)
Related
My application is only supported on Portrait mode. I have requirement that need to rotate the particular UIView only according to the device orientation.
Can you please help me?
if (interfaceOrientation == UIInterfaceOrientationPortrait) {
// set your view frame work for portrait mode
}
else {
// set new frame of view for landscape mode.
}
Hope you get the idea.
thanks
Add below give code in your viewdidload or init
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver: self selector: #selector(deviceOrientationDidChange:) name: UIDeviceOrientationDidChangeNotification object: nil];
In deviceOrientationDidChange function you will get the device orientation,according to this you can update your view
- (void)deviceOrientationDidChange:(NSNotification *)notification {
//Obtain current device orientation
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
//Do my thing
}
After the long try I found the answer using CGAffineTransform ..
- (void)deviceOrientationDidChange:(NSNotification *)notification {
//Obtain current device orientation
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
CGFloat angle;
switch (orientation) {
case UIDeviceOrientationPortraitUpsideDown:
angle = M_PI;
break;
case UIDeviceOrientationLandscapeRight:
angle = - M_PI_2;
break;
case UIDeviceOrientationLandscapeLeft:
angle = M_PI_2;
break;
case UIDeviceOrientationPortrait:
default:
angle = 0.f;
break;
}
animationView.transform= CGAffineTransformMakeRotation(angle);
animationView.frame = self.view.frame;
}
I have a custom UIView which I want to stick to the top of the UIWindow even when interface orientation changes. Here is the my view in portrait orientation
The problem is that prior iOS 8 UIWindow coordinate system is not being changed with the orientation changes. So I need to make all the calculations by hand.
The first thing is to change the transform of the UIView, which I do using this method
-(CGFloat)angleForOrientation:(UIInterfaceOrientation)orientation
{
CGFloat angle;
switch (orientation) {
case UIInterfaceOrientationLandscapeLeft:
angle = -M_PI /2.0;
NSLog(#"UIInterfaceOrientationLandscapeLeft");
break;
case UIInterfaceOrientationLandscapeRight:
angle = M_PI /2.0;
NSLog(#"UIInterfaceOrientationLandscapeRight");
break;
case UIInterfaceOrientationPortraitUpsideDown:
angle = M_PI;
NSLog(#"UIInterfaceOrientationPortraitUpsideDown");
break;
default:
angle = 0;
NSLog(#"UIInterfaceOrientationPortrait");
break;
}
return angle;
}
The second thing is to somehow map actual coordinate systems to UIWindow coordinate system, which stays the same.
So how should I calculate the frame of the custom UIView that even when the user rotates the view to other orientations I will have the same sized UIView sticked to the top centre of the screen?
For instance this is how should the view look like in landscape
By the way this image is generated from iOS 8 version. For which I do the following
self.frame = CGRectMake(window.bounds.size/2-50, 0, 100, 100);
CGFloat angle = [self angleForOrientation:orientation];
self.transform = CGAffineTransformMakeRotation(angle);
I need to do something similar to iOS 7. How can I achieve this?
Thanks for help!
So Finally I figured out how to implement this.
I've created the following method to calculate the rect which will stick the view to top based on given bounds.
-(CGRect)getTopRectForBounds:(CGRect)bounds orientation:(UIInterfaceOrientation)orientation window:(UIWindow *)window
{
CGRect newRect;
CGFloat statusBarHeight = [self getStatusBarHeight];
CGSize screenSize = window.screen.bounds.size;
CGFloat sW = screenSize.width;
CGFloat sH = screenSize.height;
CGFloat W = rect.size.width;
CGFloat H = rect.size.height;
switch (orientation) {
case UIInterfaceOrientationLandscapeLeft:
newRect = CGRectMake(statusBarHeight, (sH-W)/2, H,W);
break;
case UIInterfaceOrientationLandscapeRight:
newRect = CGRectMake(sW-H-statusBarHeight, (sH-W)/2, H,W);
break;
case UIInterfaceOrientationPortraitUpsideDown:
newRect = CGRectMake((sW-W)/2, sH-H-statusBarHeight, W,H);
break;
default:
newRect = CGRectMake((sW-W)/2, statusBarHeight, W,H);
break;
}
return newRect;
}
Then I just change the frame whenever orientation changes.
So first I listen to Orientation changes
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(statusBarFrameOrOrientationChanged:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(statusBarFrameOrOrientationChanged:) name:UIApplicationDidChangeStatusBarFrameNotification object:nil];
Then in the orientation change event handler and change the transform and the frame. (see my question to see the method which handles the transforms)
CGRect bounds = CGRectMake(0, 0, 100, 100);
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
self.frame = [self getTopRectForBounds:bounds orientation:orientation window:self.window]
CGFloat angle = [self angleForOrientation:orientation];
self.transform = CGAffineTransformMakeRotation(angle);
I'm trying to add a UIWindow with UIWindowLevelStatusBar level. it works in portrait mode on ipad perfectly but after rotating device its messed up.
on iOS 7.x all rotations are fine except for upside-down, and on iOS 8.x only portrait mode is fine and all other orientations are messed up. any idea how to solve that?
CGRect frame = [UIApplication sharedApplication].statusBarFrame;
self.statusWindow = [[UIWindow alloc] initWithFrame:CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, 20)];
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect frame = [UIApplication sharedApplication].statusBarFrame;
CGAffineTransform test = [self transformForOrientation:orientation];
[self.statusWindow setWindowLevel:UIWindowLevelStatusBar];
[self.statusWindow setHidden:NO];
- (CGAffineTransform)transformForOrientation:(UIInterfaceOrientation)orientation
{
switch (orientation)
{
case UIInterfaceOrientationLandscapeLeft:
return CGAffineTransformMakeRotation(-DEGREES_TO_RADIANS(90.0f));
case UIInterfaceOrientationLandscapeRight:
return CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(90.0f));
case UIInterfaceOrientationPortraitUpsideDown:
return CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(180.0f));
case UIInterfaceOrientationPortrait:
default:
return CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(0.0f));
}
}
In your UIWindow subclass' init method, observe this notification:
// Rotation Notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didChangeOrientation:) name:UIDeviceOrientationDidChangeNotification object:nil];
self.baseT = self.transform;
Then the method itself:
- (void)didChangeOrientation:(NSNotification *)n
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
switch (orientation) {
case UIInterfaceOrientationPortrait:
self.transform = CGAffineTransformRotate(self.baseT, 0);
break;
case UIInterfaceOrientationPortraitUpsideDown:
self.transform = CGAffineTransformRotate(self.baseT, M_PI);
break;
// Home button on left
case UIInterfaceOrientationLandscapeLeft:
self.transform = CGAffineTransformRotate(self.baseT, -M_PI_2);
break;
case UIInterfaceOrientationLandscapeRight:
self.transform = CGAffineTransformRotate(self.baseT, M_PI_2);
break;
default:
self.transform = CGAffineTransformMakeRotation(0);
break;
}
}
Depending on your implementation, you may have to also ensure the frame doesn't change. Also, in the Class' dealloc method, stop listening to the notifications.
As a modification to #dezinezync's answer: performing the rotation would work better if you put it in the willRotateToInterfaceOrientation method of the view controller. This way, the rotation will only be applied if the device is rotated to one of the supported orientations specified in the General -> Deployment Info section of the app's build settings. As an added bonus, you get access to the duration of the rotation animation. Just make sure you have a reference to your modal window in the view controller.
The UIDeviceOrientationDidChangeNotification notification is fired whenever the screen orientation changes, regardless of what orientations are supported. This can lead to undesireable behavior.
Here's an example:
UIWindow *modalWindow;
// Initialize your modal window somewhere in your code
// ...
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
// Make sure the modalWindow exists
if (modalWindow != nil)
{
// Animate the modal window's rotation
[UIView animateWithDuration:duration animations:^{
[self rotateModal:modalWindow];
}];
}
}
- (void)rotateModal:(UIWindow*)window
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
switch (orientation) {
case UIInterfaceOrientationPortrait:
window.transform = CGAffineTransformRotate(self.baseT, 0);
break;
case UIInterfaceOrientationPortraitUpsideDown:
window.transform = CGAffineTransformRotate(self.baseT, M_PI);
break;
// Home button on left
case UIInterfaceOrientationLandscapeLeft:
window.transform = CGAffineTransformRotate(self.baseT, -M_PI_2);
break;
case UIInterfaceOrientationLandscapeRight:
window.transform = CGAffineTransformRotate(self.baseT, M_PI_2);
break;
default:
window.transform = CGAffineTransformMakeRotation(0);
break;
}
}
I just did something like this on a landscape-only app, and I finally got it working properly by moving everything to the willRotateToInterfaceOrientation method.
Solution for iOS8 (need a transform as showed above as well):
UIScreen *screen = [UIScreen mainScreen];
CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
if ([screen respondsToSelector:#selector(fixedCoordinateSpace)])
{
[self setFrame:[screen.coordinateSpace convertRect:statusBarFrame toCoordinateSpace:screen.fixedCoordinateSpace]];
}
However it does not work for iOS9 beta.
I am trying to add an image view to my application window which consists of a splitviewcontroller. The reason I am doing this is so that I can fade it out like a splash screen. The application is for iPad and only works in the landscape mode. The launch image is the same as the splash image so it is a seamless transition between the two, then I can manually fade out the splash. However I am having trouble adding the splash to the window's subview in the same orientation as the launch image so that the transition from the launchimage to the splash is seamless and cannot be noticed. Here is what I have so far:
- (void)viewDidLoad
{
[super viewDidLoad];
UIWindow *window = [[UIApplication sharedApplication] delegate].window;
UIImageView *splash = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
splash.image = [UIImage imageNamed:#"Default-Landscape~ipad.png"];
[splash rotateToInterfaceOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
[window addSubview:splash];
}
#interface UIView (Orientation)
- (void)rotateToInterfaceOrientation:(UIInterfaceOrientation)orientation;
#end
#implementation UIView (Orientation)
- (void)rotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
{
CGFloat angle = 0.0;
switch (orientation) {
case UIInterfaceOrientationPortraitUpsideDown:
angle = M_PI;
break;
case UIInterfaceOrientationLandscapeLeft:
angle = - M_PI / 2.0f;
break;
case UIInterfaceOrientationLandscapeRight:
angle = M_PI / 2.0f;
break;
default: // As portrait
angle = 0.0;
break;
}
self.transform = CGAffineTransformMakeRotation(angle);
}
#end
I am developing an iOS application in which I need to rotate 6 UIViews so they are always "facing" the user. The rest of the interface doesn't need to be rotated.
The code below was working amazingly in the Simulator. However when I tested on my phone I faced a problem. Whenever I put the phone in a flat origination/horizontal, it understand it should go back to portrait. Any idea what this is happening and a work around?
#pragma mark Rotation
- (BOOL)shouldAutorotate
{
return NO;
}
- (void)orientationChanged:(NSNotification *)notification
{
CGFloat rotationAngle = [self convertOrientationToRadians];
[UIView animateWithDuration:0.5 animations:^{
for (TimerButton *timerButton in self.timerButtons) {
timerButton.button.transform = CGAffineTransformMakeRotation(rotationAngle);
}
}];
}
- (CGFloat)convertOrientationToRadians
{
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
CGFloat rotationAngle = 0.0;
switch (orientation) {
case UIDeviceOrientationPortrait:
rotationAngle = 0.0;
break;
case UIDeviceOrientationLandscapeLeft:
rotationAngle = M_PI / 2;
break;
case UIDeviceOrientationPortraitUpsideDown:
rotationAngle = M_PI;
break;
case UIDeviceOrientationLandscapeRight:
rotationAngle = - M_PI / 2;
break;
default:
break;
}
return rotationAngle;
}
Your default value for rotation angle is 0, and the case UIDeviceOrientationFaceUp is not explicitly handled.
Alternatively, you could call [[UIApplication sharedApplication] statusBarOrientation] rather than [UIDevice currentDevice].orientation.