nar*_*ner 11 objective-c uiinterfaceorientation ios avcapturesession viewdidlayoutsubviews
我已经实现了下面的代码来改变AVCaptureVideoSession基于以下内容的方向UIInterfaceOrientation:
- (AVCaptureVideoOrientation)interfaceOrientationToVideoOrientation:(UIInterfaceOrientation)orientation {
switch (orientation) {
case UIInterfaceOrientationPortrait:
return AVCaptureVideoOrientationPortrait;
case UIInterfaceOrientationPortraitUpsideDown:
return AVCaptureVideoOrientationPortraitUpsideDown;
case UIInterfaceOrientationLandscapeLeft:
return AVCaptureVideoOrientationLandscapeLeft;
case UIInterfaceOrientationLandscapeRight:
return AVCaptureVideoOrientationLandscapeRight;
default:
break;
}
NSLog(@"Warning - Didn't recognise interface orientation (%ld)",(long)orientation);
return AVCaptureVideoOrientationPortrait;
}
Run Code Online (Sandbox Code Playgroud)
这段代码几乎完美无缺.但是,出现的一个问题是,如果您快速将iOS设备旋转180度,相机将显示为颠倒.
以下是旋转前相机视图的样子:

这是旋转后的样子:

另外,这是我的实现viewDidLayoutSubviews:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
previewLayer.frame = self.view.bounds;
self.view.translatesAutoresizingMaskIntoConstraints = NO;
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.view.layer addSublayer:previewLayer];
if (previewLayer.connection.supportsVideoOrientation) {
previewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation:[UIApplication sharedApplication].statusBarOrientation];
}
}
Run Code Online (Sandbox Code Playgroud)
这个180度旋转发生时有没有人知道为什么摄像机视图会颠倒?
我相信它正在发生,因为viewDidLayoutSubviews当视图从纵向方向更改为UpsideDown时,不会调用它.当你快速旋转时,它会从一个直线转到另一个直线.如果你慢慢旋转它会通过横向方向,因此viewDidLayoutSubviews被调用,然后调用你的方法.
我建议你使用方向更改时调用的方法之一.我知道Apple建议越来越少地使用它们,因为它们希望在大小改变时改变视图,但是有些情况下,例如当你真的需要知道方向改变时.
例如,您可以注册接收此通知:
UIApplicationDidChangeStatusBarOrientationNotification
我之前也遇到过同样的问题,这解决了我的问题。
我声明了一个全局变量:
@interface YourViewController ()
{
...
UIDevice *iOSDevice;
}
..
@end
Run Code Online (Sandbox Code Playgroud)
在(.m文件)下implementation我声明了NSNotification观察者,如下-viewWillAppear所示:
@implementation YourViewController
-(void)viewWillAppear:(BOOL)animated
{
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]];
}
-(void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}
- (void)orientationChanged:(NSNotification *)notification
{
iOSDevice = notification.object;
previewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation];
//or
[self setAutoVideoConnectionOrientation:YES];
}
Run Code Online (Sandbox Code Playgroud)
我创建了一个返回复制的当前设备的方向的函数,例如:
看看我的-interfaceOrientationToVideoOrientation方法,它会将其转换iOSDevice.orientation为AVCaptureVideoOrientation与您那里相同的内容。
(就我而言,我需要下面的这个功能,但看看它可能出于某种原因对你有用)
- (AVCaptureVideoOrientation)interfaceOrientationToVideoOrientation
{
switch (iOSDevice.orientation) {
case UIInterfaceOrientationPortraitUpsideDown:
return AVCaptureVideoOrientationPortraitUpsideDown;
case UIInterfaceOrientationLandscapeLeft:
return AVCaptureVideoOrientationLandscapeLeft;
case UIInterfaceOrientationLandscapeRight:
return AVCaptureVideoOrientationLandscapeRight;
default:
case UIDeviceOrientationPortrait:
return AVCaptureVideoOrientationPortrait;
}
}
- (AVCaptureConnection *)setAutoVideoConnectionOrientation:(BOOL)status
{
AVCaptureConnection *videoConnection = nil;
//This is for me
//for (AVCaptureConnection *connection in stillImageOutput.connections) {
//This might be for you
for (AVCaptureConnection *connection in previewLayer.connection) {
for (AVCaptureInputPort *port in [connection inputPorts])
{
if ([[port mediaType] isEqual:AVMediaTypeVideo])
{
videoConnection = connection;
if (status == YES)
{
[videoConnection setVideoOrientation:[self interfaceOrientationToVideoOrientation]];
}
else
{
[videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait];
}
}
if (videoConnection)
{
break;
}
}
}
return videoConnection;
}
Run Code Online (Sandbox Code Playgroud)
编辑
对于默认方向:您需要检查“当前”方向。
- (void)viewDidLoad
{
[super viewDidLoad];
// assuming you finish setting the `previewLayer`
..
// after all of that code, when the view is ready for displaying
// if you implemented this approach the best thing to do is:
// set this
iOSDevice = [UIDevice currentDevice];
// then call
previewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation];
// to update the `previewLayer.connection.videoOrientation ` for default orientation
}
Run Code Online (Sandbox Code Playgroud)
笔记:
使用NSNotificationCenter让设备的旋转在触发之前先被解决。
希望这对你有帮助..
| 归档时间: |
|
| 查看次数: |
1157 次 |
| 最近记录: |