Jak uzyskać niestandardową nakładkę na kamerę UIImagePicker, aby była pełnoekranowa w systemie iOS 7?

Jestem zainteresowany użyciem niestandardowej Nakładki na UIImagePickerController do sterowania kamerą, które zajmują cały ekran, bardzo podobne do tego, co robi domyślna aplikacja aparatu po włączeniu funkcji wideo.

Odniosłem się do kilku pytań na ten temat, szczególnie tego jednego , a także przykład Apple Jak używać niestandardowej nakładki dla UIImagePickerController, ale żadne z nich nie były w stanie stworzyć udanego, pełnoekranowego wyniku z iOS 7.

Jak na razie tak wygląda interfejs aparatu z niestandardową nakładką (bez żadnych przycisków):

Tutaj wpisz opis obrazka

Zauważ, że na dole ekranu znajduje się czarny pasek. Zauważyłem, że mogę usunąć czarny pasek, jeśli zmienię cameraAspectRatio na 1, ale to zniekształca zoom aparatu, ponieważ wtedy ma bardzo powiększony widok. Czy jest sposób, aby mieć Pełny ekran bez zbytniego zniekształcania zoomu (rozumiem, że potrzebny jest mały bit), a także usunąć czarny pasek?

Oto Mój kod, który konfiguruje niestandardową nakładkę:

{
        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:

Dodatkowy problem, który zauważyłem jest, obraz, który jest wyświetlany w podglądzie aparatu jest zawsze mniejszy i ma mniej szczegółów niż zdjęcie, które jest zapisywane podczas metody [self.imagePickerController takePicture]. Do zilustrowania:

Tak wygląda klawiatura w podglądzie kamery z czarnym paskiem poniżej (przepraszam, że trochę chwiejna):

Tutaj wpisz opis obrazka

Jednak uwaga że rzeczywisty przechwycony obraz w panelu podglądu ma o wiele więcej szczegółów, jak pokazano tutaj, zwłaszcza w kierunku góry, a także po lewej i prawej stronie.

Tutaj wpisz opis obrazka

Moje pytanie brzmi, w jaki sposób można ustawić podgląd kamery tak, aby to, co użytkownik widzi w podglądzie, było dokładnie tym obrazem, który zostanie uchwycony i może zostać mu później pokazany? Dzięki!

Update 2

Oto cały kod w viewDidLoad, który ustawia sterowanie kamerą.

- (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);

    }
}

I w viewWillAppear, nazywam obraz picker view:

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];
        }
    }
Author: Community, 2013-12-26

9 answers

Po wielu próbach, to jest to, co zadziałało dla mnie z podziękowaniem za sugestie innych ludzi. Następujące fakty były bardzo pomocne, aby wiedzieć i pamiętać:

Rozdzielczość kamery jest 426 * 320. Aby wysokość podglądu kamery została rozciągnięta do wysokości ekranu telefonu 568, należy ją pomnożyć przez współczynnik 1,3333 przy użyciu CGAffineTransformScale.

Zauważ, że poniższe są mocno kodowane różnymi numerami w oparciu o iPhone 5 rozdzielczość ekranu w punktach. Można je ulepszyć za pomocą takich obiektów, jak ekran.wysokość, ekran.szerokość i inne zmienne, aby miało zastosowanie również do wymiarów iPhone 4 / 4s.

    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
Author: daspianist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-09 03:10:36

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);
 8
Author: Vikramaditya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-15 12:58:40

Upewnij się, że konto 20px pasek stanu zmiany w iOS7. Jeśli masz do czynienia z czarnym ekranem 20px u dołu ekranu, to będzie to twój problem. Możesz sprawdzić, czy aplikacja działa w systemie ios7, czy nie przez jeden z tych preprocesorów

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

I możesz wprowadzić następujące zmiany w kodzie i sprawdzić, czy działa

{
        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);

    }
Daj mi znać, jeśli to zadziała. Nie zakodowałem go do testów.
 2
Author: Kamran Khan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-13 06:16:24

Ponieważ proporcje ekranu różnią się od proporcji 4/3 samej kamery, musisz (jak wspomniałeś) lekko przyciąć krawędzie, aby obraz rozciągnął się na dół.

Aby to zrobić, musisz mieć szerokość wystarczająco szeroką, aby wysokość mogła być pełnym ekranem. Tak więc szerokość i wysokość obrazu musi wynosić:

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

Prawdopodobnie będziesz również chciał, aby widok przedstawiający obraz z kamery miał taką szerokość, która rozciąga się po obu stronach ekran.

 1
Author: Kendall Helmstetter Gelner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-06 05:27:27

[1]} istnieje sposób łatwiejsze, aby uzyskać nakładkę na Pełny ekran przynajmniej Przetestowane w iOS 9.

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
Author: Nicolas Manzini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-04 15:16:13

Nie wiem, dlaczego używasz rozmiaru ekranu. Po prostu spróbuj tego prostego kodu:

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
Author: Naeem Paracha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-06 09:41:27

Wypróbuj ten kod, aby utrzymać wynikowy obraz w niestandardowym rozmiarze. Otrzymałem wynik za pomocą niestandardowej metody uzyskiwania wynikowego obrazu jako niestandardowego rozmiaru.

Najpierw Utwórz IBOutlet dla 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
}

}

//---- Zmień rozmiar oryginalnego obrazu za pomocą niestandardowej metody----------------------

-(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
Author: svmrajesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-09 06:39:09

Aby rozwiązać podobny problem, utworzyłem instancję kontrolera ViewController ze storyboard i użyłem widoku kontrolera jako nakładki kamery. Nie wiem, czy to jest to, czego szukasz, ale użyłem następującego kodu:

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
Author: Nico.S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-24 16:54:12

Spróbuj tego kodu, to działa dobrze dla mnie

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];

Ten kod zakłada, że proporcja oryginalnego obszaru podglądu kamery wynosi 4: 3.

 0
Author: wzienrgo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-14 04:21:30