Decent working state with animation and touch.
This commit is contained in:
parent
afcf8d535b
commit
f5f994648a
@ -16,36 +16,54 @@ import MVMCore
|
|||||||
|
|
||||||
public static let defaultHeightWidth: CGFloat = 18.0
|
public static let defaultHeightWidth: CGFloat = 18.0
|
||||||
|
|
||||||
/// The color of the box and line when checked.
|
/// The color of the background when checked.
|
||||||
public var checkedColor: UIColor = .black
|
public var checkedBackgroundColor: UIColor = .white
|
||||||
|
|
||||||
/// The color of the border when unChecked.
|
/// The color of the background when unChecked.
|
||||||
public var unCheckedColor: UIColor = .black
|
public var unCheckedBackgroundColor: UIColor = .black
|
||||||
|
|
||||||
/// If true the border of this checkbox will be circular.
|
/// If true the border of this checkbox will be circular.
|
||||||
public var hasRoundCorners = false
|
public var hasRoundCorners = false
|
||||||
|
|
||||||
|
// Action Block called when the switch is selected.
|
||||||
|
public var actionBlock: ActionBlock?
|
||||||
|
|
||||||
// Internal values to manage the appearance of the checkbox.
|
// Internal values to manage the appearance of the checkbox.
|
||||||
private var shapeLayer: CAShapeLayer?
|
private var shapeLayer: CAShapeLayer?
|
||||||
|
|
||||||
public var cornerRadiusValue: CGFloat {
|
public var cornerRadiusValue: CGFloat {
|
||||||
return bounds.height / 2
|
return bounds.size.height / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
public var lineWidth: CGFloat = 1
|
public var lineWidth: CGFloat = 2
|
||||||
public var lineColor: UIColor = .black
|
public var lineColor: UIColor = .black
|
||||||
public var borderColor: UIColor = .black
|
|
||||||
public var checkedBackgroundColor: UIColor = .white
|
open var borderColor: UIColor {
|
||||||
|
get {
|
||||||
|
guard let color = layer.borderColor else { return .black }
|
||||||
|
return UIColor(cgColor: color)
|
||||||
|
}
|
||||||
|
set (newColor) {
|
||||||
|
layer.borderColor = newColor.cgColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open var borderWidth: CGFloat {
|
||||||
|
get { return layer.borderWidth }
|
||||||
|
set (newWidth) {
|
||||||
|
layer.borderWidth = newWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override open var isSelected: Bool {
|
override open var isSelected: Bool {
|
||||||
didSet {
|
didSet {
|
||||||
if isSelected {
|
if isSelected {
|
||||||
layer.addSublayer(shapeLayer!)
|
// layer.addSublayer(shapeLayer!)
|
||||||
shapeLayer?.strokeEnd = 1
|
// shapeLayer?.strokeEnd = 1
|
||||||
shapeLayer?.removeAllAnimations()
|
shapeLayer?.removeAllAnimations()
|
||||||
shapeLayer?.add(checkedAnimation, forKey: "strokeEnd")
|
shapeLayer?.add(checkedAnimation, forKey: "strokeEnd")
|
||||||
} else {
|
} else {
|
||||||
shapeLayer?.strokeEnd = 0
|
// shapeLayer?.strokeEnd = 0
|
||||||
shapeLayer?.removeAllAnimations()
|
shapeLayer?.removeAllAnimations()
|
||||||
shapeLayer?.add(uncheckedAnimation, forKey: "strokeEnd")
|
shapeLayer?.add(uncheckedAnimation, forKey: "strokeEnd")
|
||||||
}
|
}
|
||||||
@ -55,8 +73,9 @@ import MVMCore
|
|||||||
lazy private var checkedAnimation: CABasicAnimation = {
|
lazy private var checkedAnimation: CABasicAnimation = {
|
||||||
let check = CABasicAnimation(keyPath: "strokeEnd")
|
let check = CABasicAnimation(keyPath: "strokeEnd")
|
||||||
check.timingFunction = CAMediaTimingFunction(name: .linear)
|
check.timingFunction = CAMediaTimingFunction(name: .linear)
|
||||||
|
check.isRemovedOnCompletion = false
|
||||||
check.fillMode = .both
|
check.fillMode = .both
|
||||||
check.duration = 0.33
|
check.duration = 0.3
|
||||||
check.fromValue = 0
|
check.fromValue = 0
|
||||||
check.toValue = 1
|
check.toValue = 1
|
||||||
return check
|
return check
|
||||||
@ -65,10 +84,11 @@ import MVMCore
|
|||||||
lazy private var uncheckedAnimation: CABasicAnimation = {
|
lazy private var uncheckedAnimation: CABasicAnimation = {
|
||||||
let unCheck = CABasicAnimation(keyPath: "strokeEnd")
|
let unCheck = CABasicAnimation(keyPath: "strokeEnd")
|
||||||
unCheck.timingFunction = CAMediaTimingFunction(name: .linear)
|
unCheck.timingFunction = CAMediaTimingFunction(name: .linear)
|
||||||
|
unCheck.isRemovedOnCompletion = false
|
||||||
unCheck.fillMode = .both
|
unCheck.fillMode = .both
|
||||||
unCheck.duration = 0.33
|
unCheck.duration = 0.3
|
||||||
unCheck.fromValue = 0
|
unCheck.fromValue = 1
|
||||||
unCheck.toValue = 1
|
unCheck.toValue = 0
|
||||||
return unCheck
|
return unCheck
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -84,7 +104,7 @@ import MVMCore
|
|||||||
/// There is currently no intention on using xib files.
|
/// There is currently no intention on using xib files.
|
||||||
required public init?(coder aDecoder: NSCoder) {
|
required public init?(coder aDecoder: NSCoder) {
|
||||||
super.init(coder: aDecoder)
|
super.init(coder: aDecoder)
|
||||||
fatalError("xib file is not implemented for CheckBox.")
|
fatalError("xib file is not implemented for Checkbox.")
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init() {
|
public convenience init() {
|
||||||
@ -94,8 +114,8 @@ import MVMCore
|
|||||||
public convenience init(checkedColor: UIColor, unCheckedColor: UIColor, isChecked: Bool = false) {
|
public convenience init(checkedColor: UIColor, unCheckedColor: UIColor, isChecked: Bool = false) {
|
||||||
self.init(frame: .zero)
|
self.init(frame: .zero)
|
||||||
isSelected = isChecked
|
isSelected = isChecked
|
||||||
self.checkedColor = checkedColor
|
self.checkedBackgroundColor = checkedColor
|
||||||
self.unCheckedColor = unCheckedColor
|
self.unCheckedBackgroundColor = unCheckedColor
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -109,35 +129,31 @@ import MVMCore
|
|||||||
|
|
||||||
public func setupView() {
|
public func setupView() {
|
||||||
|
|
||||||
|
isUserInteractionEnabled = true
|
||||||
translatesAutoresizingMaskIntoConstraints = false
|
translatesAutoresizingMaskIntoConstraints = false
|
||||||
backgroundColor = .white
|
backgroundColor = .white
|
||||||
|
layer.borderWidth = 1
|
||||||
let path = UIBezierPath()
|
layer.borderColor = UIColor.black.cgColor
|
||||||
path.move(to: CGPoint(x: lineWidth / 2, y: bounds.size.height * 0.55))
|
|
||||||
path.addLine(to: CGPoint(x: bounds.size.width * 0.45, y: bounds.size.height * 0.85))
|
|
||||||
path.addLine(to: CGPoint(x: bounds.size.width - lineWidth / 2, y: lineWidth / 2))
|
|
||||||
|
|
||||||
let shapeLayer = CAShapeLayer()
|
|
||||||
self.shapeLayer = shapeLayer
|
|
||||||
shapeLayer.frame = bounds
|
|
||||||
layer.addSublayer(shapeLayer)
|
|
||||||
shapeLayer.strokeColor = lineColor.cgColor
|
|
||||||
shapeLayer.fillColor = UIColor.clear.cgColor
|
|
||||||
shapeLayer.path = path.cgPath
|
|
||||||
shapeLayer.lineJoin = .bevel
|
|
||||||
shapeLayer.lineWidth = lineWidth
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Action
|
// MARK: - Actions
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
open override func sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
|
open override func sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
|
||||||
print("Action initiated")
|
super.sendAction(action, to: target, for: event)
|
||||||
|
|
||||||
|
isSelected.toggle()
|
||||||
|
actionBlock?()
|
||||||
|
drawCheck()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func sendActions(for controlEvents: UIControl.Event) {
|
open override func sendActions(for controlEvents: UIControl.Event) {
|
||||||
print("Actions Inititaled")
|
super.sendActions(for: controlEvents)
|
||||||
|
|
||||||
|
isSelected.toggle()
|
||||||
|
actionBlock?()
|
||||||
|
drawCheck()
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -147,54 +163,62 @@ import MVMCore
|
|||||||
private func drawCheck() {
|
private func drawCheck() {
|
||||||
|
|
||||||
if shapeLayer == nil {
|
if shapeLayer == nil {
|
||||||
|
|
||||||
layoutIfNeeded()
|
let shapeLayer = CAShapeLayer()
|
||||||
|
self.shapeLayer = shapeLayer
|
||||||
let path = UIBezierPath()
|
shapeLayer.frame = bounds
|
||||||
path.move(to: CGPoint(x: lineWidth / 2, y: bounds.size.height * 0.55))
|
layer.addSublayer(shapeLayer)
|
||||||
path.addLine(to: CGPoint(x: bounds.size.width * 0.45, y: bounds.size.height * 0.85))
|
shapeLayer.strokeColor = lineColor.cgColor
|
||||||
path.addLine(to: CGPoint(x: bounds.size.width - lineWidth / 2, y: lineWidth / 2))
|
shapeLayer.fillColor = UIColor.clear.cgColor
|
||||||
|
shapeLayer.path = checkMarkBezierPath.cgPath
|
||||||
shapeLayer = CAShapeLayer()
|
shapeLayer.lineJoin = .bevel
|
||||||
shapeLayer?.frame = bounds
|
shapeLayer.lineWidth = lineWidth
|
||||||
layer.addSublayer(shapeLayer!)
|
|
||||||
shapeLayer?.strokeColor = lineColor.cgColor
|
CATransaction.withDisabledAnimations {
|
||||||
shapeLayer?.fillColor = UIColor.clear.cgColor
|
shapeLayer.strokeEnd = 0.0
|
||||||
shapeLayer?.path = path.cgPath
|
}
|
||||||
shapeLayer?.lineJoin = .bevel
|
|
||||||
shapeLayer?.lineWidth = lineWidth
|
|
||||||
|
|
||||||
CATransaction.begin()
|
|
||||||
CATransaction.setDisableActions(true)
|
|
||||||
shapeLayer?.strokeEnd = 0.0
|
|
||||||
CATransaction.commit()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
//Offsets based on the 124x124 example checkmark
|
// Offsets based on the 124x124 example checkmark
|
||||||
|
let startXOffset: Float = 42.0 / 124.0 ~~ 0.33871
|
||||||
let startXOffset: Float = 42.0 / 124.0
|
let startYOffset: Float = 66.0 / 124.0 ~~ 0.53225
|
||||||
let startYOffset: Float = 66.0 / 124.0
|
let pivotXOffset: Float = 58.0 / 124.0 ~~ 0.46774
|
||||||
let pivotXOffset: Float = 58.0 / 124.0
|
let pivotYOffset: Float = 80.0 / 124.0 ~~ 0.64516
|
||||||
let pivotYOffset: Float = 80.0 / 124.0
|
let endXOffset: Float = 83.0 / 124.0 ~~ 0.66935
|
||||||
let endXOffset: Float = 83.0 / 124.0
|
let endYOffset: Float = 46.0 / 124.0 ~~ 0.37097
|
||||||
let endYOffset: Float = 46.0 / 124.0
|
|
||||||
let pivotPercentage: Float = 0.34
|
let pivotPercentage: Float = 0.34
|
||||||
let endPercentage = 1.0 - pivotPercentage
|
let endPercentage = 1.0 - pivotPercentage
|
||||||
let animationInterval: Float = 0.01
|
let animationInterval: Float = 0.01
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public func updateCheckboxSelection(_ selected: Bool, animated: Bool) {
|
/// Returns a UIBezierPath detailing the path of a checkmark
|
||||||
|
var checkMarkBezierPath: UIBezierPath {
|
||||||
|
|
||||||
shapeLayer?.removeFromSuperlayer()
|
let sideLength = bounds.size.height
|
||||||
shapeLayer = nil
|
let startPoint = CGPoint(x: 0.33871 * sideLength, y: 0.53225 * sideLength)
|
||||||
|
let pivotOffSet = CGPoint(x: 0.46774 * sideLength, y: 0.64516 * sideLength)
|
||||||
|
let endOffset = CGPoint(x: 0.66935 * sideLength , y: 0.37097 * sideLength)
|
||||||
|
|
||||||
|
let path = UIBezierPath()
|
||||||
|
path.move(to: startPoint)
|
||||||
|
path.addLine(to: pivotOffSet)
|
||||||
|
path.addLine(to: endOffset)
|
||||||
|
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateSelection(_ selected: Bool, animated: Bool) {
|
||||||
|
|
||||||
|
// shapeLayer?.removeFromSuperlayer()
|
||||||
|
// shapeLayer = nil
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
|
||||||
self.isSelected = selected
|
self.isSelected = selected
|
||||||
self.drawCheck()
|
self.drawCheck()
|
||||||
|
|
||||||
var layer: CAShapeLayer?
|
var layer: CAShapeLayer?
|
||||||
if let presentation = self.shapeLayer?.presentation(), animated {
|
if let presentation = self.shapeLayer?.presentation(), animated {
|
||||||
layer = presentation
|
layer = presentation
|
||||||
@ -204,24 +228,93 @@ import MVMCore
|
|||||||
|
|
||||||
if animated {
|
if animated {
|
||||||
let animateStrokeEnd = CABasicAnimation(keyPath: "strokeEnd")
|
let animateStrokeEnd = CABasicAnimation(keyPath: "strokeEnd")
|
||||||
|
animateStrokeEnd.timingFunction = CAMediaTimingFunction(name: .linear)
|
||||||
|
animateStrokeEnd.duration = 0.33
|
||||||
animateStrokeEnd.fillMode = .both
|
animateStrokeEnd.fillMode = .both
|
||||||
animateStrokeEnd.isRemovedOnCompletion = false
|
animateStrokeEnd.isRemovedOnCompletion = false
|
||||||
animateStrokeEnd.duration = 0.33
|
|
||||||
animateStrokeEnd.fromValue = layer?.strokeEnd ?? 0
|
animateStrokeEnd.fromValue = layer?.strokeEnd ?? 0
|
||||||
animateStrokeEnd.toValue = selected ? 1 : 0
|
animateStrokeEnd.toValue = selected ? 1 : 0
|
||||||
animateStrokeEnd.timingFunction = CAMediaTimingFunction(name: .linear)
|
|
||||||
layer?.add(animateStrokeEnd, forKey: "strokeEndAnimation")
|
layer?.add(animateStrokeEnd, forKey: "strokeEndAnimation")
|
||||||
} else {
|
} else {
|
||||||
layer?.removeAllAnimations()
|
layer?.removeAllAnimations()
|
||||||
CATransaction.begin()
|
CATransaction.withDisabledAnimations {
|
||||||
CATransaction.setDisableActions(true)
|
layer?.strokeEnd = selected ? 1 : 0
|
||||||
CATransaction.setAnimationDuration(0)
|
}
|
||||||
layer?.strokeEnd = selected ? 1 : 0
|
|
||||||
CATransaction.commit()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - UITouch
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||||
|
|
||||||
|
if touchIsAcceptablyOutside(touches.first) {
|
||||||
|
sendActions(for: .touchUpOutside)
|
||||||
|
} else {
|
||||||
|
sendActions(for: .touchUpInside)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func touchIsAcceptablyOutside(_ touch: UITouch?) -> Bool {
|
||||||
|
let endLocation = touch?.location(in: self)
|
||||||
|
let x = endLocation?.x ?? 0.0
|
||||||
|
let y = endLocation?.y ?? 0.0
|
||||||
|
let faultTolerance: CGFloat = 20.0
|
||||||
|
let widthLimit = CGFloat(bounds.size.width + faultTolerance)
|
||||||
|
let heightLimt = CGFloat(bounds.size.height + faultTolerance)
|
||||||
|
|
||||||
|
return x < -faultTolerance || y < -faultTolerance || x > widthLimit || y > heightLimt
|
||||||
|
}
|
||||||
|
|
||||||
|
// if checkbox.isSelected {
|
||||||
|
// UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseOut, animations: {
|
||||||
|
// self.checkbox.backgroundColor = self.checkedColor
|
||||||
|
// })
|
||||||
|
// checkbox.updateCheckSelected(true, animated: animated)
|
||||||
|
// } else {
|
||||||
|
// UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseOut, animations: {
|
||||||
|
// self.checkbox.backgroundColor = self.unCheckedColor
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// checkbox.updateCheckSelected(false, animated: animated)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 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
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -239,6 +332,7 @@ import MVMCore
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func updateView(_ size: CGFloat) {
|
public func updateView(_ size: CGFloat) {
|
||||||
|
|
||||||
// TODO: Ensure the check logic is resized.
|
// TODO: Ensure the check logic is resized.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,15 +353,27 @@ import MVMCore
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let checkColorHex = dictionary["checkedColor"] as? String {
|
if let checkColorHex = dictionary["checkedColor"] as? String {
|
||||||
checkedColor = UIColor.mfGet(forHex: checkColorHex)
|
checkedBackgroundColor = UIColor.mfGet(forHex: checkColorHex)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let unCheckedColorHex = dictionary["unCheckedColor"] as? String {
|
if let unCheckedColorHex = dictionary["unCheckedColor"] as? String {
|
||||||
unCheckedColor = UIColor.mfGet(forHex: unCheckedColorHex)
|
unCheckedBackgroundColor = UIColor.mfGet(forHex: unCheckedColorHex)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let backroundColorHex = dictionary["backroundColor"] as? String {
|
// if let actionMap = dictionary.optionalDictionaryForKey("actionMap") {
|
||||||
backgroundColor = UIColor.mfGet(forHex: backroundColorHex)
|
// actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) }
|
||||||
}
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Move to its own extension file.
|
||||||
|
extension CATransaction {
|
||||||
|
|
||||||
|
/// Performs changes without activating animation actions.
|
||||||
|
static func withDisabledAnimations(_ actionBlock: ActionBlock) {
|
||||||
|
CATransaction.begin()
|
||||||
|
CATransaction.setDisableActions(true)
|
||||||
|
actionBlock()
|
||||||
|
CATransaction.commit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,16 +21,17 @@
|
|||||||
|
|
||||||
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 checkboxWidthConstraint: NSLayoutConstraint?
|
|
||||||
var checkboxHeightConstraint: NSLayoutConstraint?
|
|
||||||
|
|
||||||
// A block that is called when the switch is selected.
|
|
||||||
public var checkboxAction: ((_ selected: Bool) -> ())?
|
|
||||||
|
|
||||||
var isRequired = false
|
var isRequired = false
|
||||||
var fieldKey: String?
|
var fieldKey: String?
|
||||||
var delegate: DelegateObject?
|
var delegate: DelegateObject?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Constraints
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
var checkboxWidthConstraint: NSLayoutConstraint?
|
||||||
|
var checkboxHeightConstraint: NSLayoutConstraint?
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Life Cycle
|
// MARK: - Life Cycle
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -43,6 +44,7 @@
|
|||||||
translatesAutoresizingMaskIntoConstraints = false
|
translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
|
||||||
addSubview(checkbox)
|
addSubview(checkbox)
|
||||||
|
addSubview(label)
|
||||||
|
|
||||||
let dimension = sizeObject?.getValueBasedOnApplicationWidth() ?? Checkbox.defaultHeightWidth
|
let dimension = sizeObject?.getValueBasedOnApplicationWidth() ?? Checkbox.defaultHeightWidth
|
||||||
checkboxWidthConstraint = checkbox.heightAnchor.constraint(equalToConstant: dimension)
|
checkboxWidthConstraint = checkbox.heightAnchor.constraint(equalToConstant: dimension)
|
||||||
@ -50,13 +52,15 @@
|
|||||||
checkboxHeightConstraint = checkbox.widthAnchor.constraint(equalToConstant: dimension)
|
checkboxHeightConstraint = checkbox.widthAnchor.constraint(equalToConstant: dimension)
|
||||||
checkboxHeightConstraint?.isActive = true
|
checkboxHeightConstraint?.isActive = true
|
||||||
|
|
||||||
NSLayoutConstraint.constraintPinSubview(checkbox, pinTop: true, pinBottom: true, pinLeft: true, pinRight: false)
|
checkbox.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor).isActive = true
|
||||||
|
layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: checkbox.bottomAnchor).isActive = true
|
||||||
|
checkbox.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true
|
||||||
checkbox.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
|
checkbox.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
|
||||||
checkbox.lineWidth = 2.0
|
|
||||||
|
|
||||||
addSubview(label)
|
label.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor).isActive = true
|
||||||
|
layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: label.bottomAnchor).isActive = true
|
||||||
label.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
|
label.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
|
||||||
trailingAnchor.constraint(equalTo: label.trailingAnchor).isActive = true
|
layoutMarginsGuide.trailingAnchor.constraint(equalTo: label.trailingAnchor).isActive = true
|
||||||
label.leadingAnchor.constraint(equalTo: checkbox.trailingAnchor, constant: PaddingTwo).isActive = true
|
label.leadingAnchor.constraint(equalTo: checkbox.trailingAnchor, constant: PaddingTwo).isActive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,89 +86,32 @@
|
|||||||
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)
|
||||||
|
|
||||||
checkbox.checkedColor = checkedColor
|
checkbox.checkedBackgroundColor = checkedColor
|
||||||
checkbox.unCheckedColor = unCheckedColor
|
checkbox.unCheckedBackgroundColor = unCheckedColor
|
||||||
label.text = text
|
label.text = text
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(checkedColor: UIColor, unCheck unCheckedColor: UIColor, attributedText: NSAttributedString, isChecked: Bool = false) {
|
public convenience init(checkedColor: UIColor, unCheck unCheckedColor: UIColor, attributedText: NSAttributedString, isChecked: Bool = false) {
|
||||||
self.init(frame: .zero)
|
self.init(frame: .zero)
|
||||||
|
|
||||||
checkbox.checkedColor = checkedColor
|
checkbox.checkedBackgroundColor = checkedColor
|
||||||
checkbox.unCheckedColor = unCheckedColor
|
checkbox.unCheckedBackgroundColor = unCheckedColor
|
||||||
label.attributedText = attributedText
|
label.attributedText = attributedText
|
||||||
}
|
}
|
||||||
|
|
||||||
public convenience init(isRoundedCheckbox: Bool) {
|
public convenience init(isRoundedCheckbox: Bool) {
|
||||||
self.init(frame: .zero)
|
self.init(frame: .zero)
|
||||||
|
|
||||||
checkbox.hasRoundCorners = isRoundedCheckbox
|
checkbox.hasRoundCorners = isRoundedCheckbox
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
// MARK: - Methods
|
|
||||||
//--------------------------------------------------
|
|
||||||
|
|
||||||
override open class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
|
||||||
return CGFloat(Checkbox.defaultHeightWidth)
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc public func checkboxTapped(checkbox: Checkbox) {
|
|
||||||
// addAccessibilityLabel(selected)
|
|
||||||
|
|
||||||
checkbox.isSelected.toggle()
|
|
||||||
|
|
||||||
if let checkboxAction = checkboxAction {
|
|
||||||
checkboxAction(checkbox.isSelected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// if checkbox.isSelected {
|
|
||||||
// UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseOut, animations: {
|
|
||||||
// self.checkbox.backgroundColor = self.checkedColor
|
|
||||||
// })
|
|
||||||
// checkbox.updateCheckSelected(true, animated: animated)
|
|
||||||
// } else {
|
|
||||||
// UIView.animate(withDuration: 0.2, delay: 0.1, options: .curveEaseOut, animations: {
|
|
||||||
// self.checkbox.backgroundColor = self.unCheckedColor
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// checkbox.updateCheckSelected(false, animated: animated)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 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()
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
|
||||||
// MARK: - UITouch
|
|
||||||
//--------------------------------------------------
|
|
||||||
|
|
||||||
func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
|
|
||||||
|
|
||||||
if touchIsAcceptablyOutside(touches.first) {
|
|
||||||
checkbox.sendActions(for: .touchUpOutside)
|
|
||||||
} else {
|
|
||||||
checkbox.sendActions(for: .touchUpInside)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func touchIsAcceptablyOutside(_ touch: UITouch?) -> Bool {
|
|
||||||
let endLocation = touch?.location(in: self)
|
|
||||||
let x = endLocation?.x ?? 0.0
|
|
||||||
let y = endLocation?.y ?? 0.0
|
|
||||||
let faultTolerance: CGFloat = 20.0
|
|
||||||
let widthLimit = CGFloat(bounds.size.width + faultTolerance)
|
|
||||||
let heightLimt = CGFloat(bounds.size.height + faultTolerance)
|
|
||||||
|
|
||||||
return x < -faultTolerance || y < -faultTolerance || x > widthLimit || y > heightLimt
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Molecular
|
// MARK: - Molecular
|
||||||
extension CheckboxWithLabelView {
|
extension CheckboxWithLabelView {
|
||||||
|
|
||||||
|
override open class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||||
|
return CGFloat(Checkbox.defaultHeightWidth)
|
||||||
|
}
|
||||||
|
|
||||||
@objc override open func updateView(_ size: CGFloat) {
|
@objc override open func updateView(_ size: CGFloat) {
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
@ -198,8 +145,8 @@ extension CheckboxWithLabelView {
|
|||||||
self.isRequired = isRequired
|
self.isRequired = isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
checkbox.setWithJSON(dictionary.dictionaryForKey("checkbox"), delegateObject: delegateObject, additionalData: additionalData)
|
||||||
label.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
label.setWithJSON(dictionary.dictionaryForKey("label"), delegateObject: delegateObject, additionalData: additionalData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user