当前位置: 首页 > 知识库问答 >
问题:

如何在AVCaptureVideoPreviewLayer中处理自动旋转?

谷梁昊空
2023-03-14

我的应用程序支持所有方向,除了肖像向上向下。在我的视图层次结构中,我有一个AVCaptureVideoPreviewLayer作为俯视图中的一个子层,即UIImageView。然后,在视图层次结构的下方是几个显示控件的覆盖视图。

覆盖视图可以在方向改变的情况下正常工作,但我不知道如何使用这个AVCaptureVideoPreviewLayer。我希望它的行为像照相机应用程序一样,这样previewLayer就可以保持静止,并且可以顺利地重新组织控件。现在,由于主视图在方向改变时旋转,我的预览层也会旋转,这意味着在横向视图中,它保持在纵向视图中,仅拍摄部分屏幕,并且相机的图片也旋转了90度。我已经设法手动旋转预览层,但它有一个方向更改动画,这会导致在动画期间看到一段时间的背景。

那么,在使previewLayer保持静止的同时,自动旋转控件的正确方法是什么呢?

共有3个答案

田宇
2023-03-14

主要问题是当我收到通知时,状态栏还没有旋转,所以检查当前值实际上给出了旋转之前的值。所以我在调用检查状态栏方向并旋转我的子视图的方法之前添加了一点延迟(这里是2秒):

-(void) handleNotification:(NSNotification *) notification
{    
    (void) [NSTimer scheduledTimerWithTimeInterval:(2.0)
                                           target:self
                                          selector:@selector(orientationChanged)
                                          userInfo:nil
                                           repeats:NO ] ;
}

其余代码是BartoNaz的代码。

澹台俊材
2023-03-14

iOS8解决方案:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft) {
        self.layer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;
    } else {
        self.layer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
    }
}

在设置代码中:

self.layer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
self.layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft) {
    self.layer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;
} else {
    self.layer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
}
郝池暝
2023-03-14

在我的实现中,我为我想要旋转的视图子类化了UIView,并为这个视图子类化了类似viewController的东西,它只是NSObject的一个子类。

在此viewController中,我执行与方向更改相关的所有检查,决定是否应更改目标视图的方向,如果是,则调用视图的方法来更改其方向。

首先,我们需要将整个应用程序界面的方向固定为纵向模式,以便我们的AcceptureVideoPreviewLayer始终保持静止。这是在主视图控制器中完成的。h:

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation`
{
    return interfaceOrientation==UIInterfaceOrientationPortrait;
}

它返回NO的所有方向,肖像除外。

为了使我们的自定义viewController能够跟踪设备方向的变化,我们需要使其成为相应通知的观察者:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(orientationChanged) name:UIDeviceOrientationDidChangeNotification object:nil];

我将这些行放在viewController的awakeFromNib方法中。因此,每次更改设备方向时,都会调用viewController的方法“方向更改”。

其目的是检查设备的新方向是什么,设备的最后一个方向是什么,并决定是否更改。以下是实施:

if(UIInterfaceOrientationPortraitUpsideDown==[UIDevice currentDevice].orientation ||
    lastOrientation==(UIInterfaceOrientation)[UIDevice currentDevice].orientation) 
    return;
    [[UIApplication sharedApplication]setStatusBarOrientation:[UIDevice currentDevice].orientation animated:NO];

    lastOrientation=[UIApplication sharedApplication].statusBarOrientation;
    [resultView orientationChanged];

如果方向与之前相同或在肖像上下方向相同,则不执行任何操作。否则,它会将状态栏的方向设置为正确的方向,以便当有来电或骨化时,它会显示在屏幕的正确一侧。然后我还调用了目标视图中的方法,在该视图中,对新方向进行了所有相应的更改,如旋转、调整大小、移动此视图中与新方向相对应的界面的其他元素。

以下是目标视图中方向更改的实现:

Float32 angle=0.f;
UIInterfaceOrientation orientation=[UIApplication sharedApplication].statusBarOrientation;

switch (orientation) {
    case UIInterfaceOrientationLandscapeLeft: 
        angle=-90.f*M_PI/180.f;
        break;
    case UIInterfaceOrientationLandscapeRight: 
            angle=90.f*M_PI/180.f;
        break;
    default: angle=0.f;
        break;
}   
if(angle==0 && CGAffineTransformIsIdentity(self.transform)) return;

CGAffineTransform transform=CGAffineTransformMakeRotation(angle);

[UIView beginAnimations:@"rotateView" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:0.35f];

self.transform=transform;

[UIView commitAnimations];

当然,您可以在这里添加任何其他更改,如平移、缩放界面的不同视图,这些更改需要响应新的方向并设置动画。

此外,您可能不需要viewController来执行此操作,但只需在视图的类中执行所有操作。希望总体思路清晰。

此外,当您不需要方向更改时,不要忘记停止接收通知,如:

[[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
[[UIDevice currentDevice]endGeneratingDeviceOrientationNotifications];
 类似资料:
  • 在以前版本的swift中,您可以在ViewController中创建AVCaptureVideoPreviewLayer,并使用view将其添加到默认视图中。层添加子层(预览层)。 在SwiftUI ContentView中如何实现这一点?SwiftUI中的所有视图类型似乎都没有addSublayer。没有文本(“你好,世界”)。层添加子层。。。。 我尝试添加previewLayer到Conten

  • 使地球自动旋转,并控制旋转速率。地球的自动旋转功能在默认情况下是关闭的,如果启动旋转功能,默认的旋转速率是1。 // 启用自动旋转功能,将转速设置为1(同时1也是默认的转速) controller.setAutoRotation( true, 1 ); // 如果之前开启了自动旋转功能,可以用这种方式将其关闭 controller.setAutoRotation( false );

  • 但似乎什么都没起作用。

  • 我在做点什么,好像卡住了。我试图在处理过程中通过按钮添加文本,但是,一旦我使用translate方法,我的文本就会出现颠倒。我如何简单地旋转它,使其看起来正常?以下是我所拥有的:

  • 我目前正在测试将现有应用程序迁移到拼图模块。我的一个模块使用ElasticSearch及其Groovy插件。 org.elasticsearch:elasticsearch org.elasticsearch.module: lang-groovy 不幸的是,他们共享一个拆分包,所以给了我: X从lang.groovy和elasticsearch读取包org.elasticsearch.scrip

  • 我有很多图像,其中一些图像需要旋转。 样品: 我想逆时针旋转这个图像90°。 我谷歌了一下如何旋转图像,发现了许多链接和SO线程。但是我如何确定图像是否需要旋转?Picasa有一个自动旋转功能。我想有类似的功能。 任何指针都会对我很有帮助。 我找到了一个链接,但它与Android有关。