views:

1769

answers:

3

I've noticed that in OS 3.1 you can add an overlay view to the image picker with

cameraOverlayView

However, I've also noticed that adding a view via this method also displays the view for the entire time the UIImagePicker is displayed, when I only want to show it during the preview stage.

Is there a way to make this only happen during preview? I don't want it to be there during the open shutter animation, or the screen that asks whether you want to use the image or retake.

A: 

When you build up the picker add the overlay to the picker (picker.cameraOverlayView = myView).

The overlay will not be in the picture taken. It is just, like it says, an overlay view.

You can remove the overlay view before taking a picture (takePicture method) and add the view again in imagePickerController:didFinishPickingMediaWithInfo:

Diederik Hoogenboom
Sorry, this is not what I'm looking for. I want to display the overlay only before taking the picture. Not whilst the camera shutter is animating, or whilst it is asking you whether you like the picture you took
mac_55
If you remove the overlay (picker.cameraOverlayView = nil) before calling takePicture then the overlay will not be there when the shutter is animating.
Diederik Hoogenboom
But how do I show it on the preview screen? Am I right in assuming that takePhoto captures whatever is in the preview screen? But I want to display the overlay on the preview screen (before the photo is taken) *confused*
mac_55
I have updated the answer with more info
Diederik Hoogenboom
I think you are misunderstanding what I'm trying to do. I realise that the overlay is not included in the picture taken, but it *is* on the screen throughout the capture process - I don't want it to be shown on the screen for all this time, only on the screen where the user sees the 'take picture' button.
mac_55
+1  A: 

Hello mac_55!

I've figured out a way for you to achieve the desired result though it's a bit... not so standard. :)

The idea is to rearrange a bit the order of the inner views in the structure UIImagePickerController uses.

OK, so we create an UIImagePickerController object, initialize it and add an overlay view to it. May I have your attention please! The UIView object (UIImageView in the example code) is hidden from the very beginning. Don't miss that. Finally we present the image picker controller as modal view controller. This code should be somewhere in your applicationDidFinishLaunching:, viewWillAppear: or similar appropriate about to launch methods.

UIImagePickerController *anImagePickerController = [UIImagePickerController new];
anImagePickerController.delegate = self;
anImagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;

UIImageView *anImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Watermark.png"]];
anImageView.frame = CGRectMake(0, 1, anImageView.image.size.width, anImageView.image.size.height);
anImageView.hidden = YES;
anImagePickerController.cameraOverlayView = anImageView;

[viewController presentModalViewController:anImagePickerController animated:NO];
[anImagePickerController release];

[NSTimer scheduledTimerWithTimeInterval:0.1
                                 target:self
                               selector:@selector(timerFireMethod:)
                               userInfo:anImageView
                                repeats:YES];
[anImageView release];

Before the overlay view (anImageView) is released a NSTimer is created, initialized with anImageView (NSTimer userInfo property) and scheduled right away. Here's the method it calls:

- (void)timerFireMethod:(NSTimer*)theTimer {
    UIView *cameraOverlayView = (UIView *)theTimer.userInfo;
    UIView *previewView = cameraOverlayView.superview.superview;

    if (previewView != nil) {
        [cameraOverlayView removeFromSuperview];
        [previewView insertSubview:cameraOverlayView atIndex:1];

        cameraOverlayView.hidden = NO;

        [theTimer invalidate];
    }
}

The whole NSTimer thing is added to the flow to ensure that the reordering work around will happen exactly when the UIImagePickerController will be totally ready for that.

This is it. It works, it's not standard, it's rough and quick. Again feel free to optimize and make it 'righter' (oh please do, my aim was to show you the way).

Ivan Karpan
I was thinking of setting the view to display after a timer has run, however I wasn't sure if the camera always takes the same length of time to load - doesn't it depend on how much memory is in use at the time, and what device it's running on? e.g. it'll load faster on a 3GS than on a 3G.
mac_55
Hey mac_55, I've optimized my solution - now it works perfecto (as perfecto as a work around solution can work). :) HTH
Ivan Karpan
Sorry for the delay. I haven't got around to testing this yet, but I'm happy to mark it as the answer. :)
mac_55
+1  A: 

Actually, I was trying to do the same thing and I came across a much simpler of doing it via this blog post: http://www.alexcurylo.com/blog/2009/06/18/uiimagepickercontroller-in-3-0/

Since the UIImagePickerController can call a UINavigatorControllerDelegate, the method below gets called before the Image picker is displayed.

Here's the important code:

 - (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
   if (!viewController)
   return;

   UIView* controllerViewHolder = viewController.view;
   UIView* controllerCameraView = [[controllerViewHolder subviews] objectAtIndex:0];
   UIView* controllerPreview = [[controllerCameraView subviews] objectAtIndex:0];
   [controllerCameraView insertSubview:self.overlayView aboveSubview:controllerPreview];
}

Hope that helps.

naragon