7

Since the iOS7 upgrade, I have a weird behaviour of the UIImagePickerController. In this application I am using the UIImagePickerController with a cameraOverlayView.

In iOS6 I called the UIImagePickerController using the following code:

_picker = [[UIImagePickerController alloc] init];

if ([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear]) {
    _picker.sourceType = UIImagePickerControllerSourceTypeCamera;
    _picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
    _picker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
    _picker.showsCameraControls = NO;
    _picker.navigationBarHidden = NO;
    _picker.toolbarHidden = YES;
    _picker.wantsFullScreenLayout = YES;

    _overlayViewController = [[OverlayViewController alloc] init];
    _overlayViewController.picker = _picker;
    _overlayViewController.frameSize = self.frameSize;
    _overlayViewController.delegate = self;
    _picker.cameraOverlayView = _overlayViewController.view;
}
else {
    _picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

}
_picker.delegate = self;

Where the OverlayViewController is an UIViewController, with a transparent background which draws some custom controls on screen.

enter image description here

But now in iOS 7 the camera is drawn through the statusbar and a black bar appears beneath the live camera view.

I can solve this by applying a CGAffineTransformMakeTranslation to the cameraViewTransform property of the UIImagePickerController, but why is this like this?

Wim Haanstra
  • 5,918
  • 5
  • 41
  • 57

3 Answers3

1

In iOS 7, by default UIViewController views take up the entire screen area including the status bar.

wantsFullScreenLayout

is deprecated and ignored. In some cases, this fix works (in the view controller class):

if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) {
    [self setEdgesForExtendedLayout:UIRectEdgeNone];
}

In other cases, it's a bit more complicated. It's late here, so see how you go with it. Helpful things to note - in a UIViewController, the following code will give the correct statusbar height on both iOS 6 and iOS 7, should it come to having to align things using CGRect math:

if (UIDeviceOrientationIsLandscape(self.interfaceOrientation)) {
            statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.width;
        } else {
            statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
        }

And then don't forget that in Interface Builder, there are the new "iOS 6 delta" adjustments that allow you to design for iOS 7 and then use offsets to correct for iOS 6.

Anyhow, let me know how you go.

iosengineer
  • 186
  • 5
0

My understanding of the issue, based on a few other SO threads and such, is that UIImagePickerController does not do what we'd expect in terms of managing the status bar via [UIViewController -prefersStatusBarHidden].

This means you either have to disable view controller status bar management entirely, via plist, or figure out a way to get UIImagePickerController to do what we want. On the assumption that you're not looking for the former, I can say I've had success in the latter by putting the picker in a wrapper controller that does what I want (but fall back to your previous code if you still need to detect/support iOS6):

@interface PickerContainer : UIViewController

@property ( nonatomic, weak ) UIImagePickerController* picker;

@end

@implementation PickerContainer

- (void) setPicker: (UIImagePickerController*) picker
{
    [self addChildViewController: picker];
    [picker didMoveToParentViewController: self];

    self->_picker = picker;
}

- (void) viewDidLoad
{
    [super viewDidLoad];

    self.picker.view.frame = self.view.bounds;
    [self.view addSubview: self.picker.view];
}

// Will have no effect in ios6 -- see [-init] for that option
- (BOOL) prefersStatusBarHidden { return YES; }

- (id) init
{
    if ( ! ( self = [super init] ) ) return nil;

    if ( detectThatThisIsIos6() ) self.wantsFullScreenLayout = YES;

    return self;
}

@end

jgoldbg
  • 53
  • 7
0

This will work for you, scaled camera, you will have a black bar at the bottom but it will get overlayed by tool bar https://stackoverflow.com/a/15803947

Community
  • 1
  • 1