Set minimum zoom level for UIImagePickerController

2020-03-03 08:21发布

问题:

I am using a UIImagePickerController to allow the user to upload a photo for use in my application. After selecting a photo to upload, the user is then prompted to crop his/her photo (since I have set imagePickerController.allowsEditing = YES). However, if the photo is landscape (i.e., wider than it is taller), it is currently possible for the user to crop the photo in a way that does not output a square image. This is because the default zoom level when cropping landscape photos is aspectFit rather than aspectFill (as it is for portrait photos).

Is it possible to set the minimum zoom level for UIImagePickerController's edit mode? I suppose I could simply automatically crop the image if the output is not square, but I would rather that the edit mode of UIImagePickerController convey this to the user instead of doing it for him/her.

回答1:

It is not possible to adjust the behavior of the UIImagePickerController crop/edit feature in a supported manner. You could potentially dig into the UIImagePickerController controller/view hierarchy and try to figure out how it works, but that is not a very maintainable or pleasant thing to do.

Having said that, the UIImagePickerController is a subclass of UINavigationController, so there's nothing stopping you from implementing your own image editing view controller and pushing it onto the UIImagePickerController. This probably wouldn't be too hard, you could just throw the picked UIImage into a UIScrollView with a rectangular overlay showing the crop area, do some math, and crop the UIImage yourself. You would obviously have full control over the functionality in this case and I bet it would take less time to implement than spelunking into the guts of UIImagePickerController.

I would probably set it up whatever view controller presented the picker like this:

@interface MainViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate, ImageEditorViewControllerDelegate>
@end

@implementation MainViewController {
    UIImagePickerController* _imagePickerController;
}
#pragma mark IBAction
- (IBAction)pickImage:(id)sender {
    _imagePickerController = [[UIImagePickerController alloc] init];
    _imagePickerController.delegate = self;
    _imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    _imagePickerController.allowsEditing = NO;

    [self presentViewController:_imagePickerController animated:YES completion:nil];
}


#pragma mark UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    ImageEditorViewController* imageEditorViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"ImageEditor"];
    imageEditorViewController.delegate = self;
    imageEditorViewController.imageToEdit = info[UIImagePickerControllerOriginalImage];

    [_imagePickerController pushViewController:imageEditorViewController animated:YES];
}


- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [self dismissViewControllerAnimated:YES completion:^{
        _imagePickerController = nil;
    }];
}


#pragma mark ImageEditorViewControllerDelegate
- (void)imageEditorViewController:(ImageEditorViewController *)imageEditorViewController didFinishWithInfo:(NSDictionary *)info {
    // TODO: Handle the edited media

    [self dismissViewControllerAnimated:YES completion:^{
        _imagePickerController = nil;
    }];
}
@end

And then your editing view would have an interface like this (with an implementation specific to your needs):

@protocol ImageEditorViewControllerDelegate;

@interface ImageEditorViewController : UIViewController
@property(nonatomic, strong) UIImage* imageToEdit;

@property(nonatomic, weak) id <ImageEditorViewControllerDelegate> delegate;
@end

@protocol ImageEditorViewControllerDelegate
- (void)imageEditorViewController:(ImageEditorViewController*)imageEditorViewController didFinishWithInfo:(NSDictionary*)info;
@end