web-dev-qa-db-de.com

Wie kann das benutzerdefinierte Overlay der UIImagePicker-Kamera in iOS 7 als Vollbild angezeigt werden?

Ich bin daran interessiert, ein benutzerdefiniertes Overlay für UIImagePickerController für Kamerasteuerungen zu verwenden, die den gesamten Bildschirm einnehmen, sehr ähnlich wie die Standard-Kamera-App, wenn auf die Videofunktion umgestellt wird. 

Ich habe hier auf SO zu diesem Thema einige Fragen verwiesen, insbesondere auf dieses one , sowie auf das Apple-Beispiel , wie ein benutzerdefiniertes Overlay für den UIImagePickerController verwendet wird, aber keine davon hat konnte mit iOS 7 ein erfolgreiches Vollbild-Ergebnis erzielen.

Bisher sieht die Kamera-Benutzeroberfläche mit der benutzerdefinierten Überlagerung (ohne Schaltflächen) aus:

enter image description here

Beachten Sie, dass sich unten im Bildschirm ein schwarzer Balken befindet. Ich habe bemerkt, dass ich könnte den schwarzen Balken entfernen lassen, wenn ich cameraAspectRatio in 1 ändere, aber dies verzerrt den Kamerazoom, da er sehr stark vergrößert wird. Gibt es eine Möglichkeit, den gesamten Bildschirm zu haben, ohne den Zoom zu stark zu verzerren (ich verstehe, dass ein kleines bisschen erforderlich ist) und auch den schwarzen Balken entfernen? 

Hier ist mein Code, der die benutzerdefinierte Überlagerung konfiguriert:

{
        self.imagePickerController.showsCameraControls = NO;

        [[NSBundle mainBundle] loadNibNamed:@"overlayView" owner:self options:nil];
        self.overlayView.frame = self.imagePickerController.cameraOverlayView.frame;
        self.imagePickerController.cameraOverlayView = self.overlayView;
        self.overlayView = nil;

        // Device's screen size (ignoring rotation intentionally):
        CGSize screenSize = [[UIScreen mainScreen] bounds].size;


        float cameraAspectRatio = 4.0 / 3.0; //! Note: 4.0 and 4.0 works
        float imageWidth = floorf(screenSize.width * cameraAspectRatio);
        float scale = ceilf((screenSize.height / imageWidth) * 10.0) / 10.0;

        self.imagePickerController.cameraViewTransform = CGAffineTransformMakeScale(scale, scale);

    }

Update:

Ein weiteres Problem, das mir aufgefallen ist, ist, dass das in der Kamera-Vorschau angezeigte Bild immer kleiner ist und weniger Details enthält als das Bild, das bei der Methode [self.imagePickerController takePicture] gespeichert wird. Um zu zeigen:

So sieht die Tastatur in der Kameravorschau mit der schwarzen Leiste unten aus (leider etwas wackelig):

enter image description here

Beachten Sie jedoch, dass das tatsächlich aufgenommene Bild im Vorschaubereich sehr viel mehr Details aufweist, wie hier gezeigt, insbesondere nach oben sowie links und rechts.

enter image description here

Meine Frage ist, wie könnte ich meine Kameravorschau so einstellen, dass das, was der Benutzer in der Vorschau sieht, genau das Bild ist, das er einlesen wird, und dass ihm danach angezeigt werden könnte? Vielen Dank!

Update 2

Hier ist der gesamte Code in viewDidLoad, mit dem die Kamerasteuerung eingerichtet wird.

- (void)viewDidLoad
{
    [super viewDidLoad];

    //Appearance configuration
    self.navigationItem.hidesBackButton = YES;

    //UIImagePickerController initialization and setup
    self.imagePickerController = [[UIImagePickerController alloc] init];
    self.imagePickerController.delegate = self;
    self.imagePickerController.allowsEditing = NO;
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
        self.imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera; //if there is a camera avaliable
    } else {
        self.imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;//otherwise go to the folder
    }
    self.imagePickerController.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeImage, nil];
    if (self.imagePickerController.sourceType == UIImagePickerControllerSourceTypeCamera)
    {
        self.imagePickerController.showsCameraControls = NO;

        [[NSBundle mainBundle] loadNibNamed:@"overlayView" owner:self options:nil];
        self.overlayView.frame = self.imagePickerController.cameraOverlayView.frame;
        self.imagePickerController.cameraOverlayView = self.overlayView;
        self.overlayView = nil;

        // Device's screen size (ignoring rotation intentionally):
        CGSize screenSize = [[UIScreen mainScreen] bounds].size;

        int heightOffset = 0;

        if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
        {
            heightOffset = 120; //whole screen :)
        }

        float cameraAspectRatio = 4.0 / 3.0; //! Note: 4.0 and 4.0 works
        float imageWidth = floorf(screenSize.width * cameraAspectRatio);
        float scale = ceilf(((screenSize.height + heightOffset) / imageWidth) * 10.0) / 10.0;

        self.imagePickerController.cameraViewTransform = CGAffineTransformMakeScale(scale, scale);

    }
}

Und in viewWillAppear rufe ich die Bildauswahlansicht auf:

BOOL modalPresent = (BOOL)(self.presentedViewController);
    //Present the Camera UIImagePicker if no image is taken
    if (!appDelegate.imageStorageDictionary[@"picture1"]){
        if (modalPresent == NO){ //checks if the UIImagePickerController is modally active
            [self presentViewController:self.imagePickerController animated:NO completion:nil];
        }
    }
13
daspianist

Nach vielen Versuchen funktionierte dies für mich mit vielen Dank an den Vorschlägen anderer. Die folgenden Fakten waren sehr hilfreich zu wissen und zu beachten:

Die Auflösung von points der Kamera beträgt 426 * 320 . Damit die Höhe der Kameravorschau auf die Bildschirmhöhe von 568 des Telefons gedehnt werden kann, muss sie bei Verwendung von CGAffineTransformScale mit dem Faktor 1,333 multipliziert werden.

Beachten Sie, dass die unten aufgeführten Zahlen mit verschiedenen Zahlen auf Basis der Bildschirmauflösung des iPhone 5 in Punkten fest codiert sind. Sie können durch Verwendung solcher Objekte wie screen.height, screen.width und anderen Variablen verbessert werden, um sie auch für iPhone 4/4s-Dimensionen zu verwenden.

    self.imagePickerController.showsCameraControls = NO;

    [[NSBundle mainBundle] loadNibNamed:@"overlayView" owner:self options:nil];
    self.overlayView.frame = self.imagePickerController.cameraOverlayView.frame;
    self.imagePickerController.cameraOverlayView = self.overlayView;
    self.overlayView = nil;

    //For iphone 5+
    //Camera is 426 * 320. Screen height is 568.  Multiply by 1.333 in 5 inch to fill vertical
    CGAffineTransform translate = CGAffineTransformMakeTranslation(0.0, 71.0); //This slots the preview exactly in the middle of the screen by moving it down 71 points
    self.imagePickerController.cameraViewTransform = translate;

    CGAffineTransform scale = CGAffineTransformScale(translate, 1.333333, 1.333333);
    self.imagePickerController.cameraViewTransform = scale;
26
daspianist

In Swift

var picker: UIImagePickerController = UIImagePickerController();

picker.sourceType = UIImagePickerControllerSourceType.Camera;

picker.showsCameraControls = false;

var screenBounds: CGSize = UIScreen.mainScreen().bounds.size;

var scale = screenBounds.height / screenBounds.width;

picker.cameraViewTransform = CGAffineTransformScale(picker.cameraViewTransform, scale, scale);

9
Vikramaditya

Stellen Sie sicher, dass Sie die 20px-Statusleistenänderung in iOS7 berücksichtigen. Wenn Sie am unteren Rand des Bildschirms einen schwarzen Bildschirm mit 20 Pixeln sehen, ist dies Ihr Problem. Sie können anhand eines dieser Präprozessoren überprüfen, ob die App in ios7 ausgeführt wird oder nicht 

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

Und Sie können folgende Änderungen an Ihrem Code vornehmen und sehen, ob er funktioniert

{
        self.imagePickerController.showsCameraControls = NO;

        [[NSBundle mainBundle] loadNibNamed:@"overlayView" owner:self options:nil];
        self.overlayView.frame = self.imagePickerController.cameraOverlayView.frame;
        self.imagePickerController.cameraOverlayView = self.overlayView;
        self.overlayView = nil;

        // Device's screen size (ignoring rotation intentionally):
        CGSize screenSize = [[UIScreen mainScreen] bounds].size;

        int heightOffset = 0;

        if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
        {
            heightOffset = 20;
        }

        float cameraAspectRatio = 4.0 / 3.0; //! Note: 4.0 and 4.0 works
        float imageWidth = floorf(screenSize.width * cameraAspectRatio);
        float scale = ceilf(((screenSize.height + heightOffset) / imageWidth) * 10.0) / 10.0;

        self.imagePickerController.cameraViewTransform = CGAffineTransformMakeScale(scale, scale);

    }

Bitte lassen Sie mich wissen, ob es funktioniert. Ich habe es nicht zum Testen codiert.

2
Kamran Khan

Es gibt eine einfachere Methode, um Ihren Overlay-Vollbildschirm zumindest unter iOS 9 testen zu lassen.

let view    = ... your overlayView
let bounds  = UIScreen.mainScreen().bounds
view.center = CGPoint(x: bounds.midX, y: bounds.midY)
view.bounds = bounds
self.imagePicker.cameraOverlayView = view
1
Nicolas Manzini

Da sich das Bildschirm-Seitenverhältnis von dem 4/3-Verhältnis der Kamera selbst unterscheidet, müssen Sie (wie Sie bereits erwähnt haben) die Ränder leicht beschneiden, damit das Bild nach unten reicht.

Dazu muss die Breite so breit sein, dass die Höhe den gesamten Bildschirm annehmen kann. Ihre Bildbreite und -höhe muss also folgendermaßen sein:

float cameraAspectRatio = 4.0 / 3.0; //! Note: 4.0 and 4.0 works
float imageWidth = screenSize.height / cameraAspectRatio;

Wahrscheinlich möchten Sie auch, dass die Ansicht des Kamerabildes die Breite hat, die sich von beiden Seiten des Bildschirms erstreckt.

Verwenden Sie diesen Code, um das resultierende Bild in der benutzerdefinierten Größe zu erhalten. Ich habe das Ergebnis mit einer benutzerdefinierten Methode erhalten, um das resultierende Bild als benutzerdefinierte Größe zu erhalten.

Erstellen Sie zuerst IBOutlet für UIImageview.

-(void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    NSString *mediaType = info[UIImagePickerControllerMediaType];
[self dismissViewControllerAnimated:YES completion:nil];


if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
    OriginalImage=info[UIImagePickerControllerOriginalImage];
    image = info[UIImagePickerControllerOriginalImage];
//----------------------------------------
     imageview.image = image; //------------- additional method for custom image size
     self resizeImage];


//-----------------------------------------
        if (_newMedia)
            UIImageWriteToSavedPhotosAlbum(image,self,@selector(image:finishedSavingWithError:contextInfo:),nil);

}
else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie])
{
    // Code here to support video if enabled
}

}

// ---- Ändern Sie die Größe des Originalbildes mithilfe einer benutzerdefinierten Methode. ----------------------

-(void)resizeImage
{
    UIImage *resizeImage = imageview.image;

    float width = 320;
    float height = 320;

    CGSize newSize = CGSizeMake(320,320);
    UIGraphicsBeginImageContextWithOptions(newSize,NO,0.0);
    CGRect rect = CGRectMake(0, 0, width, height);

    float widthRatio = resizeImage.size.width / width;
    float heightRatio = resizeImage.size.height / height;
    float divisor = widthRatio > heightRatio ? widthRatio : heightRatio;

    width = resizeImage.size.width / divisor;
    height = resizeImage.size.height / divisor;

    rect.size.width  = width;
    rect.size.height = height;

    //indent in case of width or height difference
    float offset = (width - height) / 2;
    if (offset > 0) {
        rect.Origin.y = offset;
    }
    else {
        rect.Origin.x = -offset;
    }

    [resizeImage drawInRect: rect];

    UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

imageview.image = smallImage;
imageview.contentMode = UIViewContentModeScaleAspectFit;

}
0
svmrajesh

Versuchen Sie diesen Code, es funktioniert gut für mich

UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;
cameraUI.showsCameraControls = NO;

CGSize screenSize = [[UIScreen mainScreen] bounds].size;
float cameraAspectRatio = 4.0 / 3.0;
float imageHeight = floorf(screenSize.width * cameraAspectRatio);
float scale = screenSize.height / imageHeight;
float trans = (screenSize.height - imageHeight)/2;
CGAffineTransform translate = CGAffineTransformMakeTranslation(0.0, trans);
CGAffineTransform final = CGAffineTransformScale(translate, scale, scale);
cameraUI.cameraViewTransform = final
;
cameraUI.delegate = self;
[self presentViewController:cameraUI animated:YES completion:nil];

Bei diesem Code wird davon ausgegangen, dass der Aspekt des ursprünglichen Kameravorschaubereichs 4: 3 ist.

0
wzienrgo

Ich weiß nicht, warum Sie die Bildschirmgröße verwenden. Probieren Sie einfach diesen einfachen Code aus:

if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera])

{

     UIImagePickerController *controller = [[UIImagePickerController alloc] init];
     controller.sourceType = UIImagePickerControllerSourceTypeCamera;
     controller.allowsEditing = NO;
     controller.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:
     UIImagePickerControllerSourceTypeCamera];
     controller.delegate = self;
     [self presentViewController:controller animated:NO completion:^{}];
}
0
Naeem Paracha

Um ein ähnliches Problem zu lösen, habe ich einen ViewController vom Storyboard aus instanziiert und die Ansicht des Controllers als Kamera-Overlay verwendet. Ich weiß nicht, ob es das ist, wonach Sie suchen.

UIImagePickerController *globalPicker = [[UIImagePickerController alloc] init];
globalPicker.delegate = self;
globalPicker.sourceType = UIImagePickerControllerSourceTypeCamera;controller=[self.storyboard instantiateViewControllerWithIdentifier:@"myVC"];
overlayView = controller.view;
UIView *cameraView=[[UIView alloc] initWithFrame:self.view.bounds];
[cameraView addSubview:overlayView];
[globalPicker setCameraOverlayView:cameraView];
0
Nico.S