iOS, PopOverPresentationController issue, .xib - ios

I have a NavigationController, another controller was pushed on its stack: BNRDetailsViewController. Now, inside BNRDetailsViewController I am trying to show a popover window when pressing on a toolbar button, that would present me with UIImagePickerController (only on iPad devices). So, I tried to follow the following stackoverflow thread:
UIPopoverPresentationController on iOS 8 iPhone
But no success. If I just use their code I get an error that says, that pushing navigationController is not supported. If I try to push the newly created UIPopoverPresentationController like this: [self.navigationController pushViewController:self.imagePickerPopover animated:YES]; it crashes because UIPopoverPresentationController is not of type UIViewController, so, I guess, I can not just push it on the stack.
What would you suggest to do in this particular case?
Here is the code which I have right now that is triggered when the toolbar button is pressed:
- (IBAction)takePicture:(id)sender {
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
// If the device have camera, take a picture, otherwise,
// just pick from photo library
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
} else {
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
imagePicker.delegate = self;
// Place image picker on the screen
//[self presentViewController:imagePicker animated:YES completion:NULL];
// Place image picker on the screen
// Check for iPad device before instantiating the popover controller
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
// Create a new popover controller that will display the imagePicker
_imagePickerPopover = [[UIPopoverPresentationController alloc] initWithPresentedViewController:imagePicker presentingViewController:self];
imagePicker.preferredContentSize = CGSizeMake(280, 200);
_imagePickerPopover.delegate = self;
_imagePickerPopover.sourceView = self.view;
CGRect frame = [[sender valueForKey:#"view"] frame];
frame.origin.y = frame.origin.y + 20;
_imagePickerPopover.sourceRect = frame;
// [self.navigationController pushViewController:self.imagePickerPopover animated:YES];
}
}

Here is the code, based on your code, that will get the popover to display on the iPad.
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
imagePicker.modalPresentationStyle = UIModalPresentationPopover;
imagePicker.preferredContentSize = CGSizeMake(280, 200);
CGRect frame = [[sender valueForKey:#"view"] frame];
frame.origin.y = frame.origin.y + 20;
UIPopoverPresentationController *popoverController =
imagePicker.popoverPresentationController;
popoverController.sourceView = self.view;
popoverController.sourceRect = frame;
[self.navigationController presentViewController:imagePicker
animated:YES completion:nil];
}

Related

Can't present imagepicker immediately

I have a Tab bar controller, when I tap the third tab bar button I present a UIViewcontroller. In the viewWillAppear of this vc I'm presenting a UIImagepickerController that works fine. The problem is I can't display it on the screen immediately when I open the view. First the vc shows up and after 0.4-0.5 sec the image picker. So I would like to present the image picker first and present the vc after the user took an image. I tried to call the picker from viewDidLoad and viewWillAppear too, but nothing changed.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (imagePickerWasPresented == NO)
{
imagePickerWasPresented = YES;
self.imagePicker = [[UIImagePickerController alloc] init];
self.imagePicker.delegate = self;
self.imagePicker.allowsEditing = YES;
self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
self.imagePicker.mediaTypes = [NSArray arrayWithObject:(NSString *)kUTTypeImage];
[self presentViewController:self.imagePicker animated:NO completion:nil];
}
}
Am I calling it in a wrong place?
I had the same problem - instead of calling the VC and then the UIImagePicker, call the UIImagePicker directly.
When you are done taking a picture/video:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {}
you will go to this standard delegate method, call the VC from here. This way you will immediately go to the ImagePicker and only have a transition would you choose to do something with the taken content afterwards which is less frustrating/ugly.
No, your calling it in an okay place, that's just how iOS does it; if you present multiple modals on top of each other, one gets presented after the other, including the animation. A solution that would work for your problem is to present a UINavigationController instead of your UIViewController. Set the navigation controller up to have ViewController as the root viewcontroller, but also push your imagepickercontroller onto the stack. Present this navigationcontroller and it should go right to your imagepickercontroller. Otherwise, try presenting both uiviewcontroller and imagepickercontroller with animation set to NO and see if that works.
try this to see how close that gets you then adapt to your needs. when i gave it a quick test it seemed to do what you were asking.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] ;
UIViewController * vc = [[UIViewController alloc] init];
vc.view.backgroundColor = [UIColor whiteColor];
UINavigationController * navigationController = [[UINavigationController alloc] init];
[navigationController pushViewController:vc animated:NO];
UITabBarController * tabBarController = [[UITabBarController alloc] init];
NSArray* controllers = [NSArray arrayWithObjects:navigationController, nil];
tabBarController.viewControllers = controllers;
tabBarController.delegate = self;
UIImagePickerController *imagePicker =
[[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType =
UIImagePickerControllerSourceTypePhotoLibrary;
imagePicker.mediaTypes = [NSArray arrayWithObjects:
(NSString *) kUTTypeImage,
nil];
imagePicker.allowsEditing = NO;
self.window.rootViewController = tabBarController;
[self.window makeKeyAndVisible];
[vc presentViewController:imagePicker animated:NO completion:nil];
return YES;
}
UIImage as a PopOver
Gallery mode:
BOOL hasGallery = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary];
UIImagePickerController* picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = hasGalleryt ? UIImagePickerControllerSourceTypePhotoLibrary : UIImagePickerControllerSourceTypePhotoLibrary;
if (self.popoverController != nil)
{
[self.popoverController dismissPopoverAnimated:YES];
self.popoverController=nil;
}
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:picker];
CGRect popoverRect = [self.view convertRect:[self.imageView frame]
fromView:[self.imageView superview]];
popoverRect.size.width = MIN(popoverRect.size.width, 300) ;
popoverRect.origin.x = popoverRect.origin.x;
[self.popoverController
presentPopoverFromRect:popoverRect
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
Camera mode:
BOOL hasCamera = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
UIImagePickerController* picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = hasCamera ? UIImagePickerControllerSourceTypeCamera : UIImagePickerControllerSourceTypePhotoLibrary;
if (self.popoverController != nil)
{
[self.popoverController dismissPopoverAnimated:YES];
self.popoverController = nil;
}
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:picker];
CGRect popoverRect = [self.view convertRect:[self.imageView frame]
fromView:[self.imageView superview]];
popoverRect.size.width = MIN(popoverRect.size.width, 300) ;
popoverRect.origin.x = popoverRect.origin.x;
[self.popoverController
presentPopoverFromRect:popoverRect
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
Remember to give to the .h File #interface the delegates, like this:
#interface the UIViewController: UIViewController <UIPopoverControllerDelegate, UIImagePickerControllerDelegate>

MPMediaPickerController very slow on iPad ios7

I am trying to display a MPMediaPickerController in a popover on iOS7+ and it is VERY slow. It takes about 4 seconds from the first NSLog to the second NSLog. I have tried retaining the picker but this makes no difference. Any ideas would be greatly appreciated.
- (void) showMediaPickerControllerWithArrowDirection:(UIPopoverArrowDirection)arrow_direction
{
MPMediaPickerController *self.picker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeAnyAudio];
self.picker.modalPresentationStyle = UIModalPresentationPopover;
self.picker.delegate = self;
self.picker.allowsPickingMultipleItems = YES;
UIPopoverPresentationController *popPresenter = self.picker.popoverPresentationController;
popPresenter.sourceView = self.view;
popPresenter.sourceRect = self.view.bounds;
popPresenter.permittedArrowDirections = arrow_direction;
NSLog(#"____________________________ about to launch picker ");
[self.viewController presentViewController:self.picker animated:YES completion:^{
NSLog(#"____________________________ picker launched ");
}];
}

Hide UIPopoverController background

I am loading a UIPopoverController that contains a UIImagePickerController, when the view loads it loads a seethrough view behind the popover, which if touched it dismisses the popover and the the cameraview inside it.
I would like to know if there is a way to remove this background view and control the dismiss myself with buttons.
My goal is to have some information to the left and the camera popover view to the right, but I cannot do this as some of the information is selectable i.e. textfields, and currently this background view is preventing selection of them.
This is my code for the popovercontroller and the UIImagePickerController.
- (void) cameraButtonSelected
{
// set background
UIView *cameraBG = [[UIView alloc] initWithFrame:CGRectMake(0.0, 20.0, screenHeight, screenWidth-64)];
cameraBG.backgroundColor = [UIColor blackColor];
cameraBG.alpha = 0.8;
[self.view addSubview:cameraBG];
// create picker
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
CGFloat scaleFactor=1.3f;
picker.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * -90 / 180.0), scaleFactor, scaleFactor);
}
// create popover
self.popOver = [[UIPopoverController alloc] initWithContentViewController:picker];
[self.popOver presentPopoverFromRect:CGRectMake(500, 100, 0, 0) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:NO];
}
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
viewController.preferredContentSize = CGSizeMake(805, 650);
}
You can just call,
self.popOver.hidden = YES; or self.popOver.hidden = NO;
If you want the pop0ver view to still be drawn but still hidden to the user, you can call self.pop0ver.alpha = 0.0f;

UIPickerController iPad capture cropping size

I used a very popular code to capture photo with iPad
-(void)presentImagePicker:(UIImagePickerControllerSourceType)source sender:(UIButton *)sender
{
if (!self.popOver && [UIImagePickerController isSourceTypeAvailable:source])
{
NSArray *availableMedia = [UIImagePickerController availableMediaTypesForSourceType:source];
if ([availableMedia containsObject:(NSString*)kUTTypeImage])
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = source;
picker.mediaTypes = #[(NSString*)kUTTypeImage];
picker.allowsEditing = YES;
if (source != UIImagePickerControllerSourceTypeCamera &&
UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
self.popOver = [[UIPopoverController alloc] initWithContentViewController:picker];
[self.popOver presentPopoverFromRect:sender.bounds
inView:sender
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
self.popOver.delegate = self;
}
else
{
[self presentViewController:picker animated:YES completion:nil];
}
}
}
}
The problem is that when the picker shows up, the cropping-size of the capture image is different from the size of the iPad (full screen). It is like a box centered in the screen.
When I take the picture in portrait mode, the captured image is not the portrait image, but something different in size.
My application can run only in landscape mode: is that the problem?
The solution is here
GKImage picker
a custom picker, very very useful.

iPad Camera has incorrect screen placement when you open it

I am developing an iPad app to take a photo or choose from library.
It works fine, the only problem is the camera layout incorrectly when you follow the steps below.
List item
Tap btnPhotoLibrary button
Cancel the popover
Tap btnCamera button
The resulting layout is very similar to the image in
Camera has incorrect screen placement when open fullscreen modal from popover.
It is positioned slightly lower than the screen bounds. This means
that the controls at the bottom are 20px south of the screen and there
is a 20px black band at the top of the screen
You have no problem if you do not tap btnPhotoLibrary but btnCamera only.
We are using the same UIImagePickerController instance for both of camera and photolibrary, so we probably need to reset some properties before using it as a camera, but could not find a way.
--
- (void)viewDidLoad {
[super viewDidLoad];
_imagePicker = [[UIImagePickerController alloc]init];
_imagePicker.allowsEditing = FALSE;
_imagePicker.delegate = self;
}
-(IBAction)btnCamera:(id)sender{
if ([popover isPopoverVisible]) {
[popover dismissPopoverAnimated:YES];
}
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
_imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:_imagePicker animated:YES completion:nil];
}
}
-(IBAction)btnPhotoLibrary:(id)sender{
_imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
if ([popover isPopoverVisible]) {
[popover dismissPopoverAnimated:YES];
}
popover = [[UIPopoverController alloc] initWithContentViewController:_imagePicker];
[popover presentPopoverFromRect:btnCameraRoll.bounds inView:btnPhotoLibrary permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
}
The target os is iOS6.1, landscape view.
Thanks in advance.
It seems that resetting view property of UIImagePickerController to nil does the trick, but I guess it's almost identical to creating a new instance of UIImagePickerController every time you need.
-(IBAction)btnCamera:(id)sender{
if ([popover isPopoverVisible]) {
[popover dismissPopoverAnimated:YES];
}
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
_imagePicker.view = nil;
_imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:_imagePicker animated:YES completion:nil];
}
}

Resources