Skip to content

Customizing MCamera Screens

Tomasz K. edited this page Dec 13, 2024 · 35 revisions

Dzisiejsze pokolenie ma mocne głowy i zimne serca.

Customizing MCamera Screens

Overview

MCamera is a view object that contains three screens that are displayed in relation to the state of the camera:

  • ErrorScreen, which is shown when the user denies any of the required permissions,
  • CapturedMediaScreen, which is presented when the user captures either an image or video (can be disabled),
  • CameraScreen, which contains all of the camera controls that the user can interact with to adjust and capture images or video.

On this page, we are going to learn how to create your own `MCamera' screen(s) and what methods you can use to make this process as easy as possible for you. For this reason, this page is divided into three separate sections that cover this topic and provide a code example to help you easily get started with customizing your own camera screens.

MCameraErrorScreen

Overview

By definition, it's a screen that displays an error message when one or more camera permissions are denied by the user. The default screen can be replaced by creating a structure conforming to MCameraErrorScreen and setting it as the error screen during MCamera initialization.

Step-By-Step Guide

  1. Create a struct conforming to MCameraErrorScreen

    struct CustomCameraErrorScreen: MCameraErrorScreen {
        let error: MCameraError
        let closeMCameraAction: () -> ()
    
    
        var body: some View {
            Button(action: openAppSettings) { Text("Open Settings") }
        }
    }
  2. Pass the newly created screen as an argument during MCamera initialization

    struct ContentView: View {
        var body: some View {
            MCamera()
                .setErrorScreen(CustomCameraErrorScreen.init)
    
                // MUST BE CALLED!
                .startSession()
        }
    }

MCameraErrorScreen Available Methods

  • func openAppSettings()
    • A method that when triggered, the user will open the application settings.

MCapturedMediaScreen

Overview

In a nutshell, it's a screen that displays the captured media. The default screen can be replaced by creating a structure conforming to MCapturedMediaScreen and setting it as the captured media screen during MCamera initialization. It's also possible to disable this screen by calling the `setCapturedMediaScreen' method with a nil value.

Step-By-Step Guide

  1. Create a struct conforming to MCapturedMediaScreen

    struct CustomCapturedMediaScreen: MCapturedMediaScreen {
        let capturedMedia: MCameraMedia
        let namespace: Namespace.ID
        let retakeAction: () -> ()
        let acceptMediaAction: () -> ()
    
    
        var body: some View {
            VStack(spacing: 0) {
                Spacer()
                createContentView()
                Spacer()
                createButtons()
            }
        }
    }
    private extension CustomCapturedMediaScreen {
        func createContentView() -> some View { ZStack {
            if let image = capturedMedia.getImage() { createImageView(image) }
            else { EmptyView() }
        }}
        func createButtons() -> some View {
            HStack(spacing: 24) {
                createRetakeButton()
                createSaveButton()
            }
        }
    }
    private extension CustomCapturedMediaScreen {
        func createImageView(_ image: UIImage) -> some View {
            Image(uiImage: image)
                .resizable()
                .aspectRatio(contentMode: .fit)
                .ignoresSafeArea()
        }
        func createRetakeButton() -> some View {
            Button(action: retakeAction) { Text("Retake") }
        }
        func createSaveButton() -> some View {
            Button(action: acceptMediaAction) { Text("Save") }
        }
    }
  2. Pass the newly created screen as an argument during MCamera initialization

    struct ContentView: View {
        var body: some View {
            MCamera()
                .setCapturedMediaScreen(CustomCapturedMediaScreen.init)
    
                // MUST BE CALLED!
                .startSession()
        }
    }

MCameraScreen

Overview

A screen that displays the camera view and manages camera actions. It contains many methods that allow you to easily create a screen that suits your needs. The default screen can be replaced by creating a structure conforming to MCameraScreen and setting it as the captured media screen during MCamera initialization.

Step-By-Step Guide

  1. Create a struct conforming to MCameraScreen

    struct CustomCameraScreen: MCameraScreen {
        @ObservedObject var cameraManager: CameraManager
        let namespace: Namespace.ID
        let closeMCameraAction: () -> ()
    
    
        var body: some View {
            VStack(spacing: 0) {
                createNavigationBar()
                createCameraOutputView()
                createCaptureButton()
            }
        }
    }
    private extension CustomCameraScreen {
        func createNavigationBar() -> some View {
            Text("This is a Custom Camera View")
                .padding(.top, 12)
                .padding(.bottom, 12)
        }
        func createCaptureButton() -> some View {
            Button(action: captureOutput) { Text("Click to capture") }
                .padding(.top, 12)
                .padding(.bottom, 12)
        }
    }
  2. Pass the newly created screen as an argument during MCamera initialization

    struct ContentView: View {
        var body: some View {
            MCamera()
                .setCameraScreen(CustomCameraErrorScreen.init)
    
                // MUST BE CALLED!
                .startSession()
        }
    }

MCameraScreen Available Methods

  • func createCameraOutputView() -> some View

    • View that displays the camera output.
  • func captureOutput()

    • Capture the current camera output.
    • The output type depends on what cameraOutputType is set to.
  • func setOutputType(_ outputType: CameraOutputType)

    • Set the output type of the camera.
  • func setCameraPosition(_ cameraPosition: CameraPosition) async throws

    • Set the camera position.
    • If the selected camera position is not available, the camera will not be changed.
  • func setZoomFactor(_ zoomFactor: CGFloat) throws

    • Set the zoom factor of the camera.
    • If the zoom factor is out of bounds, it will be set to the closest available value.
  • func setFlashMode(_ flashMode: CameraFlashMode)

    • Set the flash mode of the camera.
    • If the selected flash mode is not available, the flash mode will not be changed.
  • func setLightMode(_ lightMode: CameraLightMode) throws

    • Set the light mode of the camera.
    • If the selected light mode is not available, the light mode will not be changed.
  • func setResolution(_ resolution: AVCaptureSession.Preset)

    • Set the camera resolution.
    • Changing the resolution may affect the maximum frame rate that can be set.
  • func setFrameRate(_ frameRate: Int32) throws

    • Set the camera frame rate.
    • Changing the resolution may affect the maximum frame rate that can be set.
    • If the frame rate is out of bounds, it will be set to the closest available value.
  • func setExposureDuration(_ exposureDuration: CMTime) throws

    • Set the camera exposure duration.
    • If the exposure duration is out of bounds, it will be set to the closest available value.
  • func setExposureTargetBias(_ exposureTargetBias: Float) throws

    • Set the camera exposure target bias.
    • If the target bias is out of bounds, it will be set to the closest available value.
  • func setISO(_ iso: Float) throws

    • Set the camera ISO.
    • If the ISO is out of bounds, it will be set to the closest available value.
  • func setExposureMode(_ exposureMode: AVCaptureDevice.ExposureMode) throws

    • Set the camera exposure mode.
    • If the exposure mode is not supported, the exposure mode will not be changed.
  • func setHDRMode(_ hdrMode: CameraHDRMode) throws

    • Set the camera HDR mode.
  • func setCameraFilters(_ filters: [CIFilter])

    • Set the camera filters to be applied to the camera output.
    • Setting multiple filters simultaneously can affect the performance of the camera.
  • func setMirrorOutput(_ shouldMirror: Bool)

    • Set whether the camera output should be mirrored.
  • func setGridVisibility(_ shouldShowGrid: Bool)

    • Set whether the camera grid should be visible.

MCameraScreen Available Attributes

  • var cameraOutputType: CameraOutputType
  • var cameraPosition: CameraPosition
  • var zoomFactor: CGFloat
  • var flashMode: CameraFlashMode
  • var lightMode: CameraLightMode
  • var resolution: AVCaptureSession.Preset
  • var frameRate: Int32
  • var exposureDuration: CMTime
  • var exposureTargetBias: Float
  • var iso: Float
  • var exposureMode: AVCaptureDevice.ExposureMode
  • var hdrMode: CameraHDRMode
  • var cameraFilters: [CIFilter]
  • var isOutputMirrored: Bool
  • var isGridVisible: Bool
  • var hasFlash: Bool
  • var hasLight: Bool
  • var recordingTime: MTime
  • var isRecording: Bool
  • var isOrientationLocked: Bool
  • var deviceOrientation: AVCaptureVideoOrientation

See also