Added a new extension file for CATransaction. Implementation of Checkbox and CheckboxWithLabel.
This commit is contained in:
parent
5f8780614f
commit
77a3eb8827
@ -19,6 +19,7 @@
|
|||||||
01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; };
|
01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */; };
|
0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */; };
|
||||||
0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */; };
|
0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */; };
|
||||||
|
0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; };
|
||||||
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; };
|
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; };
|
||||||
948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; };
|
948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; };
|
||||||
B8200E152280C4CF007245F4 /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E142280C4CF007245F4 /* ProgressBar.swift */; };
|
B8200E152280C4CF007245F4 /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E142280C4CF007245F4 /* ProgressBar.swift */; };
|
||||||
@ -205,6 +206,7 @@
|
|||||||
01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MFTextFieldListView.swift; sourceTree = "<group>"; };
|
01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MFTextFieldListView.swift; sourceTree = "<group>"; };
|
||||||
01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldListFormViewController.swift; sourceTree = "<group>"; };
|
01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldListFormViewController.swift; sourceTree = "<group>"; };
|
||||||
0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = "<group>"; };
|
0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = "<group>"; };
|
||||||
|
0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CATransaction+Extension.swift"; sourceTree = "<group>"; };
|
||||||
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = "<group>"; };
|
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = "<group>"; };
|
||||||
0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = "<group>"; };
|
0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = "<group>"; };
|
||||||
948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = "<group>"; };
|
948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = "<group>"; };
|
||||||
@ -654,6 +656,7 @@
|
|||||||
D29DF2A021E7AF4E003B2FB9 /* MVMCoreUIUtility.m */,
|
D29DF2A021E7AF4E003B2FB9 /* MVMCoreUIUtility.m */,
|
||||||
D29DF2A721E7B2F9003B2FB9 /* MVMCoreUIConstants.h */,
|
D29DF2A721E7B2F9003B2FB9 /* MVMCoreUIConstants.h */,
|
||||||
D29DF2A821E7B2F9003B2FB9 /* MVMCoreUIConstants.m */,
|
D29DF2A821E7B2F9003B2FB9 /* MVMCoreUIConstants.m */,
|
||||||
|
0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */,
|
||||||
);
|
);
|
||||||
path = Utility;
|
path = Utility;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1095,6 +1098,7 @@
|
|||||||
D29DF25121E6A177003B2FB9 /* MFDigitTextBox.m in Sources */,
|
D29DF25121E6A177003B2FB9 /* MFDigitTextBox.m in Sources */,
|
||||||
DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */,
|
DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */,
|
||||||
0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */,
|
0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */,
|
||||||
|
0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */,
|
||||||
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
|
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
|
||||||
D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */,
|
D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */,
|
||||||
0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */,
|
0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */,
|
||||||
|
|||||||
@ -8,6 +8,22 @@
|
|||||||
|
|
||||||
import MVMCore
|
import MVMCore
|
||||||
|
|
||||||
|
/*
|
||||||
|
!!! -- DO NOT REMOVE -- !!!
|
||||||
|
(Unless Design changes the appearance of the checkmark).
|
||||||
|
|
||||||
|
// Offsets based on the 124x124 example checkmark
|
||||||
|
let startXOffset: Float = 42.0 / 124.0 ~~ 0.33871
|
||||||
|
let startYOffset: Float = 66.0 / 124.0 ~~ 0.53225
|
||||||
|
let pivotXOffset: Float = 58.0 / 124.0 ~~ 0.46774
|
||||||
|
let pivotYOffset: Float = 80.0 / 124.0 ~~ 0.64516
|
||||||
|
let endXOffset: Float = 83.0 / 124.0 ~~ 0.66935
|
||||||
|
let endYOffset: Float = 46.0 / 124.0 ~~ 0.37097
|
||||||
|
let pivotPercentage: Float = 0.34
|
||||||
|
let endPercentage = 1.0 - pivotPercentage
|
||||||
|
let animationInterval: Float = 0.01
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class expects its height and width to be equal.
|
This class expects its height and width to be equal.
|
||||||
*/
|
*/
|
||||||
@ -16,85 +32,82 @@ import MVMCore
|
|||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
// Form Validation
|
||||||
|
var isRequired = false
|
||||||
|
var fieldKey: String?
|
||||||
|
var delegateObject: DelegateObject?
|
||||||
|
|
||||||
public static let defaultHeightWidth: CGFloat = 18.0
|
public static let defaultHeightWidth: CGFloat = 18.0
|
||||||
|
|
||||||
/// The color of the background when checked.
|
/// If true the border of this checkbox will be circular.
|
||||||
public var checkedBackgroundColor: UIColor?
|
public var isRound: Bool = false
|
||||||
|
|
||||||
/// The color of the background when unChecked. Will change of the view's background color.
|
/// Determined if the checkbox's UI should animated when selected.
|
||||||
public var unCheckedBackgroundColor: UIColor = .white {
|
public var isAnimated: Bool = true
|
||||||
didSet (newColor) {
|
|
||||||
backgroundColor = newColor
|
/// Disables all selection logic when setting the value of isSelected, reducing it to a stored property.
|
||||||
|
public var updateSelectionOnly: Bool = false
|
||||||
|
|
||||||
|
/// The color of the background when checked.
|
||||||
|
public var checkedBackgroundColor: UIColor = .white {
|
||||||
|
didSet {
|
||||||
|
if isSelected {
|
||||||
|
backgroundColor = checkedBackgroundColor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If true the border of this checkbox will be circular.
|
/// The color of the background when unChecked.
|
||||||
public var hasRoundedCorners = false
|
public var unCheckedBackgroundColor: UIColor = .white {
|
||||||
|
didSet {
|
||||||
// Action Block called when the switch is selected.
|
if !isSelected {
|
||||||
public var actionBlock: ActionBlock?
|
backgroundColor = unCheckedBackgroundColor
|
||||||
|
}
|
||||||
// Internal values to manage the appearance of the checkbox.
|
}
|
||||||
private var shapeLayer: CAShapeLayer?
|
}
|
||||||
|
|
||||||
public var cornerRadiusValue: CGFloat {
|
public var cornerRadiusValue: CGFloat {
|
||||||
return bounds.size.height / 2
|
return bounds.size.height / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
public var lineWidth: CGFloat = 2
|
/// Action Block called when the switch is selected.
|
||||||
public var lineColor: UIColor = .black
|
public var actionBlock: ActionBlock?
|
||||||
public var borderColor: UIColor = .black
|
|
||||||
|
/// Manages the appearance of the checkbox.
|
||||||
|
private var shapeLayer: CAShapeLayer?
|
||||||
|
|
||||||
|
public var checkWidth: CGFloat = 2
|
||||||
|
public var checkColor: UIColor = .black
|
||||||
public var borderWidth: CGFloat = 1
|
public var borderWidth: CGFloat = 1
|
||||||
|
public var borderColor: UIColor = .black
|
||||||
|
|
||||||
override open var isSelected: Bool {
|
override open var isSelected: Bool {
|
||||||
didSet {
|
didSet {
|
||||||
shapeLayer?.removeAllAnimations()
|
if !updateSelectionOnly {
|
||||||
if isSelected {
|
layoutIfNeeded()
|
||||||
if checkedBackgroundColor != nil {
|
shapeLayer?.removeAllAnimations()
|
||||||
UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseOut, animations: {
|
|
||||||
self.backgroundColor = self.checkedBackgroundColor
|
updateCheckboxUI(selection: isSelected, isAnimated: isAnimated)
|
||||||
})
|
|
||||||
|
if let delegate = delegateObject as? FormValidationProtocol {
|
||||||
|
delegate.formValidatorModel?()?.enableByValidation()
|
||||||
}
|
}
|
||||||
shapeLayer?.add(checkedAnimation, forKey: "strokeEnd")
|
|
||||||
} else {
|
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "checkbox_checked_state" : "checkbox_unchecked_state")
|
||||||
if checkedBackgroundColor != nil {
|
|
||||||
UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseOut, animations: {
|
|
||||||
self.backgroundColor = self.unCheckedBackgroundColor
|
|
||||||
})
|
|
||||||
}
|
|
||||||
shapeLayer?.add(uncheckedAnimation, forKey: "strokeEnd")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy private var checkedAnimation: CABasicAnimation = {
|
|
||||||
let check = CABasicAnimation(keyPath: "strokeEnd")
|
|
||||||
check.timingFunction = CAMediaTimingFunction(name: .linear)
|
|
||||||
check.isRemovedOnCompletion = false
|
|
||||||
check.fillMode = .both
|
|
||||||
check.duration = 0.3
|
|
||||||
check.fromValue = 0
|
|
||||||
check.toValue = 1
|
|
||||||
return check
|
|
||||||
}()
|
|
||||||
|
|
||||||
lazy private var uncheckedAnimation: CABasicAnimation = {
|
|
||||||
let unCheck = CABasicAnimation(keyPath: "strokeEnd")
|
|
||||||
unCheck.timingFunction = CAMediaTimingFunction(name: .linear)
|
|
||||||
unCheck.isRemovedOnCompletion = false
|
|
||||||
unCheck.fillMode = .both
|
|
||||||
unCheck.duration = 0.3
|
|
||||||
unCheck.fromValue = 1
|
|
||||||
unCheck.toValue = 0
|
|
||||||
return unCheck
|
|
||||||
}()
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializers
|
// MARK: - Initializers
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
override public init(frame: CGRect) {
|
override public init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
accessibilityTraits = .none
|
||||||
|
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "checkbox_action_hint")
|
||||||
|
|
||||||
setupView()
|
setupView()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,16 +121,20 @@ import MVMCore
|
|||||||
self.init(frame:.zero)
|
self.init(frame:.zero)
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(checkedColor: UIColor, unCheckedColor: UIColor, isChecked: Bool = false) {
|
public convenience init(isChecked: Bool) {
|
||||||
self.init(frame: .zero)
|
self.init(frame: .zero)
|
||||||
|
updateSelectionOnly = true
|
||||||
isSelected = isChecked
|
isSelected = isChecked
|
||||||
self.checkedBackgroundColor = checkedColor
|
updateSelectionOnly = false
|
||||||
self.unCheckedBackgroundColor = unCheckedColor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(isCircular: Bool) {
|
public convenience init(checkedBackgroundColor: UIColor, unCheckedBackgroundColor: UIColor, isChecked: Bool = false) {
|
||||||
self.init(frame: .zero)
|
self.init(frame: .zero)
|
||||||
hasRoundedCorners = isCircular
|
updateSelectionOnly = true
|
||||||
|
isSelected = isChecked
|
||||||
|
updateSelectionOnly = false
|
||||||
|
self.checkedBackgroundColor = checkedBackgroundColor
|
||||||
|
self.unCheckedBackgroundColor = unCheckedBackgroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -126,9 +143,9 @@ import MVMCore
|
|||||||
|
|
||||||
override open func layoutSubviews() {
|
override open func layoutSubviews() {
|
||||||
super.layoutSubviews()
|
super.layoutSubviews()
|
||||||
|
|
||||||
drawCheck()
|
drawCheck()
|
||||||
layer.cornerRadius = hasRoundedCorners ? cornerRadiusValue : 0
|
layer.cornerRadius = isRound ? cornerRadiusValue : 0
|
||||||
backgroundColor = unCheckedBackgroundColor
|
|
||||||
layer.borderWidth = borderWidth
|
layer.borderWidth = borderWidth
|
||||||
layer.borderColor = borderColor.cgColor
|
layer.borderColor = borderColor.cgColor
|
||||||
}
|
}
|
||||||
@ -137,6 +154,7 @@ import MVMCore
|
|||||||
|
|
||||||
isUserInteractionEnabled = true
|
isUserInteractionEnabled = true
|
||||||
translatesAutoresizingMaskIntoConstraints = false
|
translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
backgroundColor = .white
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -161,6 +179,7 @@ import MVMCore
|
|||||||
// MARK: - Methods
|
// MARK: - Methods
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
/// Creates the check mark used for the checkbox.
|
||||||
private func drawCheck() {
|
private func drawCheck() {
|
||||||
|
|
||||||
if shapeLayer == nil {
|
if shapeLayer == nil {
|
||||||
@ -169,36 +188,20 @@ import MVMCore
|
|||||||
self.shapeLayer = shapeLayer
|
self.shapeLayer = shapeLayer
|
||||||
shapeLayer.frame = bounds
|
shapeLayer.frame = bounds
|
||||||
layer.addSublayer(shapeLayer)
|
layer.addSublayer(shapeLayer)
|
||||||
shapeLayer.strokeColor = lineColor.cgColor
|
shapeLayer.strokeColor = checkColor.cgColor
|
||||||
shapeLayer.fillColor = UIColor.clear.cgColor
|
shapeLayer.fillColor = UIColor.clear.cgColor
|
||||||
shapeLayer.path = checkMarkBezierPath.cgPath
|
shapeLayer.path = checkMarkPath.cgPath
|
||||||
shapeLayer.lineJoin = .bevel
|
shapeLayer.lineJoin = .bevel
|
||||||
shapeLayer.lineWidth = lineWidth
|
shapeLayer.lineWidth = checkWidth
|
||||||
|
|
||||||
CATransaction.withDisabledAnimations {
|
CATransaction.withDisabledAnimations {
|
||||||
shapeLayer.strokeEnd = 0.0
|
shapeLayer.strokeEnd = isSelected ? 1 : 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
!!! -- DO NOT REMOVE -- !!!
|
|
||||||
(Unless Design changes the appearance of the checkmark).
|
|
||||||
|
|
||||||
// Offsets based on the 124x124 example checkmark
|
|
||||||
let startXOffset: Float = 42.0 / 124.0 ~~ 0.33871
|
|
||||||
let startYOffset: Float = 66.0 / 124.0 ~~ 0.53225
|
|
||||||
let pivotXOffset: Float = 58.0 / 124.0 ~~ 0.46774
|
|
||||||
let pivotYOffset: Float = 80.0 / 124.0 ~~ 0.64516
|
|
||||||
let endXOffset: Float = 83.0 / 124.0 ~~ 0.66935
|
|
||||||
let endYOffset: Float = 46.0 / 124.0 ~~ 0.37097
|
|
||||||
let pivotPercentage: Float = 0.34
|
|
||||||
let endPercentage = 1.0 - pivotPercentage
|
|
||||||
let animationInterval: Float = 0.01
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// Returns a UIBezierPath detailing the path of a checkmark
|
/// Returns a UIBezierPath detailing the path of a checkmark
|
||||||
var checkMarkBezierPath: UIBezierPath {
|
var checkMarkPath: UIBezierPath {
|
||||||
|
|
||||||
let sideLength = bounds.size.height
|
let sideLength = bounds.size.height
|
||||||
let startPoint = CGPoint(x: 0.33871 * sideLength, y: 0.53225 * sideLength)
|
let startPoint = CGPoint(x: 0.33871 * sideLength, y: 0.53225 * sideLength)
|
||||||
@ -213,38 +216,43 @@ import MVMCore
|
|||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateSelection(_ selected: Bool, animated: Bool) {
|
/// Programmatic means to check/uncheck the box.
|
||||||
|
/// - parameter selected: state of the check box: true = checked OR false = unchecked.
|
||||||
// shapeLayer?.removeFromSuperlayer()
|
/// - parameter animated: allows the state of the checkbox to change with or without animation.
|
||||||
// shapeLayer = nil
|
public func updateSelection(to selected: Bool, animated: Bool) {
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
|
||||||
|
self.updateSelectionOnly = true
|
||||||
self.isSelected = selected
|
self.isSelected = selected
|
||||||
|
self.updateSelectionOnly = false
|
||||||
self.drawCheck()
|
self.drawCheck()
|
||||||
|
self.shapeLayer?.removeAllAnimations()
|
||||||
|
self.updateCheckboxUI(selection: selected, isAnimated: animated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateCheckboxUI(selection: Bool, isAnimated: Bool) {
|
||||||
|
|
||||||
|
if isAnimated {
|
||||||
|
let animateStrokeEnd = CABasicAnimation(keyPath: "strokeEnd")
|
||||||
|
animateStrokeEnd.timingFunction = CAMediaTimingFunction(name: .linear)
|
||||||
|
animateStrokeEnd.duration = 0.3
|
||||||
|
animateStrokeEnd.fillMode = .both
|
||||||
|
animateStrokeEnd.isRemovedOnCompletion = false
|
||||||
|
animateStrokeEnd.fromValue = !selection ? 1 : 0
|
||||||
|
animateStrokeEnd.toValue = selection ? 1 : 0
|
||||||
|
self.shapeLayer?.add(animateStrokeEnd, forKey: "strokeEnd")
|
||||||
|
|
||||||
var layer: CAShapeLayer?
|
UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseOut, animations: {
|
||||||
if let presentation = self.shapeLayer?.presentation(), animated {
|
self.backgroundColor = selection ? self.checkedBackgroundColor : self.unCheckedBackgroundColor
|
||||||
layer = presentation
|
})
|
||||||
} else {
|
} else {
|
||||||
layer = self.shapeLayer
|
CATransaction.withDisabledAnimations {
|
||||||
|
self.shapeLayer?.strokeEnd = selection ? 1 : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if animated {
|
self.backgroundColor = selection ? self.checkedBackgroundColor : self.unCheckedBackgroundColor
|
||||||
let animateStrokeEnd = CABasicAnimation(keyPath: "strokeEnd")
|
|
||||||
animateStrokeEnd.timingFunction = CAMediaTimingFunction(name: .linear)
|
|
||||||
animateStrokeEnd.duration = 0.33
|
|
||||||
animateStrokeEnd.fillMode = .both
|
|
||||||
animateStrokeEnd.isRemovedOnCompletion = false
|
|
||||||
animateStrokeEnd.fromValue = layer?.strokeEnd ?? 0
|
|
||||||
animateStrokeEnd.toValue = selected ? 1 : 0
|
|
||||||
layer?.add(animateStrokeEnd, forKey: "strokeEndAnimation")
|
|
||||||
} else {
|
|
||||||
layer?.removeAllAnimations()
|
|
||||||
CATransaction.withDisabledAnimations {
|
|
||||||
layer?.strokeEnd = selected ? 1 : 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,11 +262,7 @@ import MVMCore
|
|||||||
|
|
||||||
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||||
|
|
||||||
if touchIsAcceptablyOutside(touches.first) {
|
sendActions(for: touchIsAcceptablyOutside(touches.first) ? .touchUpOutside : .touchUpInside)
|
||||||
sendActions(for: .touchUpOutside)
|
|
||||||
} else {
|
|
||||||
sendActions(for: .touchUpInside)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func touchIsAcceptablyOutside(_ touch: UITouch?) -> Bool {
|
func touchIsAcceptablyOutside(_ touch: UITouch?) -> Bool {
|
||||||
@ -272,40 +276,6 @@ import MVMCore
|
|||||||
return x < -faultTolerance || y < -faultTolerance || x > widthLimit || y > heightLimt
|
return x < -faultTolerance || y < -faultTolerance || x > widthLimit || y > heightLimt
|
||||||
}
|
}
|
||||||
|
|
||||||
// if delegate && delegate.responds(to: #selector(formValidationProtocol)) && delegate.perform(#selector(formValidationProtocol)).responds(to: #selector(Unmanaged<AnyObject>.formValidatorModel)) {
|
|
||||||
// let formValidator = delegate.perform(#selector(formValidationProtocol)).perform(#selector(Unmanaged<AnyObject>.formValidatorModel)) as? FormValidator
|
|
||||||
// formValidator?.enableByValidation()
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
- (void)setSelected:(BOOL)selected animated:(BOOL)animated runBlock:(BOOL)runBlock {
|
|
||||||
[self addAccessibilityLabel:selected];
|
|
||||||
|
|
||||||
self.isSelected = selected;
|
|
||||||
if (self.switchSelected && runBlock) {
|
|
||||||
self.switchSelected(selected);
|
|
||||||
}
|
|
||||||
if (selected) {
|
|
||||||
[UIView animateWithDuration:0.2 delay:0.1 options:UIViewAnimationOptionCurveEaseOut animations:^{
|
|
||||||
self.checkedSquare.backgroundColor = self.checkedColor;
|
|
||||||
} completion:nil];
|
|
||||||
[self.checkMark updateCheckSelected:YES animated:animated];
|
|
||||||
} else {
|
|
||||||
[UIView animateWithDuration:0.2 delay:0.1 options:UIViewAnimationOptionCurveEaseOut animations:^{
|
|
||||||
self.checkedSquare.backgroundColor = self.unCheckedColor;
|
|
||||||
} completion:nil];
|
|
||||||
[self.checkMark updateCheckSelected:NO animated:animated];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.delegate && [self.delegate respondsToSelector:@selector(formValidationProtocol)] && [[self.delegate performSelector:@selector(formValidationProtocol)] respondsToSelector:@selector(formValidatorModel)]) {
|
|
||||||
FormValidator *formValidator = [[self.delegate performSelector:@selector(formValidationProtocol)] performSelector:@selector(formValidatorModel)];
|
|
||||||
[formValidator enableByValidation];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Molecular
|
// MARK: - Molecular
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -322,15 +292,22 @@ import MVMCore
|
|||||||
setupView()
|
setupView()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateView(_ size: CGFloat) {
|
public func updateView(_ size: CGFloat) { }
|
||||||
|
|
||||||
// TODO: Ensure the check logic is resized.
|
|
||||||
}
|
|
||||||
|
|
||||||
public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||||
|
self.delegateObject = delegateObject
|
||||||
|
FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol)
|
||||||
|
|
||||||
guard let dictionary = json else { return }
|
guard let dictionary = json else { return }
|
||||||
|
|
||||||
|
if let fieldKey = dictionary[KeyFieldKey] as? String {
|
||||||
|
self.fieldKey = fieldKey
|
||||||
|
}
|
||||||
|
|
||||||
|
if let isRequired = dictionary[KeyRequired] as? Bool {
|
||||||
|
self.isRequired = isRequired
|
||||||
|
}
|
||||||
|
|
||||||
if let borderColorHex = dictionary["borderColor"] as? String {
|
if let borderColorHex = dictionary["borderColor"] as? String {
|
||||||
layer.borderColor = UIColor.mfGet(forHex: borderColorHex).cgColor
|
layer.borderColor = UIColor.mfGet(forHex: borderColorHex).cgColor
|
||||||
}
|
}
|
||||||
@ -339,36 +316,50 @@ import MVMCore
|
|||||||
layer.borderWidth = borderWidth
|
layer.borderWidth = borderWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
if let checkColorHex = dictionary["lineColor"] as? String {
|
if let isChecked = dictionary["isChecked"] as? Bool, isChecked {
|
||||||
lineColor = UIColor.mfGet(forHex: checkColorHex)
|
updateSelectionOnly = true
|
||||||
|
isSelected = isChecked
|
||||||
|
updateSelectionOnly = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if let checkColorHex = dictionary["checkedColor"] as? String {
|
if let checkColorHex = dictionary["checkColor"] as? String {
|
||||||
checkedBackgroundColor = UIColor.mfGet(forHex: checkColorHex)
|
checkColor = UIColor.mfGet(forHex: checkColorHex)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let unCheckedColorHex = dictionary["unCheckedColor"] as? String {
|
if let unCheckedBackgroundColorHex = dictionary["unCheckedBackgroundColor"] as? String {
|
||||||
unCheckedBackgroundColor = UIColor.mfGet(forHex: unCheckedColorHex)
|
unCheckedBackgroundColor = UIColor.mfGet(forHex: unCheckedBackgroundColorHex)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let checkedBackgroundColorHex = dictionary["checkedBackgroundColor"] as? String {
|
||||||
|
checkedBackgroundColor = UIColor.mfGet(forHex: checkedBackgroundColorHex)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let isAnimated = dictionary["isAnimated"] as? Bool {
|
||||||
|
self.isAnimated = isAnimated
|
||||||
}
|
}
|
||||||
|
|
||||||
if let isRound = dictionary["isRound"] as? Bool {
|
if let isRound = dictionary["isRound"] as? Bool {
|
||||||
hasRoundedCorners = isRound
|
self.isRound = isRound
|
||||||
}
|
}
|
||||||
|
|
||||||
// if let actionMap = dictionary.optionalDictionaryForKey("actionMap") {
|
if let actionMap = dictionary.optionalDictionaryForKey("actionMap") {
|
||||||
// actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) }
|
actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) }
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Move to its own extension file.
|
// MARK:- FormValidationProtocol
|
||||||
extension CATransaction {
|
extension Checkbox: FormValidationProtocol {
|
||||||
|
|
||||||
/// Performs changes without activating animation actions.
|
public func isValidField() -> Bool {
|
||||||
static func withDisabledAnimations(_ actionBlock: ActionBlock) {
|
return isRequired ? isSelected : true
|
||||||
CATransaction.begin()
|
}
|
||||||
CATransaction.setDisableActions(true)
|
|
||||||
actionBlock()
|
public func formFieldName() -> String? {
|
||||||
CATransaction.commit()
|
return fieldKey
|
||||||
|
}
|
||||||
|
|
||||||
|
public func formFieldValue() -> Any? {
|
||||||
|
return NSNumber(value: isSelected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,8 +12,8 @@
|
|||||||
// MARK: - Outlets
|
// MARK: - Outlets
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
let checkbox = Checkbox()
|
public let checkbox = Checkbox()
|
||||||
let label = Label.commonLabelB2(true)
|
public let label = Label.commonLabelB2(true)
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
@ -21,17 +21,34 @@
|
|||||||
|
|
||||||
var sizeObject: MFSizeObject? = MFSizeObject(standardSize: Checkbox.defaultHeightWidth, standardiPadPortraitSize: Checkbox.defaultHeightWidth + 6.0)
|
var sizeObject: MFSizeObject? = MFSizeObject(standardSize: Checkbox.defaultHeightWidth, standardiPadPortraitSize: Checkbox.defaultHeightWidth + 6.0)
|
||||||
|
|
||||||
var isRequired = false
|
var checkboxPosition: CheckboxPosition = .centerLeft
|
||||||
var fieldKey: String?
|
|
||||||
var delegate: DelegateObject?
|
public enum CheckboxPosition: String {
|
||||||
|
case centerLeft
|
||||||
|
case topLeft
|
||||||
|
case bottomLeft
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Constraints
|
// MARK: - Constraints
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
var checkboxWidthConstraint: NSLayoutConstraint?
|
var checkboxWidthConstraint: NSLayoutConstraint?
|
||||||
var checkboxHeightConstraint: NSLayoutConstraint?
|
var checkboxHeightConstraint: NSLayoutConstraint?
|
||||||
|
|
||||||
|
var checkboxLeadingConstraint: NSLayoutConstraint?
|
||||||
|
var checkboxTrailingConstraint: NSLayoutConstraint?
|
||||||
|
var checkboxTopConstraint: NSLayoutConstraint?
|
||||||
|
var checkboxBottomConstraint: NSLayoutConstraint?
|
||||||
|
var checkboxCenterYConstraint: NSLayoutConstraint?
|
||||||
|
|
||||||
|
var checkboxLabelConstraint: NSLayoutConstraint?
|
||||||
|
|
||||||
|
var labelLeadingConstraint: NSLayoutConstraint?
|
||||||
|
var labelTrailingConstraint: NSLayoutConstraint?
|
||||||
|
var labelTopConstraint: NSLayoutConstraint?
|
||||||
|
var labelBottomConstraint: NSLayoutConstraint?
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Life Cycle
|
// MARK: - Life Cycle
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -46,23 +63,24 @@
|
|||||||
addSubview(checkbox)
|
addSubview(checkbox)
|
||||||
addSubview(label)
|
addSubview(label)
|
||||||
|
|
||||||
|
label.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||||
|
|
||||||
let dimension = sizeObject?.getValueBasedOnApplicationWidth() ?? Checkbox.defaultHeightWidth
|
let dimension = sizeObject?.getValueBasedOnApplicationWidth() ?? Checkbox.defaultHeightWidth
|
||||||
checkboxWidthConstraint = checkbox.heightAnchor.constraint(equalToConstant: dimension)
|
checkboxWidthConstraint = checkbox.heightAnchor.constraint(equalToConstant: dimension)
|
||||||
checkboxWidthConstraint?.isActive = true
|
checkboxWidthConstraint?.isActive = true
|
||||||
checkboxHeightConstraint = checkbox.widthAnchor.constraint(equalToConstant: dimension)
|
checkboxHeightConstraint = checkbox.widthAnchor.constraint(equalToConstant: dimension)
|
||||||
checkboxHeightConstraint?.isActive = true
|
checkboxHeightConstraint?.isActive = true
|
||||||
|
|
||||||
checkbox.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor).isActive = true
|
alignSubviews(by: .centerLeft)
|
||||||
layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: checkbox.bottomAnchor).isActive = true
|
|
||||||
checkbox.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true
|
|
||||||
checkbox.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
|
|
||||||
checkbox.checkedBackgroundColor = .yellow
|
|
||||||
|
|
||||||
label.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor).isActive = true
|
label.isUserInteractionEnabled = true
|
||||||
layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: label.bottomAnchor).isActive = true
|
let tap = UITapGestureRecognizer(target: self, action: #selector(tapped))
|
||||||
label.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
|
tap.numberOfTapsRequired = 1
|
||||||
layoutMarginsGuide.trailingAnchor.constraint(equalTo: label.trailingAnchor).isActive = true
|
label.addGestureRecognizer(tap)
|
||||||
label.leadingAnchor.constraint(equalTo: checkbox.trailingAnchor, constant: PaddingTwo).isActive = true
|
}
|
||||||
|
|
||||||
|
@objc func tapped() {
|
||||||
|
checkbox.updateSelection(to: !checkbox.isSelected, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -77,13 +95,18 @@
|
|||||||
override public init(frame: CGRect) {
|
override public init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
setupView()
|
setupView()
|
||||||
// addAccessibleProperties()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init() {
|
public convenience init() {
|
||||||
self.init(frame: .zero)
|
self.init(frame: .zero)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public convenience init(position: CheckboxPosition) {
|
||||||
|
self.init(frame: .zero)
|
||||||
|
|
||||||
|
alignSubviews(by: position)
|
||||||
|
}
|
||||||
|
|
||||||
public convenience init(checkedColor: UIColor, unCheckedColor: UIColor, text: String?, isChecked: Bool = false) {
|
public convenience init(checkedColor: UIColor, unCheckedColor: UIColor, text: String?, isChecked: Bool = false) {
|
||||||
self.init(frame: .zero)
|
self.init(frame: .zero)
|
||||||
|
|
||||||
@ -99,79 +122,130 @@
|
|||||||
checkbox.unCheckedBackgroundColor = unCheckedColor
|
checkbox.unCheckedBackgroundColor = unCheckedColor
|
||||||
label.attributedText = attributedText
|
label.attributedText = attributedText
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Methods
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
/// Aligns Checkbox and Label relative to the desired position of the Checkbox.
|
||||||
|
private func alignSubviews(by position: CheckboxPosition) {
|
||||||
|
checkboxPosition = position
|
||||||
|
|
||||||
|
label.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true
|
||||||
|
|
||||||
|
switch position {
|
||||||
|
case .centerLeft:
|
||||||
|
checkboxTopConstraint = checkbox.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor)
|
||||||
|
checkboxBottomConstraint = layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: checkbox.bottomAnchor)
|
||||||
|
checkboxLeadingConstraint = checkbox.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
|
||||||
|
checkboxCenterYConstraint = checkbox.centerYAnchor.constraint(equalTo: centerYAnchor)
|
||||||
|
|
||||||
|
labelTopConstraint = label.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor)
|
||||||
|
labelTrailingConstraint = layoutMarginsGuide.trailingAnchor.constraint(equalTo: label.trailingAnchor)
|
||||||
|
checkboxLabelConstraint = label.leadingAnchor.constraint(equalTo: checkbox.trailingAnchor, constant: PaddingTwo)
|
||||||
|
|
||||||
|
case .topLeft:
|
||||||
|
checkboxTopConstraint = checkbox.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor)
|
||||||
|
checkboxBottomConstraint = layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: checkbox.bottomAnchor)
|
||||||
|
checkboxLeadingConstraint = checkbox.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
|
||||||
|
|
||||||
|
labelTopConstraint = label.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor)
|
||||||
|
labelTrailingConstraint = layoutMarginsGuide.trailingAnchor.constraint(equalTo: label.trailingAnchor)
|
||||||
|
checkboxLabelConstraint = label.leadingAnchor.constraint(equalTo: checkbox.trailingAnchor, constant: PaddingTwo)
|
||||||
|
|
||||||
|
case .bottomLeft:
|
||||||
|
checkboxTopConstraint = checkbox.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor)
|
||||||
|
checkboxBottomConstraint = layoutMarginsGuide.bottomAnchor.constraint(equalTo: checkbox.bottomAnchor)
|
||||||
|
checkboxLeadingConstraint = checkbox.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor)
|
||||||
|
|
||||||
|
labelTopConstraint = label.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor)
|
||||||
|
labelTrailingConstraint = layoutMarginsGuide.trailingAnchor.constraint(equalTo: label.trailingAnchor)
|
||||||
|
checkboxLabelConstraint = label.leadingAnchor.constraint(equalTo: checkbox.trailingAnchor, constant: PaddingTwo)
|
||||||
|
labelBottomConstraint = layoutMarginsGuide.bottomAnchor.constraint(equalTo: label.bottomAnchor)
|
||||||
|
}
|
||||||
|
|
||||||
|
if position != .bottomLeft {
|
||||||
|
layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: label.bottomAnchor).isActive = true
|
||||||
|
let labelBottom = label.bottomAnchor.constraint(equalTo: bottomAnchor)
|
||||||
|
labelBottomConstraint = labelBottom
|
||||||
|
labelBottom.priority = UILayoutPriority(249)
|
||||||
|
labelBottom.isActive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleSubviewConstraints(isActive: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toggleSubviewConstraints(isActive state: Bool) {
|
||||||
|
|
||||||
|
checkboxLeadingConstraint?.isActive = state
|
||||||
|
checkboxTrailingConstraint?.isActive = state
|
||||||
|
checkboxTopConstraint?.isActive = state
|
||||||
|
checkboxBottomConstraint?.isActive = state
|
||||||
|
checkboxCenterYConstraint?.isActive = state
|
||||||
|
labelLeadingConstraint?.isActive = state
|
||||||
|
labelTrailingConstraint?.isActive = state
|
||||||
|
labelTopConstraint?.isActive = state
|
||||||
|
labelBottomConstraint?.isActive = state
|
||||||
|
checkboxLabelConstraint?.isActive = state
|
||||||
|
|
||||||
|
if !state {
|
||||||
|
checkboxLeadingConstraint = nil
|
||||||
|
checkboxTrailingConstraint = nil
|
||||||
|
checkboxTopConstraint = nil
|
||||||
|
checkboxBottomConstraint = nil
|
||||||
|
checkboxCenterYConstraint = nil
|
||||||
|
labelLeadingConstraint = nil
|
||||||
|
labelTrailingConstraint = nil
|
||||||
|
labelTopConstraint = nil
|
||||||
|
labelBottomConstraint = nil
|
||||||
|
checkboxLabelConstraint = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Molecular
|
/// MARK: - Molecular
|
||||||
extension CheckboxWithLabelView {
|
extension CheckboxWithLabelView {
|
||||||
|
|
||||||
override open class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
override open class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||||
return CGFloat(Checkbox.defaultHeightWidth)
|
return CGFloat(Checkbox.defaultHeightWidth)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc override open func updateView(_ size: CGFloat) {
|
@objc override open func updateView(_ size: CGFloat) {
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
label.updateView(size)
|
||||||
self.label.updateView(size)
|
|
||||||
if self.checkbox.responds(to: #selector(self.updateView(_:))) {
|
if self.checkbox.responds(to: #selector(self.updateView(_:))) {
|
||||||
if let dimension = self.sizeObject?.getValueBased(onSize: size) {
|
if let dimension = sizeObject?.getValueBased(onSize: size) {
|
||||||
self.checkboxWidthConstraint?.constant = dimension
|
checkboxWidthConstraint?.constant = dimension
|
||||||
self.checkboxHeightConstraint?.constant = dimension
|
checkboxHeightConstraint?.constant = dimension
|
||||||
self.checkbox.updateView(size)
|
checkbox.updateView(size)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layoutIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
override open func alignment() -> UIStackView.Alignment {
|
override open func alignment() -> UIStackView.Alignment {
|
||||||
return .leading
|
return .leading
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override func resetConstraints() {
|
||||||
|
super.resetConstraints()
|
||||||
|
|
||||||
|
toggleSubviewConstraints(isActive: false)
|
||||||
|
}
|
||||||
|
|
||||||
override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||||
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||||
delegate = delegateObject
|
|
||||||
FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol)
|
|
||||||
|
|
||||||
guard let dictionary = json else { return }
|
guard let dictionary = json else { return }
|
||||||
|
|
||||||
if let fieldKey = dictionary[KeyFieldKey] as? String {
|
if let checkboxAlignment = dictionary["checkboxAlignment"] as? String, let position = CheckboxPosition(rawValue: checkboxAlignment) {
|
||||||
self.fieldKey = fieldKey
|
toggleSubviewConstraints(isActive: false)
|
||||||
}
|
alignSubviews(by: position)
|
||||||
|
|
||||||
if let isRequired = dictionary[KeyRequired] as? Bool {
|
|
||||||
self.isRequired = isRequired
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox.setWithJSON(dictionary.dictionaryForKey("checkbox"), delegateObject: delegateObject, additionalData: additionalData)
|
checkbox.setWithJSON(dictionary.dictionaryForKey("checkbox"), delegateObject: delegateObject, additionalData: additionalData)
|
||||||
label.setWithJSON(dictionary.dictionaryForKey("label"), delegateObject: delegateObject, additionalData: additionalData)
|
label.setWithJSON(dictionary.dictionaryForKey("label"), delegateObject: delegateObject, additionalData: additionalData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK:- FormValidationProtocol
|
|
||||||
extension CheckboxWithLabelView: FormValidationProtocol {
|
|
||||||
|
|
||||||
public func isValidField() -> Bool {
|
|
||||||
return isRequired ? checkbox.isSelected : true
|
|
||||||
}
|
|
||||||
|
|
||||||
public func formFieldName() -> String? {
|
|
||||||
return fieldKey
|
|
||||||
}
|
|
||||||
|
|
||||||
public func formFieldValue() -> Any? {
|
|
||||||
return NSNumber(value: checkbox.isSelected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK:- Accessibility
|
|
||||||
extension CheckboxWithLabelView {
|
|
||||||
|
|
||||||
func addAccessibleProperties() {
|
|
||||||
// accessibilityTraits = .none
|
|
||||||
// accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "checkbox_action_hint")
|
|
||||||
}
|
|
||||||
|
|
||||||
func addAccessibilityLabel(_ selected: Bool) {
|
|
||||||
// let state = selected ? MVMCoreUIUtility.hardcodedString(withKey: "checkbox_checked_state") : MVMCoreUIUtility.hardcodedString(withKey: "checkbox_unchecked_state")
|
|
||||||
// accessibilityLabel = String(format: MVMCoreUIUtility.hardcodedString(withKey: "checkbox_desc_state"), label.text ?? "", state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
21
MVMCoreUI/Utility/CATransaction+Extension.swift
Normal file
21
MVMCoreUI/Utility/CATransaction+Extension.swift
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// CATransaction+Extension.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Kevin Christiano on 10/2/19.
|
||||||
|
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
|
extension CATransaction {
|
||||||
|
|
||||||
|
/// Performs changes without activating animation actions.
|
||||||
|
static func withDisabledAnimations(_ actionBlock: ActionBlock) {
|
||||||
|
CATransaction.begin()
|
||||||
|
CATransaction.setDisableActions(true)
|
||||||
|
actionBlock()
|
||||||
|
CATransaction.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user