react-native-camera-kit-no-.../ios/ReactNativeCameraKit/RatioOverlayView.swift
David Bertet a13aa787c4
Add iOS linter & report issues on PR (#634)
* Add iOS linter & report issues on PR

* Fix lint errors

---------

Co-authored-by: Seph Soliman <github@seph.dk>
2024-04-30 16:10:07 -07:00

165 lines
5.2 KiB
Swift

//
// RatioOverlayView.swift
// ReactNativeCameraKit
//
import UIKit
struct RatioOverlayData: CustomStringConvertible {
let width: Float
let height: Float
let ratio: Float
init(from inputString: String) {
let values = inputString.split(separator: ":")
if values.count == 2,
let inputHeight = Float(values[0]),
let inputWidth = Float(values[1]),
inputHeight != 0,
inputWidth != 0 {
height = inputHeight
width = inputWidth
ratio = width / height
} else {
height = 0
width = 0
ratio = 0
}
}
// MARK: CustomStringConvertible
var description: String {
return "height:\(height) width:\(width) ratio:\(ratio)"
}
}
/*
* Full screen overlay that can appear on top of the camera as an hint for the expected ratio
*/
class RatioOverlayView: UIView {
private var ratioData: RatioOverlayData?
private let topView: UIView = UIView()
private let bottomView: UIView = UIView()
// MARK: - Lifecycle
init(frame: CGRect, ratioString: String, overlayColor: UIColor?) {
super.init(frame: frame)
isUserInteractionEnabled = false
let color = overlayColor ?? UIColor.black.withAlphaComponent(0.3)
setColor(color)
addSubview(topView)
addSubview(bottomView)
setRatio(ratioString)
}
@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
setOverlayParts()
}
// MARK: - Public
func setRatio(_ ratioString: String) {
ratioData = RatioOverlayData(from: ratioString)
UIView.animate(withDuration: 0.2) {
self.setOverlayParts()
}
}
func setColor(_ color: UIColor) {
topView.backgroundColor = color
bottomView.backgroundColor = color
}
// MARK: - Private
// swiftlint:disable:next function_body_length
private func setOverlayParts() {
guard let ratioData, ratioData.ratio != 0 else {
isHidden = true
return
}
isHidden = false
var centerSize = CGSize.zero
var sideSize = CGSize.zero
var centerFrame: CGRect
if ratioData.width < ratioData.height {
centerSize.width = frame.size.width
centerSize.height = frame.size.height * CGFloat(ratioData.ratio)
sideSize.width = centerSize.width
sideSize.height = (frame.size.height - centerSize.height) / 2.0
topView.frame = CGRect(x: 0,
y: 0,
width: sideSize.width,
height: sideSize.height)
centerFrame = CGRect(x: 0,
y: topView.frame.size.height + topView.frame.origin.y,
width: centerSize.width,
height: centerSize.height)
bottomView.frame = CGRect(x: 0,
y: centerFrame.size.height + centerFrame.origin.y,
width: sideSize.width,
height: sideSize.height)
} else if ratioData.width > ratioData.height {
centerSize.width = frame.size.width / CGFloat(ratioData.ratio)
centerSize.height = frame.size.height
sideSize.width = (frame.size.width - centerSize.width) / 2.0
sideSize.height = centerSize.height
topView.frame = CGRect(x: 0,
y: 0,
width: sideSize.width,
height: sideSize.height)
centerFrame = CGRect(x: topView.frame.size.width + topView.frame.origin.x,
y: 0,
width: centerSize.width,
height: centerSize.height)
bottomView.frame = CGRect(x: centerFrame.size.width + centerFrame.origin.x,
y: 0,
width: sideSize.width,
height: sideSize.height)
} else { // ratio is 1:1
centerSize.width = frame.size.width
centerSize.height = frame.size.width
sideSize.width = centerSize.width
sideSize.height = (frame.size.height - centerSize.height) / 2.0
topView.frame = CGRect(x: 0,
y: 0,
width: sideSize.width,
height: sideSize.height)
centerFrame = CGRect(x: 0,
y: topView.frame.size.height + topView.frame.origin.y,
width: centerSize.width,
height: centerSize.height)
bottomView.frame = CGRect(x: 0,
y: centerFrame.size.height + centerFrame.origin.y,
width: sideSize.width,
height: sideSize.height)
}
}
}