camera overlay view - just for preview?

2019-01-21 15:01发布

问题:

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.

回答1:

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).



回答2:

I just wanted to show up another possibility without subview fiddling. There are system notifications for the changes in the CameraPicker. They are not documented either (as the subview structure). So they are also subject to change. BUT you get them.

You can register for them using no name:

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(notificationReceived:) name: nil object: nil];

We get some interesting (selfexplaining) notifications here:

PLCameraControllerPreviewStartedNotification
PLCameraViewIrisAnimationWillBeginNotification
PLCameraViewIrisAnimationDidEndNotification

Recorder_DidStartPreviewing
Recorder_SourceStarted
Recorder_WillCapturePhoto
Recorder_DidCapturePhoto
Recorder_PhotoStillImageSampleBufferReady
Recorder_DidStopPreviewing

_UIImagePickerControllerUserDidCaptureItem // Photo was taken, preview is shown
_UIImagePickerControllerUserDidRejectItem  // Repeat was pressed, camera is shown again 

You could use them, to trigger your overlayviews hidden state or anything else.



回答3:

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.



回答4:

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: