4

私は静的フレームワークをプログラムしました。その中に、AVCaptureSession でカメラを設定する ViewfinderViewController というクラスがあります。この ViewController は、AVCaptureVideoPreviewLayer を独自のビューのレイヤーにサブレイヤーとして追加します。

    // code in ViewfinderViewController.m
    previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:captureSession];
    previewLayer.frame = self.view.bounds;
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    [self.view.layer addSublayer:previewLayer];

ViewfinderViewController はまた、いくつかのビデオ処理を行い、処理されたフレームの 1 つに関心のあるものが見つかった場合、または見つからなかった場合に備えて、いくつかのデリゲート メソッドに登録するフレームワークのユーザーを提供します。

実際のアプリケーションの viewDidLoad メソッドで、ViewfinderViewController のインスタンスを作成し、そのフレームを設定して、そのビューをサブビューとして追加します。

    // code in the app's view controller viewDidLoad method
    ViewfinderViewController *vfVC = [[ViewfinderViewController alloc] init];
    vfVC.view.frame = self.view.bounds;
    [self.view addSubview:vfVC.view];

回転を無視する限り、これは問題なく機能します(これまでは行っていました)。私の主な問題は、 ViewfinderViewController.view がフレームのサイズを変更することですが、 AVCaptureVideoPreviewLayer はそうではありません。私は少し困惑しています: superLayer に対応するビューが正しくサイズ変更されるため、previewLayer も自動的にサイズ変更されるべきではありませんか?

何か案は?喜んでより多くの情報を提供しますが、質問を短くするために、今のところこれ以上説明しません。ありがとう。

4

1 に答える 1

9

最後に、次の方法が私のアプリに最適であることがわかりました。私のアプリケーションでは、ViewFinderViewController を子ビュー コントローラーとして追加します。

- (void)viewWillAppear:(BOOL)animated;
{
    if ([self.childViewControllers containsObject:self.viewfinderViewController] == NO) {
        [self addChildViewController:self.viewfinderViewController];
        self.viewfinderViewController.view.frame = self.view.bounds;
        [self.view addSubview:self.viewfinderViewController.view];
        [self.viewfinderViewController didMoveToParentViewController:self];
    }
}

このようにして、 willAnimateRotationToInterfaceOrientation: メソッドが自動的に呼び出されます。これは、ビューファインダーのビューをサブビューとして追加したビュー コントローラーから以前に転送したものです。

さらに、ViewfinderViewController のこのメソッドで previewLayer のサイズを更新します。

- (void)viewWillLayoutSubviews;
{
    self.previewLayer.frame = self.view.bounds;
}

次の 2 つのメソッドを実装して、previewLayer の回転を処理します。

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [CATransaction begin];
    [CATransaction setAnimationDuration:duration];
    [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    [self updatePreviewLayerForOrientation:toInterfaceOrientation];
    [CATransaction commit];
}

- (void)updatePreviewLayerForOrientation:(UIInterfaceOrientation)interfaceOrientation;
{
    // correct position of previewLayer
    CGSize newSize = self.view.bounds.size;
    self.previewLayer.position = CGPointMake(0.5 * newSize.width, 0.5 * newSize.height);

    // rotate the previewLayer, in order to have camera picture right
    switch (interfaceOrientation) {
        case UIInterfaceOrientationPortrait:
            [self.previewLayer setAffineTransform:CGAffineTransformMakeRotation(0)];
            break;

        case UIInterfaceOrientationLandscapeLeft:
            [self.previewLayer setAffineTransform:CGAffineTransformMakeRotation(M_PI/2)];
            break;

        case UIInterfaceOrientationLandscapeRight:
            [self.previewLayer setAffineTransform:CGAffineTransformMakeRotation(-M_PI/2)];
            break;

        case UIDeviceOrientationPortraitUpsideDown:
            [self.previewLayer setAffineTransform:CGAffineTransformMakeRotation(M_PI)];
            break;

        default:
            break;
    }
}

これが、サブレイヤーとして AVCaptureVideoPreviewLayer を追加しようとしていて、インターフェイスの回転に関してサイズ変更と向きに問題があるすべての人に役立つことを願っています。

于 2013-08-01T13:52:19.980 に答える