UIImagePickerController shows black bar when zoomi

2019-05-23 15:12发布

Edit: It has been suggested this post is a duplicate, which is not the case as the black bars are not initially present an an affine transformation does not remedy the problem.

I run this on an iPad Air 2 and target iOS 8. I have a UIImagePickerController whose showsCameraControls property is set to NO. When starting the app in landscape and then zooming in, this is what happens (all images are non-cropped):

enter image description here

A black bar appears and can be gotten rid of by changing device orientation to portrait (which will also show the black bar) and then changing it back.

After change to portrait:

enter image description here

Back to landscape (+ zooming in):

enter image description here

Strangely, after returning to landscape, the zoom slider is not visible anymore during zooming. When starting from portrait initially, zooming first works until one changes to landscape, where a black bar appears, which stays when going back to portrait.

None of this happens when setting showsCameraControls to YES. How can I get rid of this issue?

UPDATE: Apple claims to have fixed this in iOS 9.

1条回答
做自己的国王
2楼-- · 2019-05-23 15:35

I have found one way to work around what I for lack of better understanding would label a bug (as it happens with apple-provided samples as well).

The solution for me is to do manual zooming, by adding a UIPinchGestureRecognizer to the overlay view. The Controller must then implement a zooming callback which will get rid of the phenomenon described above.

@implementation CameraViewController
{
    CGFloat _lastScale; //< the current zoom scale before update
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.imagePicker = [[UIImagePickerController alloc] init];
    self.imagePicker.delegate = self;
    self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
    self.imagePicker.allowsEditing = NO;
    self.imagePicker.showsCameraControls = NO;

    [[NSBundle mainBundle] loadNibNamed:@"CameraOverlay" owner:self options:nil];

    UIPinchGestureRecognizer *pinchRec = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(zoom:)];
    [self.overlayView addGestureRecognizer:pinchRec];

    self.imagePicker.cameraOverlayView = self.overlayView;  
    _lastScale = 1.;
}

- (void)zoom:(UIPinchGestureRecognizer *) sender
{
    // reset scale when pinch has ended so that future scalings are applied cumulatively and the zoom does not jump back (not sure I understand this)
    if([sender state] == UIGestureRecognizerStateEnded)
    {
        _lastScale = 1.0;
        return;
    }

    CGFloat scale = 1.0 - (_lastScale - sender.scale); // sender.scale gives current distance of fingers compared to initial distance. We want a value to scale the current transform with, so diff between previous scale and new scale is what must be used to stretch the current transform


    CGAffineTransform currentTransform = self.imagePicker.cameraViewTransform;
    CGAffineTransform newTransform = CGAffineTransformScale (currentTransform, scale, scale); // stretch current transform by amount given by sender

    newTransform.a = MAX(newTransform.a, 1.); // it should be impossible to make preview smaller than screen (or initial size)
    newTransform.d = MAX(newTransform.d, 1.);

    self.imagePicker.cameraViewTransform = newTransform;
    _lastScale = sender.scale;

}
@end
查看更多
登录 后发表回答