refactored checkbox coloring

Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
Matt Bruce 2022-08-03 09:52:23 -05:00
parent e8abde15f1
commit 0b8d585354

View File

@ -26,75 +26,58 @@ import Combine
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
private func getCheckboxBackgroundColor(for disabled: Bool, surface: Surface) -> (on: UIColor, off: UIColor) {
if disabled {
if surface == .light {
return (
on: VDSColor.interactiveDisabledOnlight,
off: .clear)
private func getCheckboxBackgroundColor(viewModel: ModelType) -> UIColor {
var colors: (on: UIColor, off: UIColor)
if viewModel.disabled {
if viewModel.surface == .light {
colors = (on: VDSColor.interactiveDisabledOnlight, off: .clear)
} else {
return (
on: VDSColor.interactiveDisabledOndark,
off: .clear
)
colors = (on: VDSColor.interactiveDisabledOndark, off: .clear)
}
} else {
if surface == .light {
return (
on: VDSColor.elementsPrimaryOnlight,
off: .clear
)
if viewModel.surface == .light {
colors = (on: VDSColor.elementsPrimaryOnlight, off: .clear)
} else {
return (
on: VDSColor.elementsPrimaryOndark,
off: .clear
)
colors = (on: VDSColor.elementsPrimaryOndark, off: .clear)
}
}
return viewModel.on ? colors.on : colors.off
}
private func getCheckboxBorderColor(for disabled: Bool, surface: Surface) -> (on: UIColor, off: UIColor) {
if disabled {
if surface == .light {
return (
on: VDSColor.interactiveDisabledOnlight,
off: VDSColor.interactiveDisabledOnlight
)
private func getCheckboxBorderColor(viewModel: ModelType) -> UIColor {
var colors: (on: UIColor, off: UIColor)
if viewModel.disabled {
if viewModel.surface == .light {
colors = (on: VDSColor.interactiveDisabledOnlight, off: VDSColor.interactiveDisabledOnlight)
} else {
return (
on: VDSColor.interactiveDisabledOndark,
off: VDSColor.interactiveDisabledOnlight
)
colors = (on: VDSColor.interactiveDisabledOndark, off: VDSColor.interactiveDisabledOnlight)
}
} else {
if surface == .light {
return (
on: VDSColor.elementsPrimaryOnlight,
off: VDSFormControlsColor.borderOnlight
)
if viewModel.surface == .light {
colors = (on: VDSColor.elementsPrimaryOnlight, off: VDSFormControlsColor.borderOnlight)
} else {
return (
on: VDSColor.elementsPrimaryOndark,
off: VDSFormControlsColor.borderOndark
)
colors = (on: VDSColor.elementsPrimaryOndark, off: VDSFormControlsColor.borderOndark)
}
}
return viewModel.on ? colors.on : colors.off
}
private func getCheckboxCheckColor(for disabled: Bool, surface: Surface) -> UIColor {
private func getCheckboxCheckColor(viewModel: ModelType) -> UIColor {
var color: UIColor
if disabled {
if surface == .light {
return VDSColor.interactiveDisabledOndark
color = VDSColor.interactiveDisabledOndark
} else {
return VDSColor.interactiveDisabledOnlight
color = VDSColor.interactiveDisabledOnlight
}
} else {
if surface == .light {
return VDSColor.elementsPrimaryOndark
color = VDSColor.elementsPrimaryOndark
} else {
return VDSColor.elementsPrimaryOnlight
color = VDSColor.elementsPrimaryOnlight
}
}
return viewModel.on ? color : .clear
}
private var mainStackView: UIStackView = {
@ -138,8 +121,8 @@ import Combine
return label
}()
private var checkboxView: CheckBoxView = {
let view = CheckBoxView()
private var checkboxView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
@ -235,7 +218,7 @@ import Combine
checkboxHeightConstraint?.constant = checkboxSize.height
checkboxWidthConstraint?.constant = checkboxSize.width
setCheckboxColor(viewModel: model)
updateCheckbox(viewModel: model)
}
public override func setupView() {
@ -259,7 +242,7 @@ import Combine
checkboxWidthConstraint = checkboxView.widthAnchor.constraint(equalToConstant: checkboxSize.width)
checkboxWidthConstraint?.isActive = true
setCheckboxColor(viewModel: model)
updateCheckbox(viewModel: model)
mainStackView.topAnchor.constraint(equalTo: topAnchor).isActive = true
mainStackView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
@ -267,20 +250,7 @@ import Combine
mainStackView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
}
/// Creates the check mark layer.
private func setCheckboxColor(viewModel: ModelType) {
let background = getCheckboxBackgroundColor(for: viewModel.disabled, surface: viewModel.surface)
let border = getCheckboxBorderColor(for: viewModel.disabled, surface: viewModel.surface)
let checkColor = getCheckboxCheckColor(for: viewModel.disabled, surface: viewModel.surface)
let backgroundColor = viewModel.on ? background.on : background.off
checkboxView.backgroundColor = backgroundColor
checkboxView.borderColor = viewModel.on ? border.on : border.off
checkboxView.checkColor = viewModel.on ? checkColor : backgroundColor
checkboxView.isSelected = viewModel.on
}
func ensureLabel(viewModel: ModelType) {
//deal with labels
@ -325,10 +295,68 @@ import Combine
public override func reset() {
super.reset()
setCheckboxColor(viewModel: model)
updateCheckbox(viewModel: model)
setAccessibilityLabel()
onChange = nil
}
//--------------------------------------------------
// MARK: - Checkbox View
//--------------------------------------------------
/// Manages the appearance of the checkbox.
private var shapeLayer: CAShapeLayer?
private func updateCheckbox(viewModel: ModelType) {
//get the colors
let backgroundColor = getCheckboxBackgroundColor(viewModel: viewModel)
let borderColor = getCheckboxBorderColor(viewModel: viewModel)
let checkColor = getCheckboxCheckColor(viewModel: viewModel)
if let shapeLayer = shapeLayer, let sublayers = layer.sublayers, sublayers.contains(shapeLayer) {
shapeLayer.removeFromSuperlayer()
self.shapeLayer = nil
}
checkboxView.backgroundColor = backgroundColor
checkboxView.layer.borderColor = borderColor.cgColor
checkboxView.layer.cornerRadius = 2.0
checkboxView.layer.borderWidth = 1.0
if shapeLayer == nil {
let bounds = checkboxView.bounds
let length = max(bounds.size.height, bounds.size.width)
guard length > 0.0, shapeLayer == nil else { return }
//draw the checkmark layer
let xInsetLeft = length * 0.25
let yInsetTop = length * 0.3
let innerWidth = length - (xInsetLeft + length * 0.25) // + Right X Inset
let innerHeight = length - (yInsetTop + length * 0.35) // + Bottom Y Inset
let startPoint = CGPoint(x: xInsetLeft, y: yInsetTop + (innerHeight / 2))
let pivotOffSet = CGPoint(x: xInsetLeft + (innerWidth * 0.33), y: yInsetTop + innerHeight)
let endOffset = CGPoint(x: xInsetLeft + innerWidth, y: yInsetTop)
let bezierPath = UIBezierPath()
bezierPath.move(to: startPoint)
bezierPath.addLine(to: pivotOffSet)
bezierPath.addLine(to: endOffset)
let shapeLayer = CAShapeLayer()
self.shapeLayer = shapeLayer
shapeLayer.frame = bounds
layer.addSublayer(shapeLayer)
shapeLayer.strokeColor = checkColor.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.path = bezierPath.cgPath
shapeLayer.lineJoin = .miter
shapeLayer.lineWidth = 2
CATransaction.withDisabledAnimations {
shapeLayer.strokeEnd = model.on ? 1 : 0
}
}
}
//--------------------------------------------------
// MARK: - Actions
@ -375,7 +403,7 @@ import Combine
let enabled = !viewModel.disabled
ensureLabel(viewModel: viewModel)
setCheckboxColor(viewModel: viewModel)
updateCheckbox(viewModel: viewModel)
setAccessibilityHint(enabled)
setAccessibilityValue(viewModel.on)
setAccessibilityLabel(viewModel.on)
@ -384,75 +412,4 @@ import Combine
layoutIfNeeded()
}
private class CheckBoxView: UIView {
public var borderColor: UIColor = .black
public var checkColor: UIColor = .white
public var isSelected: Bool = false {
didSet {
if let shapeLayer = shapeLayer, let sublayers = layer.sublayers, sublayers.contains(shapeLayer) {
shapeLayer.removeFromSuperlayer()
self.shapeLayer = nil
}
}
}
/// Manages the appearance of the checkbox.
private var shapeLayer: CAShapeLayer?
/// Creates the check mark layer.
private func drawShapeLayer() {
layer.borderColor = borderColor.cgColor
layer.cornerRadius = 2.0
layer.borderWidth = 1.0
shapeLayer?.strokeColor = checkColor.cgColor
guard let path = try? checkMarkPath(), shapeLayer == nil else { return }
if shapeLayer == nil {
let shapeLayer = CAShapeLayer()
self.shapeLayer = shapeLayer
shapeLayer.frame = bounds
layer.addSublayer(shapeLayer)
shapeLayer.strokeColor = checkColor.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.path = path
shapeLayer.lineJoin = .miter
shapeLayer.lineWidth = 2
CATransaction.withDisabledAnimations {
shapeLayer.strokeEnd = isSelected ? 1 : 0
}
}
}
override func layoutSubviews() {
super.layoutSubviews()
drawShapeLayer()
}
/// - returns: The CGPath of a UIBezierPath detailing the path of a checkmark
private func checkMarkPath() throws -> CGPath {
let length = max(bounds.size.height, bounds.size.width)
guard length > 0.0 else { throw Error.boundsNotSet }
let xInsetLeft = length * 0.25
let yInsetTop = length * 0.3
let innerWidth = length - (xInsetLeft + length * 0.25) // + Right X Inset
let innerHeight = length - (yInsetTop + length * 0.35) // + Bottom Y Inset
let startPoint = CGPoint(x: xInsetLeft, y: yInsetTop + (innerHeight / 2))
let pivotOffSet = CGPoint(x: xInsetLeft + (innerWidth * 0.33), y: yInsetTop + innerHeight)
let endOffset = CGPoint(x: xInsetLeft + innerWidth, y: yInsetTop)
let bezierPath = UIBezierPath()
bezierPath.move(to: startPoint)
bezierPath.addLine(to: pivotOffSet)
bezierPath.addLine(to: endOffset)
return bezierPath.cgPath
}
enum Error: Swift.Error {
case boundsNotSet
}
}
}