简体   繁体   中英

SwiftUI 5: How to lock orientation for a specific view

On my camera view, I want to keep the orientation as portrait because when it's in landscape, the camera preview does not rotate:


struct CameraPreview: UIViewRepresentable {
    
    @ObservedObject var camera: CameraModel
    
    func makeUIView(context: Context) -> some UIView {
        
        let view = UIView(frame: UIScreen.main.bounds)
        
        camera.preview = AVCaptureVideoPreviewLayer(session: camera.session)
        
        //...
        camera.preview.videoGravity = .resizeAspectFill
        camera.preview.frame = view.frame
        view.layer.addSublayer(camera.preview)
        
        
        // starting session
        camera.session.startRunning()
        
        return view
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) {
        
    }
    
}

I know I'll need to fix this sooner or later but I need to get moving. For now, I'll prevent all other orientations except:


struct CameraView: View {
    init() {
        let value = UIInterfaceOrientation.portrait.rawValue
        UIDevice.current.setValue(value, forKey: "orientation")
    }

[..]

By doing the above, when put in landscape, the camera preview cuts in half then the init "kicks in" which sets it back CameraView back into portrait. How to let it stay in portrait mode without any animation?

Placing the code inside .onAppear does nothing:



struct CameraView: View {
  var body: some View {

    VStack{..}
      .onAppear(perform: {
        let value = UIInterfaceOrientation.portrait.rawValue
        UIDevice.current.setValue(value, forKey: "orientation")
      }
  }

Well it turns out I've fixed the rotation instead:

func updateUIView(_ uiView: UIViewType, context: Context) {
    let view = UIView(frame: UIScreen.main.bounds)
    let statusBarOrientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
    let videoOrientation: AVCaptureVideoOrientation = statusBarOrientation?.videoOrientation ?? .portrait
    camera.preview.frame = view.frame
    camera.preview.connection?.videoOrientation = videoOrientation
}

For videoOrientation see Jack's answer .


import AVFoundation

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
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM