2014-01-21 110 views

回答

29

首先,答案

- (void)viewWillLayoutSubviews { 
    _captureVideoPreviewLayer.frame = self.view.bounds; 
    if (_captureVideoPreviewLayer.connection.supportsVideoOrientation) { 
    _captureVideoPreviewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation:[UIApplication sharedApplication].statusBarOrientation]; 
    } 
} 

- (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 (%d)",orientation); 
    return AVCaptureVideoOrientationPortrait; 
} 

我遇到幾個SO帖子在這個問題上,並沒有找到任何簡單的解釋,所以我想我會分享我自己的。

如果按照蘋果的樣品就不管了,你就當你旋轉你的iOS設備爲橫向

  1. Capture將出現旋轉(好像你拿着相機拍攝的90度運行到兩個潛在的問題關閉)
  2. 它不會跨越其設定界限完全

這裏的問題是,「CALayer的」不支持自動旋轉,因此,不同於「的UIView」你添加爲子視圖,它贏得當它的父'UIView'旋轉時不會旋轉。因此,每次父視圖的邊界發生更改時,都必須手動更新其框架(不是父視圖的框架,因爲框架在旋轉後保持不變)。這是通過在容器視圖控制器中重寫'viewWillLayoutSubviews'來實現的。其次,您應該使用'videoOrientation'屬性來告知AVFoundation有關方向,以便正確執行預覽。

希望這會有所幫助。

+0

覆蓋viewWillLayoutSubviews()解決我的問題!謝謝。 – iForests

+0

太棒了!但是我必須通過調用self.view.setNeedsLayout()來調用will-或didRotateToInterfaceOrientation()才能獲得名爲 –

+0

的viewWillLayoutSubviews。此方法對我很有幫助。感謝隊友 –

0

除了viewWillLayoutSubviews(),您還必須實現didRotateFromInterfaceOrientation()。

這是因爲如果設備從縱向模式旋轉到縱向模式(顯然是出於效率原因),子視圖佈局將不會更新。

2
override func viewWillLayoutSubviews() { 
    self.previewLayer.frame = self.view.bounds 
    if previewLayer.connection.isVideoOrientationSupported { 
     self.previewLayer.connection.videoOrientation = self.interfaceOrientation(toVideoOrientation: UIApplication.shared.statusBarOrientation) 
    } 
} 

func interfaceOrientation(toVideoOrientation orientation: UIInterfaceOrientation) -> AVCaptureVideoOrientation { 
    switch orientation { 
    case .portrait: 
     return .portrait 
    case .portraitUpsideDown: 
     return .portraitUpsideDown 
    case .landscapeLeft: 
     return .landscapeLeft 
    case .landscapeRight: 
     return .landscapeRight 
    default: 
     break 
    } 

    print("Warning - Didn't recognise interface orientation (\(orientation))") 
    return .portrait 
} 

// SWIFT 3換算,

+0

這完美地工作_except_在相機不顯示並且由viewDidLoad()運行的情況下,由於previewLayer可能還不存在,它引入了各種各樣的問題。因此,以上@neoneye的答案應該被認爲是正確的。 –

6

Swift3

func updateVideoOrientation() { 
    guard let previewLayer = self.previewLayer else { 
     return 
    } 
    guard previewLayer.connection.isVideoOrientationSupported else { 
     print("isVideoOrientationSupported is false") 
     return 
    } 

    let statusBarOrientation = UIApplication.shared.statusBarOrientation 
    let videoOrientation: AVCaptureVideoOrientation = statusBarOrientation.videoOrientation ?? .portrait 

    if previewLayer.connection.videoOrientation == videoOrientation { 
     print("no change to videoOrientation") 
     return 
    } 

    previewLayer.frame = cameraView.bounds 
    previewLayer.connection.videoOrientation = videoOrientation 
    previewLayer.removeAllAnimations() 
} 

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { 
    super.viewWillTransition(to: size, with: coordinator) 

    coordinator.animate(alongsideTransition: nil, completion: { [weak self] (context) in 
     DispatchQueue.main.async(execute: { 
      self?.updateVideoOrientation() 
     }) 
    }) 
} 

extension UIInterfaceOrientation { 
    var videoOrientation: AVCaptureVideoOrientation? { 
     switch self { 
     case .portraitUpsideDown: return .portraitUpsideDown 
     case .landscapeRight: return .landscapeRight 
     case .landscapeLeft: return .landscapeLeft 
     case .portrait: return .portrait 
     default: return nil 
     } 
    } 
} 
+0

完美。 **謝謝!** –