【问题标题】:view.frame change on orientation change - no changeview.frame 在方向改变时改变 - 没有改变
【发布时间】:2020-06-16 13:52:25
【问题描述】:

我正在使用 SwiftUI 开发一个应用程序 - 使用一些 UIKit 组件 - 具有画中画功能,并且我试图在旋转设备时将图片保持在屏幕的特定角落。为此,我需要更改框架在视图上的位置,因此我已注册 UIDevice.orientationDidChangeNotification,当收到此通知时,我会更改 UIViewController 中的视图框架,如下所示:

@objc func onViewDidTransition() {
        view.frame = CGRect(x: 100, y: 100, width: 200, height: 200)
        self.cameraPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.landscapeRight
    }

但是,这似乎没有任何作用。框架根本没有变化。好像UIView 保留了旧框架并更改为新的CGRect 无济于事。当我使用view.frame. 检查对象时,没有xy 的选项,好像这些属性在初始化后不可更改。这是正确的吗?我没有办法改变框架的位置吗?

编辑:代码。

框架在CustomCameraControllersetup()函数中设置

func setup() {
            view.frame = CGRect(x: 225, y: 0, width: 150, height: 150)

后来在onViewDidTransition()修改了

@objc func onViewDidTransition() {
        view.frame = CGRect(x: 662, y: 0, width: 150, height: 150)

当转换为横向时,这应该将图片放在右上角 (iphone x),但事实并非如此。图像停留在距左角 200 pt 处。

最少可重现的 ContentView 代码

import SwiftUI
import AVFoundation

struct CustomCameraPhotoView: View {

    @State private var image: Image?
    @State private var showingCustomCamera = false
    @State private var showImagePicker = false
    @State private var inputImage: UIImage?
    @State private var url: URL?

    var body: some View {
        CustomCameraView(image: self.$inputImage)
    }
}

struct CustomCameraView: View {

    @Binding var image: UIImage?
    @State var didTapCapture: Bool = false
    var body: some View {
        ZStack() {

            CustomCameraRepresentable(image: self.$image, didTapCapture: $didTapCapture)
        }
    }

}

struct CustomCameraRepresentable: UIViewControllerRepresentable {

    @Environment(\.presentationMode) var presentationMode
    @Binding var image: UIImage?
    @Binding var didTapCapture: Bool

    func makeUIViewController(context: Context) -> CustomCameraController {
        let controller = CustomCameraController()
        controller.delegate = context.coordinator
        return controller
    }

    func updateUIViewController(_ cameraViewController: CustomCameraController, context: Context) {

        if(self.didTapCapture) {
            cameraViewController.didTapRecord()
        }
    }
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, UINavigationControllerDelegate, AVCapturePhotoCaptureDelegate {
        let parent: CustomCameraRepresentable

        init(_ parent: CustomCameraRepresentable) {
            self.parent = parent
        }

        func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {

            parent.didTapCapture = false

            if let imageData = photo.fileDataRepresentation() {
                parent.image = UIImage(data: imageData)
            }
            parent.presentationMode.wrappedValue.dismiss()
        }
    }
}

class CustomCameraController: UIViewController {

    var image: UIImage?

    var captureSession = AVCaptureSession()
    var backCamera: AVCaptureDevice?
    var frontCamera: AVCaptureDevice?
    var currentCamera: AVCaptureDevice?
    var photoOutput: AVCapturePhotoOutput?
    var cameraPreviewLayer: AVCaptureVideoPreviewLayer?

    //DELEGATE
    var delegate: AVCapturePhotoCaptureDelegate?

    func didTapRecord() {

        let settings = AVCapturePhotoSettings()
        photoOutput?.capturePhoto(with: settings, delegate: delegate!)

    }

    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
    }
    func setup() {
        view.frame = CGRect(x: 225, y: 0, width: 150, height: 150)
        view.layer.cornerRadius = 40
        view.layer.masksToBounds = true
        view.backgroundColor = .white
        setupCaptureSession()
        setupDevice()
        setupInputOutput()
        setupPreviewLayer()
        startRunningCaptureSession()

        NotificationCenter.default.addObserver(self, selector: #selector(onViewDidTransition), name: UIDevice.orientationDidChangeNotification, object: nil)
    }

    deinit {
        NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)
    }

    @objc func onViewDidTransition() {
        view.frame = CGRect(x: 662, y: 0, width: 150, height: 150)
        self.cameraPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.landscapeRight
        //UIDevice.current.orientation
    }

    func setupCaptureSession() {
        let cameraMediaType = AVMediaType.video
        let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: cameraMediaType)

        switch cameraAuthorizationStatus {
        case .denied: break
        case .authorized: break
        case .restricted: break

        case .notDetermined:
            // Prompting user for the permission to use the camera.
            AVCaptureDevice.requestAccess(for: cameraMediaType) { granted in
                if granted {
                    print("Granted access to \(cameraMediaType)")
                } else {
                    print("Denied access to \(cameraMediaType)")
                }
            }
        @unknown default:
            break
        }
        captureSession.sessionPreset = AVCaptureSession.Preset.iFrame1280x720
    }

    func setupDevice() {
        let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera],
                                                                      mediaType: AVMediaType.video,
                                                                      position: AVCaptureDevice.Position.front)
        for device in deviceDiscoverySession.devices {

            switch device.position {
            case AVCaptureDevice.Position.front:
                self.frontCamera = device
            case AVCaptureDevice.Position.back:
                self.backCamera = device
            default:
                break
            }
        }

        self.currentCamera = self.frontCamera
    }


    func setupInputOutput() {
        do {

            let captureDeviceInput = try AVCaptureDeviceInput(device: currentCamera!)
            captureSession.addInput(captureDeviceInput)
            photoOutput = AVCapturePhotoOutput()
            photoOutput?.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.hevc])], completionHandler: nil)
            captureSession.addOutput(photoOutput!)

        } catch {
            print(error)
        }

    }
    func setupPreviewLayer()
    {
        self.cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        self.cameraPreviewLayer?.cornerRadius = 40
        self.cameraPreviewLayer?.masksToBounds = true
        self.cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
        self.cameraPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
        self.cameraPreviewLayer?.frame = self.view.frame
        self.view.layer.insertSublayer(cameraPreviewLayer!, at: 0)

    }
    func startRunningCaptureSession(){
        captureSession.startRunning()
    }
}

【问题讨论】:

  • 任何最小的可重现代码?
  • @Asperi 我会准备一些东西并编辑我的问题
  • @Asperi 我添加了一些重点内容,应该可以用不多的代码证明问题。

标签: ios swift uikit swiftui


【解决方案1】:

愚蠢的错误。我正在修改视图的框架:

view.frame = CGRect(x: 662, y: 0, width: 150, height: 150)

当我本应查看相机预览层的框架时:

self.cameraPreviewLayer?.frame = self.view.frame

我已经更改了代码以修改相机预览层并保留视图框架,现在它可以工作了。

self.cameraPreviewLayer?.frame = CGRect(x: 662, y: 0, width: 150, height: 150)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-01
    相关资源
    最近更新 更多