I am using UIImagePickerController to select a single image from photo library. There is a strange issue on iPad when it is in landscape mode.
The image picker is presented using UIPopoverPresentationController on iPad as recommended. When it is first presented, the status bar is correct:
However, when going into the second level of the photo library, the status bar is changed to portrait mode:
What I have noticed so far are:
This issue only appears in iOS 11, not iOS 10.
When it happens, rotate the iPad to portrait and back to landscape will fix the status bar orientation.
It only happened the first time presenting the picker controller.
If ignore, presenting other modal view will be in portrait mode:
The code that presenting the uiimagepickerController is as follow:
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.modalPresentationStyle = UIModalPresentationPopover;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self;
[self presentViewController:picker animated:YES completion:nil];
UIPopoverPresentationController *popupController = picker.popoverPresentationController;
if (popupController) {
popupController.barButtonItem = sender;
}
Any idea what have I done wrong, or it is a bug?
Whole example project can be downloaded here:
https://www.dropbox.com/s/zgipclyr0mz26c6/test.zip?dl=0
I have finally found the cause of my issue.
My app needs to support all orientation on iPad and Portrait mode only on iPhone. Therefore I added the following code of UIApplicationDelegate:
- (UIInterfaceOrientationMask) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (window.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
return UIInterfaceOrientationMaskAll;
}
return UIInterfaceOrientationMaskPortrait;
}
But sometimes it gives me nil window, as in the case of UIImagePickerController presented using UIPopoverPresentationController on iPad, and will return UIInterfaceOrientationMaskPortrait and cause the status bar rotates to portrait mode. I have also noticed that this happens only when UIRequiresFullScreen is checked.
I have solved my issue by checking that window is not nil as below:
- (UIInterfaceOrientationMask) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (window) {
if (window.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
return UIInterfaceOrientationMaskAll;
} else {
return UIInterfaceOrientationMaskPortrait;
}
} else {
return UIInterfaceOrientationMaskAll;
}
}
As I am working with iOS application support only Portrait Orientation.
But I am getting some Orientation related issue.
My app support only portrait orientation
when my parent P1.view is push using navigation it is in portrait mode thats fine. Now from P1.view I am subviewing my child view C1.view
Now I am in childview C1.view and from there using delegate I am calling
-(void)imagePickerController:(UIImagePickerController *)picker
[self.delegate openCamera];//called from C1.view
-(void)openCamera //declared in P1.view
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = NO;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;>
[self presentModalViewController:picker animated:YES];
}
Now when I capture photo in Lanscape mode and dismiss that
presentModalViewController my view appears in Landscapmode instead of Portrait
mode.
- (BOOL)shouldAutorotate {
return YES;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return (interfaceOrientation == UIInterfaceOrientationPortrait ||
interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
}
- (NSUInteger)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
}
This methods are define in both the view controller(P1 & C1) and also called when modelview dismiss, but my viewcontroller remains in Landscape which should not be happen.
This code working fine in iOS6 but not iOS7
I think that preferredInterfaceOrientationForPresentation is not supposed to return a bit mask. You could try:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
I'm creating an app that is landscape only, it uses an image picker control.
Looking through the site I've discovered that apple only allow portrait for this for some reason. I'm okay with it flipping to portrait for this one section, if it means the user can select a photo from the library.
Below is my code that gives an error about it being in landscape mode. How do I fix this to say it's okay to flip it to portrait. thanks
-(IBAction)takePhoto{
takePicker = [[UIImagePickerController alloc]init];
takePicker.delegate = self;
[takePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
[self presentViewController:takePicker animated:YES completion:NULL];
}
-(IBAction)chooseExisiting{
choosePicker = [[UIImagePickerController alloc]init];
choosePicker.delegate = self;
[choosePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
[self presentViewController:choosePicker animated:YES completion:NULL];
}
You don't have to use ImagePickerController in portrait mode.
Just subclass it to open in landscape mode :
#interface NonRotatingUIImagePickerController : UIImagePickerController
#end
#implementation NonRotatingUIImagePickerController
- (BOOL)shouldAutorotate
{
return NO;
}
#end
After that, you can use your code with that class.
-(IBAction)takePhoto {
takePicker = [[NonRotatingUIImagePickerController alloc]init];
takePicker.delegate = self;
[takePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
[self presentViewController:takePicker animated:YES completion:NULL];
}
-(IBAction)chooseExisiting{
choosePicker = [[NonRotatingUIImagePickerController alloc]init];
choosePicker.delegate = self;
[choosePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
[self presentViewController:choosePicker animated:YES completion:NULL];
}
Why present an error at all? Why not just present the image picker in portrait? People are smart enough to rotate their device. Or you could write your own landscape image picker, or use one of the several open source ones available.
I am creating an app which is in landscape mode and I am using UIImagePickerController to take photos using iPhone camera in it and I want to create it in landscape mode too.
But as the Apple documention suggests UIImagePickerController does not support landscape orientation, so what should I do to get desired functionality?
If you'd like to use UIImagePickerController in landscape mode, use user1673099's answer, but instead of:
- (BOOL)shouldAutorotate
{
return NO;
}
use:
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
}
and then the picker would open in landscape mode:
But make sure you check Portrait in deployment info:
... and I want to create it in landscape mode too.
One line of code can make a big difference! In the method or function where your IBAction lands:
In Swift,
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
// .overCurrentContext allows for landscape and portrait mode
imagePickerController.modalPresentationStyle = .overCurrentContext
Objective-C,
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
[imagePickerController setDelegate:self];
[imagePickerController setModalPresentationStyle: UIModalPresentationOverCurrentContext];
Note: This will allow imagePickerController to present it's view correctly, but will may not fix the issue of rotation while it is presented.
Try this way....
As per Apple Document, ImagePicker Controller never Rotate in Landscape mode. You have to use in Portrait Mode only.
For disable Landscape mode only for ImagePicker Controller follow below code:
In your ViewController.m:
Make the SubClass(NonRotatingUIImagePickerController) of Image Picker Controller
#interface NonRotatingUIImagePickerController : UIImagePickerController
#end
#implementation NonRotatingUIImagePickerController
// Disable Landscape mode.
- (BOOL)shouldAutorotate
{
return NO;
}
#end
Use as follow
UIImagePickerController* picker = [[NonRotatingUIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self;
etc.... Just as Default ImagePicker Controller
This is working for me & Let me know if you have any Problem.
This works great with Swift 4.0 in iOS 10/11.
import UIKit
extension UIImagePickerController {
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .all
}
}
Just drop the extension somewhere in your project, no need to subclass anything for it to work.
If you do need to specify device types, you can add a check like this:
import UIKit
extension UIImagePickerController {
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return UIDevice.current.userInterfaceIdiom == .phone ? .portrait : .all
}
}
This will allow an iPad to freely rotate, but enforces portrait mode on a phone. Just make sure that your app is configured to support these in its info.plist, otherwise you may encounter crashes upon launching the picker.
Here's a version that supports rotation in all interface orientations:
/// Not fully supported by Apple, but works as of iOS 11.
class RotatableUIImagePickerController: UIImagePickerController {
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .all
}
}
This way if the user rotates her device, it'll update the picker controller to support the current orientation. Just instantiate as you normally would a UIImagePickerController.
If you only want to support a subset of orientations, you can return a different value.
The correct way to use UIImagePickerController in landscape mode without any hacks is to put it into a UIPopoverController
- (void)showPicker:(id)sender
{
UIButton *button = (UIButton *)sender;
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
_popover = [[UIPopoverController alloc] initWithContentViewController:picker];
[_popover presentPopoverFromRect:button.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
Modify above code method
- (NSUInteger)supportedInterfaceOrientations
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if(orientation == UIDeviceOrientationLandscapeRight || orientation == UIDeviceOrientationLandscapeLeft)
return UIInterfaceOrientationMaskLandscape;
else
return UIInterfaceOrientationMaskPortrait;
}
Accepted answer doesn't work for me. I had also to add modalPresentationStyle to UIImagePickerController to make it working.
UIImagePickerController *pickerController = [[UIImagePickerController alloc] init];
pickerController.modalPresentationStyle = UIModalPresentationCurrentContext; //this will allow the picker to be presented in landscape
pickerController.delegate = self;
pickerController.allowsEditing = YES;
pickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:pickerController animated:YES completion:nil];
And of course remember to put this in a controller that presents the picker:
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape; //this will force landscape
}
But according to Apple's documentation this is not supported to present this picker in the landscape mode so be careful about it.
If you're looking for SwiftUI solution in conjunction with the things mentioned here check this out here. Ignoring the safe area for the UIImagePickerController representable resolved a lot of my issues.
I am working on a application which has to play videos when clicking on some thumbnail, I am displaying list. I want only the Video to rotate in Landscape and Portrait Mode but other screens must in Portrait Mode How can we do this.
In ViewWillAppear
UIViewController *vc = [[UIViewController alloc] init];
[self presentViewController:vc animated:NO completion:NULL];
[self dismissViewControllerAnimated:NO completion:NULL];
This will trigger the redrawing of the view and thus calling following functions, provided you have implemented these
- (BOOL)shouldAutorotate{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}