refactored checkbox coloring
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
parent
e8abde15f1
commit
0b8d585354
@ -26,75 +26,58 @@ import Combine
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Private Properties
|
// MARK: - Private Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
private func getCheckboxBackgroundColor(for disabled: Bool, surface: Surface) -> (on: UIColor, off: UIColor) {
|
private func getCheckboxBackgroundColor(viewModel: ModelType) -> UIColor {
|
||||||
if disabled {
|
var colors: (on: UIColor, off: UIColor)
|
||||||
if surface == .light {
|
if viewModel.disabled {
|
||||||
return (
|
if viewModel.surface == .light {
|
||||||
on: VDSColor.interactiveDisabledOnlight,
|
colors = (on: VDSColor.interactiveDisabledOnlight, off: .clear)
|
||||||
off: .clear)
|
|
||||||
} else {
|
} else {
|
||||||
return (
|
colors = (on: VDSColor.interactiveDisabledOndark, off: .clear)
|
||||||
on: VDSColor.interactiveDisabledOndark,
|
|
||||||
off: .clear
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if surface == .light {
|
if viewModel.surface == .light {
|
||||||
return (
|
colors = (on: VDSColor.elementsPrimaryOnlight, off: .clear)
|
||||||
on: VDSColor.elementsPrimaryOnlight,
|
|
||||||
off: .clear
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
return (
|
colors = (on: VDSColor.elementsPrimaryOndark, off: .clear)
|
||||||
on: VDSColor.elementsPrimaryOndark,
|
|
||||||
off: .clear
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return viewModel.on ? colors.on : colors.off
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getCheckboxBorderColor(for disabled: Bool, surface: Surface) -> (on: UIColor, off: UIColor) {
|
private func getCheckboxBorderColor(viewModel: ModelType) -> UIColor {
|
||||||
if disabled {
|
var colors: (on: UIColor, off: UIColor)
|
||||||
if surface == .light {
|
if viewModel.disabled {
|
||||||
return (
|
if viewModel.surface == .light {
|
||||||
on: VDSColor.interactiveDisabledOnlight,
|
colors = (on: VDSColor.interactiveDisabledOnlight, off: VDSColor.interactiveDisabledOnlight)
|
||||||
off: VDSColor.interactiveDisabledOnlight
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
return (
|
colors = (on: VDSColor.interactiveDisabledOndark, off: VDSColor.interactiveDisabledOnlight)
|
||||||
on: VDSColor.interactiveDisabledOndark,
|
|
||||||
off: VDSColor.interactiveDisabledOnlight
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if surface == .light {
|
if viewModel.surface == .light {
|
||||||
return (
|
colors = (on: VDSColor.elementsPrimaryOnlight, off: VDSFormControlsColor.borderOnlight)
|
||||||
on: VDSColor.elementsPrimaryOnlight,
|
|
||||||
off: VDSFormControlsColor.borderOnlight
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
return (
|
colors = (on: VDSColor.elementsPrimaryOndark, off: VDSFormControlsColor.borderOndark)
|
||||||
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 disabled {
|
||||||
if surface == .light {
|
if surface == .light {
|
||||||
return VDSColor.interactiveDisabledOndark
|
color = VDSColor.interactiveDisabledOndark
|
||||||
} else {
|
} else {
|
||||||
return VDSColor.interactiveDisabledOnlight
|
color = VDSColor.interactiveDisabledOnlight
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if surface == .light {
|
if surface == .light {
|
||||||
return VDSColor.elementsPrimaryOndark
|
color = VDSColor.elementsPrimaryOndark
|
||||||
} else {
|
} else {
|
||||||
return VDSColor.elementsPrimaryOnlight
|
color = VDSColor.elementsPrimaryOnlight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return viewModel.on ? color : .clear
|
||||||
}
|
}
|
||||||
|
|
||||||
private var mainStackView: UIStackView = {
|
private var mainStackView: UIStackView = {
|
||||||
@ -138,8 +121,8 @@ import Combine
|
|||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private var checkboxView: CheckBoxView = {
|
private var checkboxView: UIView = {
|
||||||
let view = CheckBoxView()
|
let view = UIView()
|
||||||
view.translatesAutoresizingMaskIntoConstraints = false
|
view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
@ -235,7 +218,7 @@ import Combine
|
|||||||
|
|
||||||
checkboxHeightConstraint?.constant = checkboxSize.height
|
checkboxHeightConstraint?.constant = checkboxSize.height
|
||||||
checkboxWidthConstraint?.constant = checkboxSize.width
|
checkboxWidthConstraint?.constant = checkboxSize.width
|
||||||
setCheckboxColor(viewModel: model)
|
updateCheckbox(viewModel: model)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func setupView() {
|
public override func setupView() {
|
||||||
@ -259,7 +242,7 @@ import Combine
|
|||||||
checkboxWidthConstraint = checkboxView.widthAnchor.constraint(equalToConstant: checkboxSize.width)
|
checkboxWidthConstraint = checkboxView.widthAnchor.constraint(equalToConstant: checkboxSize.width)
|
||||||
checkboxWidthConstraint?.isActive = true
|
checkboxWidthConstraint?.isActive = true
|
||||||
|
|
||||||
setCheckboxColor(viewModel: model)
|
updateCheckbox(viewModel: model)
|
||||||
|
|
||||||
mainStackView.topAnchor.constraint(equalTo: topAnchor).isActive = true
|
mainStackView.topAnchor.constraint(equalTo: topAnchor).isActive = true
|
||||||
mainStackView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
|
mainStackView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
|
||||||
@ -268,19 +251,6 @@ import Combine
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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) {
|
func ensureLabel(viewModel: ModelType) {
|
||||||
|
|
||||||
//deal with labels
|
//deal with labels
|
||||||
@ -325,11 +295,69 @@ import Combine
|
|||||||
|
|
||||||
public override func reset() {
|
public override func reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
setCheckboxColor(viewModel: model)
|
updateCheckbox(viewModel: model)
|
||||||
setAccessibilityLabel()
|
setAccessibilityLabel()
|
||||||
onChange = nil
|
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
|
// MARK: - Actions
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -375,7 +403,7 @@ import Combine
|
|||||||
let enabled = !viewModel.disabled
|
let enabled = !viewModel.disabled
|
||||||
|
|
||||||
ensureLabel(viewModel: viewModel)
|
ensureLabel(viewModel: viewModel)
|
||||||
setCheckboxColor(viewModel: viewModel)
|
updateCheckbox(viewModel: viewModel)
|
||||||
setAccessibilityHint(enabled)
|
setAccessibilityHint(enabled)
|
||||||
setAccessibilityValue(viewModel.on)
|
setAccessibilityValue(viewModel.on)
|
||||||
setAccessibilityLabel(viewModel.on)
|
setAccessibilityLabel(viewModel.on)
|
||||||
@ -384,75 +412,4 @@ import Combine
|
|||||||
layoutIfNeeded()
|
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user