2014-12-18 13 views
6

Mam UIViewautoLayout i AVCaptureVideoPreviewLayer

@property (nonatomic, strong) IBOutlet UIView *previewView; 

previewView ostatecznie wyświetlić podgląd tego, co dzieje się w moim aparacie na moim iPhone przy użyciu następującej warstwę podglądu.

@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer; 

mam ograniczenia ustanowione na moim previewView w storyboardy i dlatego używam w następującej kwestii.

self.previewLayer.frame = self.previewView.bounds; // This doesn't work 
self.previewLayer.videoGravity = AVLayerVideoGravityResize; 
[self.previewView.layer addSublayer:self.previewLayer]; 

previewLayer zostanie dodany do previewView podwarstwy, ale nie wykazują w odpowiednich parametrach (szerokość i wysokość). Myślę, że jest to spowodowane użyciem ograniczeń w autolayout.

Jak mogę to naprawić?

Update: ja też próbowałem następujące:

self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspect; 
CALayer *rootLayer = [previewView layer]; 
rootLayer.frame = self.previewView.bounds; 
[rootLayer setMasksToBounds:YES]; 
[self.previewLayer setFrame:[rootLayer bounds]]; 
[rootLayer addSublayer:self.previewLayer]; 

I wydaje się, aby pokazać jak to: http://cl.ly/image/3T3o0O1E3U17

Pierwsze blisko, ale wciąż bardzo dużo off.

+0

Mam podobny problem. Moje zdjęcie z kamery wygląda bardzo podobnie do twojego, tzn. Po prawej stronie jest duży pusty pasek. Do tej pory doszedłem do wniosku, że problem ten występuje tylko dla mnie podczas korzystania z Auto-układu. – robert

Odpowiedz

10

OK, rozwiązałem to.

Problemem jest to, że podczas korzystania autoLayout, ramy/granice subviews swoich UIViewController „s można zmienić po skonfigurowaniu swojej previewLayer bez previewLayer jest sama odpowiednio na bieżąco! Dzieje się tak dlatego, że układ CALayer s jest kontrolowany wyłącznie przez własny kod (patrz także ta odpowiednia odpowiedź: https://stackoverflow.com/a/27735617/623685).

Aby rozwiązać ten problem, trzeba zastąpić metodę swojego UIViewControllerviewDidLayoutSubviews zaktualizować „stanowiska i granic (i prawdopodobnie innych) za każdym razem subviews” The previewLayer zmiany układu.


Poniżej opiszę w jaki sposób rozwiązać go w szczegółach:

Moja sprawa była rzeczywiście nieco bardziej skomplikowana, ponieważ używam ramy OpenCV iOS 2.4.9. Tutaj warstwa podglądu jest tworzona i zarządzana przez klasę OpenCV o nazwie CvVideoCamera. Dlatego musiałem utworzyć podklasę CvVideoCamera, do którego dodaje się następującą metodę:

- (void)updatePreviewLayer 
{ 
    self.customPreviewLayer.bounds = CGRectMake(0, 0, self.parentView.frame.size.width, self.parentView.frame.size.height); 
    [self layoutPreviewLayer]; 
} 

Objaśnienie: parentView jest UIView można przejść do CvVideoCamera w celu określenia, gdzie warstwa podgląd powinien być umieszczony i jak duże to powinno być. customPreviewLayer to warstwa podglądu zarządzana przez CvVideoCamera. I layoutPreviewLayer jest to metoda, która w zasadzie aktualizuje położenie warstwy za: https://github.com/Itseez/opencv/blob/2.4/modules/highgui/src/cap_ios_video_camera.mm#L211

Potem po prostu o nazwie tej metody z mojego UIViewController tak:

- (void)viewDidLayoutSubviews 
{ 
    NSLog(@"viewDidLayoutSubviews"); 
    [super viewDidLayoutSubviews]; 
    [self.myCameraView updatePreviewLayer]; 
} 
+0

działało idealnie :) –

1

Główną ideą jest taki sam - przy użyciu Autolayout, ramka Warstwa podglądu musi zostać ustawiona po zastosowaniu wszystkich ograniczeń widoku.Do tego celu używana jest metoda viewDidLayoutSubviews - taka sama jak w oryginalnej odpowiedzi, ale bez komplikacji związanych z używaniem innych frameworków niż Apple AVFoundation.

Poniższy kod jest oparty na próbce Apple (AVCam-iOS: Using AVFoundation to Capture Images and Movies). Ale kod został zmodyfikowany w celu użycia metody updateViewConstraints do programowego ustawiania wszystkich ograniczeń zamiast podejścia do scenorysu zastosowanego w próbce. Odpowiednie fragmenty pokazano poniżej:

@interface QRScannerViewController() 

@property (nonatomic) UIView *previewView; 

@end 

@implementation QRScannerViewController 
{ 
    AVCaptureSession *_captureSession; 
    AVCaptureVideoPreviewLayer *_captureVideoPreviewLayer; 
    dispatch_queue_t _sessionQueue; 
} 

#pragma mark - Lifecycle 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    [self.view addSubview:self.previewView]; 

    _captureSession = [AVCaptureSession new]; 
    _captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_captureSession]; 
    _captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; 

    _sessionQueue = dispatch_queue_create("av_session_queue", DISPATCH_QUEUE_SERIAL); 

    [self.view setNeedsUpdateConstraints]; 

    dispatch_async(_sessionQueue, ^{ 
     [self configureCaptureSession]; 
    }); 

    [self.previewView.layer addSublayer:_captureVideoPreviewLayer]; 
} 

- (void)viewDidAppear:(BOOL)animated 
{ 
    [super viewDidAppear:animated]; 

    if (_isCaptureDeviceConfigured) { 
     [_captureSession startRunning]; 
    } 
} 

- (void)viewDidLayoutSubviews 
{ 
    _captureVideoPreviewLayer.frame = self.previewView.bounds; 
} 

#pragma mark - getters/initializers 

- (UIView *)previewView 
{ 
    if (_previewView) { 
     return _previewView; 
    } 
    _previewView = [UIView new]; 
    _previewView.backgroundColor = [UIColor blackColor]; 
    _previewView.translatesAutoresizingMaskIntoConstraints = NO; 

    return _previewView; 
} 

- (void)configureCaptureSession 
{ 
    [_captureSession beginConfiguration]; 

    // Code omitted, only relevant to the preview layer is included. See the Apple's sample for full code. 
    ... 
    _captureVideoPreviewLayer.connection.videoOrientation = initialVideoOrientation; 
    ... 
} 

#pragma mark - Autolayout 

- (void)updateViewConstraints 
{ 
    [self.previewView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor constant:0.0].active = YES; 
    [self.previewView.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor constant:-40.0].active = YES; 
    [self.previewView.widthAnchor constraintEqualToConstant:300].active = YES; 
    [self.previewView.heightAnchor constraintEqualToAnchor:self.previewView.widthAnchor constant:0.0].active = YES; 

    [super updateViewConstraints]; 
} 
Powiązane problemy