Take a picture (ID Card in this case) through a frame with rounded edges using SwiftUI

568 views Asked by At

I have managed to take a correct picture of an ID Card, however, to help the user to frame it I need to do it through a frame with rounded edges exactly as shown in the image. I have tried many approaches without success. Could someone give me some guidance?

import UIKit
import SwiftUI
import AVFoundation

struct CameraView: UIViewControllerRepresentable {
    @Binding var isShowing: Bool
    @Binding var capturedImage: UIImage?
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<CameraView>) -> UIViewController {
        let cameraView = UIImagePickerController()
        cameraView.sourceType = .camera
        cameraView.delegate = context.coordinator
        return cameraView
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<CameraView>) {

    }

    func makeCoordinator() -> Coordinator {
        return Coordinator(isShowing: $isShowing, capturedImage: $capturedImage)
    }

    class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        @Binding var isShowing: Bool
        @Binding var capturedImage: UIImage?

        init(isShowing: Binding<Bool>, capturedImage: Binding<UIImage?>) {
            _isShowing = isShowing
            _capturedImage = capturedImage
        }

        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
            capturedImage = image
            isShowing = false
        }

        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            isShowing = false
        }
    }
}

This is my basic approach

1

There are 1 answers

0
Ashley Mills On BEST ANSWER

The way to handle this is to use the UIImagePickerController.cameraOverlayView property. You assign a UIView to this which is presented over the top of the camera.

Here's a (bad looking) example, using SwiftUI View and a UIHostingController

struct Overlay: View {

    var body: some View {
        VStack(spacing: 0) {
            Rectangle().fill(.black.opacity(0.5))
                .frame(height: 100)
            HStack(spacing: 0) {
                Rectangle().fill(.black.opacity(0.5))
                    .frame(width: 20)
                Color.clear
                Rectangle().fill(.black.opacity(0.5))
                    .frame(width: 20)
            }
            .frame(maxWidth: .infinity)
            .frame(height: 200)
            Rectangle().fill(.black.opacity(0.5))
            Color.clear
                .frame(height: 200)
        }
    }
}

and then

func makeUIViewController(context: UIViewControllerRepresentableContext<CameraView>) -> UIViewController {
    let cameraView = UIImagePickerController()
    cameraView.sourceType = .camera
    cameraView.delegate = context.coordinator
    
    let overlayView = UIHostingController(rootView: Overlay()).view
    overlayView?.backgroundColor = .clear
    overlayView?.isUserInteractionEnabled = false
    overlayView?.frame = (cameraView.cameraOverlayView?.frame)!
    cameraView.cameraOverlayView = overlayView
    return cameraView
}

gives…

enter image description here

There are more details in the Apple documentation