Uiimagepicker Cameraoverlayview Appears on Retake Screen

UIImagePicker cameraOverlayView appears on Retake screen

Solved by signing up to NSNotificationCenter, and listening to @"_UIImagePickerControllerUserDidCaptureItem" and @"_UIImagePickerControllerUserDidRejectItem".

iPhone camera, how to avoid cameraOverlay on preivew view; How to know when entering preview view?

Found a solution. Was hard to find, but finally got it. The solution is described at UIImagePicker cameraOverlayView appears on Retake screen. Additionally I add my working code for others who have the same problem.

The use of the NSNotificationCenter with @"_UIImagePickerControllerUserDidCaptureItem" and @"_UIImagePickerControllerUserDidRejectItem" is the key!

CamViewController.h

#import <UIKit/UIKit.h>
#import "CameraViewController.h"
#import <AssetsLibrary/AssetsLibrary.h>

@interface CamViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@property (nonatomic, strong) UIImage *image;
@property (nonatomic, strong) UIImage *lastTakenImage;
@property (nonatomic, strong) UIImagePickerController *picker;
- (IBAction)takePhoto:(id)sender;
- (IBAction)selectPhoto:(id)sender;
@end

CamViewController.h

#import "CamViewController.h"

@interface CamViewController ()

@end

@implementation CamViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}

int isAction = 0; // Photo, 1: CameraRoll, 2: Cancel

- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:@"_UIImagePickerControllerUserDidCaptureItem" object:nil ];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:@"_UIImagePickerControllerUserDidRejectItem" object:nil ];

[super viewDidLoad];
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {

UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:@"Error"
message:@"Device has no camera"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles: nil];

[myAlertView show];

}
isAction = 0;
[self cameraRoll];
}

-(void)handleNotification:(NSNotification *)message {
if ([[message name] isEqualToString:@"_UIImagePickerControllerUserDidCaptureItem"]) {
// Remove overlay, so that it is not available on the preview view;
self.picker.cameraOverlayView = nil;
}
if ([[message name] isEqualToString:@"_UIImagePickerControllerUserDidRejectItem"]) {
// Retake button pressed on preview. Add overlay, so that is available on the camera again
self.picker.cameraOverlayView = [self addCameraRollButton];
}
}

-(void)viewDidAppear:(BOOL)animated {
// isAction = 0: Photo, 1: CameraRoll, 2: Cancel
DLog(@"###### isAction> %d", isAction);

switch (isAction) {
case 1:
[self selectPhoto:nil];
break;
case 2:
[self dismissViewControllerAnimated:NO completion:nil];
break;
default:
[self takePhoto:nil];
break;
}
}

- (IBAction)takePhoto:(id)sender {
self.picker = [[UIImagePickerController alloc] init];
self.picker.delegate = self;
self.picker.allowsEditing = YES; // if this is NO or missing, the image the image will not be in info[UIImagePickerControllerEditedImage]
self.picker.sourceType = UIImagePickerControllerSourceTypeCamera;
self.picker.cameraOverlayView = [self addCameraRollButton];

[self presentViewController:self.picker animated:YES completion:NULL];
}

-(void)prepareCameraRoll {
isAction = 1;
[self dismissViewControllerAnimated:NO completion:nil];

}

- (IBAction)selectPhoto:(id)sender {

self.picker = [[UIImagePickerController alloc] init];
self.picker.delegate = self;
self.picker.allowsEditing = YES;
self.picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

[self presentViewController:self.picker animated:YES completion:NULL];
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

self.image = info[UIImagePickerControllerEditedImage];

isAction = 0;
[picker dismissViewControllerAnimated:YES completion:NULL];
[self performSegueWithIdentifier:@"toCameraView" sender:info];

}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {

isAction = 2; // Cancel
[picker dismissViewControllerAnimated:YES completion:NULL];

}

# pragma mark - CameraRoll function and presentation
- (UIView *)addCameraRollButton {
float startY = ([[UIScreen mainScreen] bounds].size.height == 568.0) ? 500.0 : 410.0;

UIButton *rollButton = [UIButton buttonWithType:UIButtonTypeCustom];
rollButton.frame = CGRectMake(230.0, startY, 60.0, 60.0);
rollButton.backgroundColor = [UIColor clearColor];

[rollButton setImage:self.lastTakenImage forState:UIControlStateNormal];
rollButton.imageView.contentMode = UIViewContentModeScaleAspectFill;

[rollButton addTarget:self action:@selector(prepareCameraRoll) forControlEvents:UIControlEventTouchUpInside];

return rollButton;
}

-(void)cameraRoll {
// have to import assetlibrary framework!!!
ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];
[assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos
usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
if (nil != group) {
// be sure to filter the group so you only get photos
[group setAssetsFilter:[ALAssetsFilter allPhotos]];

[group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop) {
if (asset) {
ALAssetRepresentation *repr = [asset defaultRepresentation];
// UIImage *img = [UIImage imageWithCGImage:[repr fullResolutionImage]];
UIImage *img = [UIImage imageWithCGImage:[repr fullScreenImage]];
[self setLastTakenImage:img];
*stop = YES;
}
}];
}

*stop = NO;
} failureBlock:^(NSError *error) {
NSLog(@"error: %@", error);
}];
}

#pragma mark - Navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
CameraViewController *cvc = [segue destinationViewController];

cvc.image = self.image;
DLog(@"%@, cvcimage", cvc.image);
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}

@end

camera overlay view - just for preview?

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



Related Topics



Leave a reply



Submit