iOS CAlayer Orientation AVCaptureVideoPreviewLayer不会旋转

Jan*_*ski 6 calayer orientation-changes ios

在此输入图像描述 简介: 我无法强制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))];
Run Code Online (Sandbox Code Playgroud)

它在纵向模式下正确显示.当我尝试旋转设备时,预览图层表现得很奇怪.它似乎没有自己调整大小,并且它无法正确旋转.

我尝试通过添加以下方法来修复它

-(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");
}
Run Code Online (Sandbox Code Playgroud)

}

添加上述方法后,我可以看到进度.现在图层旋转正确反映当前设备方向,并且在横向模式下正确显示,但不在纵向模式下显示.

图层未正确定位,它不在屏幕中心(请参见屏幕截图).为了看看发生了什么,我添加了以下调试语句:

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);
Run Code Online (Sandbox Code Playgroud)

并获得以下输出:

2012-09-30 13:25:12.067 RotatePreviewLayer[2776:907] 1024.000000 768.000000 0.000000 0.000000 
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

注意调试输出的第二行.预览图层的帧移动128,-128.任何人都可以解释我为什么会发生这种情况以及如何解决预览图层的方向问题?谢谢你,Janusz

小智 9

那这个呢?

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    _videoPreviewLayer.connection.videoOrientation = toInterfaceOrientation;
}
Run Code Online (Sandbox Code Playgroud)


Sie*_*ult 6

这是我在视图控制器中使用的方法,用于维护捕获层的方向,使其始终正面朝上:

- (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;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

有点罗嗦,但即使任何枚举在将来发生变化,也是安全的.


Jan*_*ski 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]];
Run Code Online (Sandbox Code Playgroud)

然后我将rotateLayer方法的调用添加到didRotate

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
    [self rotateLayer];
}
Run Code Online (Sandbox Code Playgroud)

最后,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))];
}
Run Code Online (Sandbox Code Playgroud)

我仍然不明白为什么它以这种方式运作.如果有人能解释它会很棒.