6

ここに画像の説明を入力 概要: 向きの変化に CALayer を正しく応答させることはできません。cgaffinetransform を使用しようとするたびに、奇妙な結果が得られます (レイヤーが中央に配置されていません)。どんな助けでも大歓迎です!ありがとう、

プロセス AVCaptureVideoPreviewLayer サブクラスを使用してビデオのプレビューを追加しています。デバイスが縦向きの場合、すべてが正常に見えます。この問題は、デバイスを横向き (左または右) または縦向きに回転させたときに発生します。

AVCaptureVideoPreviewLayer サブクラスを使用してビデオのプレビューを追加しています。デバイスが縦向きの場合、すべてが正常に見えます。この問題は、デバイスを横向き (左または右) または縦向きに回転させたときに発生します。

次のコードを使用してプレビュー レイヤーを追加しています。

CGRect layerRect = [[[self view] layer] bounds];
[[[self captureManager] previewLayer] setBounds:layerRect];
[[[self captureManager] previewLayer]setFrame:CGRectMake(0, height, width, height)];
[[[self captureManager] previewLayer] setPosition:CGPointMake(CGRectGetMidX(layerRect),CGRectGetMidY(layerRect))];

そして、ポートレートモードでちゃんと表示されます。デバイスを回転させようとすると、プレビュー レイヤーの動作がおかしくなりました。それ自体のサイズが変更されないようで、正しく回転しません。

次のメソッドを追加して修正しようとしました

-(void)rotateLayer{
CALayer * stuckview = [[self captureManager] previewLayer];
CGRect layerRect = [[[self view] layer] bounds];

UIDeviceOrientation orientation =[[UIDevice currentDevice]orientation];

switch (orientation) {
    case UIDeviceOrientationLandscapeLeft:
        stuckview.affineTransform = CGAffineTransformMakeRotation(M_PI+ M_PI_2); // 270 degress
        NSLog(@"Landscape Left");
        [stuckview setPosition: CGPointMake(self.view.bounds.size.width /2.0, self.view.bounds.size.height /2.0)];

        break;
    case UIDeviceOrientationLandscapeRight:
        stuckview.affineTransform = CGAffineTransformMakeRotation(M_PI_2); // 90 degrees
        NSLog(@"Landscape Right");
        [stuckview setPosition: CGPointMake(self.view.bounds.size.width /2.0, self.view.bounds.size.height /2.0)];
        break;
    case UIDeviceOrientationPortraitUpsideDown:
        stuckview.affineTransform = CGAffineTransformMakeRotation(M_PI); // 180 degrees
        NSLog(@"Landscape Upside down");
        break;
    default:
        stuckview.affineTransform = CGAffineTransformMakeRotation(0.0);
        break;
}
 float h1 = stuckview.frame.size.height;
   float w1 = stuckview.frame.size.width;

if(UIDeviceOrientationIsPortrait(orientation))
{
  stuckview.position =CGPointMake(h1/2.0, w1/2.0);
    NSLog(@"Portrait");
}
else{
  stuckview.position =CGPointMake(w1/2.0, h1/2.0);
    NSLog(@"Portrait");
}

}

上記のメソッドを追加すると、進行状況がわかります。現在のデバイスの向きを反映してレイヤーが正しく回転し、横向きモードでは正しく表示されますが、縦向きモードでは表示されません。

レイヤーが正しく配置されておらず、画面の中央に配置されていません (スクリーンショットを見てください)。何が起こっているかを確認するために、次のデバッグ ステートメントを追加しました。

CALayer * stuckview = [[self captureManager] previewLayer];
CGRect layerRect = [[[self view] layer] bounds];
float h = stuckview.bounds.size.height;
float w = stuckview.bounds.size.width;

float x = stuckview.bounds.origin.x;
float y = stuckview.bounds.origin.y;

float h1 = stuckview.frame.size.height;
float w1 = stuckview.frame.size.width;

float x1 = stuckview.frame.origin.x;
float y1 = stuckview.frame.origin.y;

NSLog(@"%f %f %f %f ", h,w,x,y );
NSLog(@"%f %f %f %f ", h1,w1,x1,y1 );

NSLog(@"Anchor Point: %f  %f",stuckview.anchorPoint.x, stuckview.anchorPoint.y);
NSLog(@"Position: %f  %f",stuckview.position.x, stuckview.position.y);

CGAffineTransform at = stuckview.affineTransform;

NSLog(@"Affine Transform After : %f %f %f %f %f %f %f", at.a,at.b, at.c, at.d, at.tx,at.tx, at.ty);

そして、次の出力を取得します。

2012-09-30 13:25:12.067 RotatePreviewLayer[2776:907] 1024.000000 768.000000 0.000000 0.000000 

2012-09-30 RotatePreviewLayer[2776:907] 1024.000000 768.000000 128.000000 -128.000000

2012-09-30 13:25:12.070 RotatePreviewLayer[2776:907] Portrait
2012-09-30 13:25:12.072 RotatePreviewLayer[2776:907] Anchor Point: 0.500000  0.500000
2012-09-30 13:25:12.074 RotatePreviewLayer[2776:907] Position: 512.000000  384.000000
2012-09-30 13:25:12.076 RotatePreviewLayer[2776:907] Affine Transform after: -1.000000 0.000000 -0.000000 -1.000000 0.000000 0.000000 0.000000

デバッグ出力の 2 行目に注目してください。プレビューレイヤーの枠を128、-128移動させます。なぜこれが起こっているのか、プレビューレイヤーで向きの問題を修正する方法を誰かに説明できますか? ありがとう、ヤヌス

4

8 に答える 8

6

これは、View Controller でキャプチャ レイヤーの向きを維持するために使用する方法で、常に正しい向きになります。

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
    if (_previewLayer.connection.supportsVideoOrientation)
    {
    switch (toInterfaceOrientation)
        {
        case UIInterfaceOrientationPortrait:
            {
            _previewLayer.connection.videoOrientation = AVCaptureVideoOrientationPortrait;
            break;
            }
        case UIInterfaceOrientationPortraitUpsideDown:
            {
            _previewLayer.connection.videoOrientation = AVCaptureVideoOrientationPortraitUpsideDown;
            break;
            }
        case UIInterfaceOrientationLandscapeLeft:
            {
            _previewLayer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;
            break;
            }
        case UIInterfaceOrientationLandscapeRight:
            {
            _previewLayer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
            break;
            }
        }
    }

少し冗長ですが、いずれかの列挙が将来変更されても安全です。

于 2013-09-03T20:22:46.000 に答える
5

何が問題を引き起こしているのかまだわかりませんが、なんとか修正することができました。これが私がやった方法です:

viewDidLoad でレイヤーを追加しています:

CGRect layerRect = [[[self view] layer] bounds];
    [[[self captureManager] previewLayer] setBounds:layerRect];
    [[[self captureManager] previewLayer] setPosition:CGPointMake(CGRectGetMidX(layerRect),CGRectGetMidY(layerRect))];
    [[[self view] layer] addSublayer:[[self captureManager] previewLayer]];

次に、rotateLayer メソッドへの呼び出しを didRotate に追加しています。

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
    [self rotateLayer];
}

最後に、rotateLayer メソッドは次のようになります。

-(void)rotateLayer{
    CALayer * stuckview = [[self captureManager] previewLayer];
    CGRect layerRect = [[[self view] layer] bounds];

    UIDeviceOrientation orientation =[[UIDevice currentDevice]orientation];

    switch (orientation) {
        case UIDeviceOrientationLandscapeLeft:
            stuckview.affineTransform = CGAffineTransformMakeRotation(M_PI+ M_PI_2); // 270 degress

            break;
        case UIDeviceOrientationLandscapeRight:
            stuckview.affineTransform = CGAffineTransformMakeRotation(M_PI_2); // 90 degrees
            break;
        case UIDeviceOrientationPortraitUpsideDown:
            stuckview.affineTransform = CGAffineTransformMakeRotation(M_PI); // 180 degrees
            break;
        default:
            stuckview.affineTransform = CGAffineTransformMakeRotation(0.0);
            [stuckview setBounds:layerRect];
            break;
    }
    [stuckview setPosition:CGPointMake(CGRectGetMidX(layerRect),CGRectGetMidY(layerRect))];
}

なぜこのように機能するのか、私はまだ理解していません。誰かが説明できれば、それは素晴らしいことです。

于 2012-10-02T15:30:10.277 に答える
1

@Janusz Chudzynski ここでは、rotateLayerメソッドの詳細な説明を示します

このメソッドは、さまざまな方向が にどのように影響するかを調べた後に作成されます。そのpreviewLayerため、作成者は方向がオンになっていることを確認し、LandscapeLeft270 度回転して、使用した正しい位置に配置する必要があります。

stuckview.affineTransform = CGAffineTransformMakeRotation(M_PI+ M_PI_2);

     M_PI        3.14159265358979323846264338327950288   // pi     = 180 degree  
                                    +      
     M_PI_2      1.57079632679489661923132169163975144   // pi/2   = 90  degree

                                                         // Total  = 270 degree

previewLayerそのため、作成者は、私が270 度回転すると、可能なすべての回転でLandscapeLeft回転したのと同じように、正しい位置になることに気付きました。previewLayer

于 2013-08-09T06:53:27.493 に答える
0
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration  
{  
    previewLayer.orientation = toInterfaceOrientation;  
}
于 2012-10-04T11:13:28.850 に答える
0

willRotateToUserInterfaceOrientation を使用した回答は、そのメソッドが廃止されたことを除いて、正常に機能します。したがって、iOS 9 を使用できる場合は、Swift でそれを行う方法を次に示します。

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        let newOrientation = UIDevice.currentDevice().orientation
        switch newOrientation {
        case .LandscapeLeft:
            self.capturePreviewLayer?.connection.videoOrientation = .LandscapeLeft
        case .LandscapeRight:
            self.capturePreviewLayer?.connection.videoOrientation = .LandscapeRight
        case .Portrait, .Unknown, .FaceUp, .FaceDown:
            self.capturePreviewLayer?.connection.videoOrientation = .Portrait
        case .PortraitUpsideDown:
            self.capturePreviewLayer?.connection.videoOrientation = .PortraitUpsideDown
        }
        super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    }
于 2016-04-25T14:49:18.077 に答える
0

私は @Siegfault を使用していますが、ビューが最初に iPad で横向きに読み込まれたときに、向きがまだ正しいこともわかりました。viewDidAppear:修正するには、現在ので同じデリゲート メソッドを呼び出しますinterfaceOrientation

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self willRotateToInterfaceOrientation:self.interfaceOrientation duration:0.0];
}
于 2015-04-06T19:07:23.620 に答える