diff --git a/MVMCoreUI/Atoms/Views/Switch.swift b/MVMCoreUI/Atoms/Views/Switch.swift index d7e9b25e..e12fd890 100644 --- a/MVMCoreUI/Atoms/Views/Switch.swift +++ b/MVMCoreUI/Atoms/Views/Switch.swift @@ -10,367 +10,464 @@ import MVMCore import MVMCoreUI import UIKit -typealias ValueChangeBlock = () -> Void +typealias ValueChangeBlock = () -> () -open class Switch: UIControl, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol, FormValidationFormFieldProtocol { - var on = false - var onTintColor: UIColor? - var offTintColor: UIColor? - var onKnobTintColor: UIColor? - var offKnobTintColor: UIColor? +open class Switch: Control, MVMCoreViewProtocol, MVMCoreUIViewConstrainingProtocol, FormValidationFormFieldProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public var isOn = false + public var trackTintColor: (on: UIColor?, off: UIColor?)? + public var thumbTintColor: (on: UIColor?, off: UIColor?)? + var shouldTouchToSwitch = false var valueChangedBlock: ValueChangeBlock? var actionBlock: ValueChangeBlock? - let SwitchWidth: CGFloat = 42 - let SwitchHeight: CGFloat = 22 - let SwitchKnobWidth: CGFloat = 20 - let SwitchKnobHeight: CGFloat = 20 - let SwitchShakeIntensity: CGFloat = 2 + static let width: CGFloat = 42 + static let height: CGFloat = 22 + static let thumbWidth: CGFloat = 20 + static let thumbHeight: CGFloat = 20 + static let shakeIntensity: CGFloat = 2 private weak var baseView: UIView? - private weak var knobView: UIView? - private var knobLeftConstraint: NSLayoutConstraint? - private var knobRightConstraint: NSLayoutConstraint? - private var knobHeightConstraint: NSLayoutConstraint? - private var knobWidthConstraint: NSLayoutConstraint? - private weak var height: NSLayoutConstraint? - private weak var width: NSLayoutConstraint? + private weak var thumbView: UIView? + private var valueShouldChange = false private var canChangeValue = false - private var json: [AnyHashable: Any]? + + //-------------------------------------------------- + // MARK: - Delegate + //-------------------------------------------------- + private var delegate: DelegateObject? + //-------------------------------------------------- + // MARK: - Constraints + //-------------------------------------------------- + + private var thumbLeftConstraint: NSLayoutConstraint? + private var thumbRightConstraint: NSLayoutConstraint? + private var thumbHeightConstraint: NSLayoutConstraint? + private var thumbWidthConstraint: NSLayoutConstraint? + private weak var height: NSLayoutConstraint? + private weak var width: NSLayoutConstraint? + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + public func updateView(_ size: CGFloat) { + height?.constant = MVMCoreUISwitch.getHeight() width?.constant = MVMCoreUISwitch.getWidth() baseView?.layer.cornerRadius = MVMCoreUISwitch.getHeight() / 2.0 - knobView?.layer.cornerRadius = MVMCoreUISwitch.getKnobHeight() * 0.5 - knobHeightConstraint?.constant = MVMCoreUISwitch.getKnobHeight() - knobWidthConstraint?.constant = MVMCoreUISwitch.getKnobWidth() + thumbView?.layer.cornerRadius = MVMCoreUISwitch.getthumbHeight() * 0.5 + thumbHeightConstraint?.constant = MVMCoreUISwitch.getthumbHeight() + thumbWidthConstraint?.constant = MVMCoreUISwitch.getthumbWidth() } public func setupView() { - onTintColor = UIColor.mfSwitchOnTint() - offTintColor = UIColor.mfSwitchOffTint() + + trackTintColor?.on = .mfSwitchOnTint() + trackTintColor?.off = .mfSwitchOffTint() canChangeValue = true shouldTouchToSwitch = true - setUpViewWithState(on) - accessibilityLabel() = MVMCoreUIUtility.hardcodedString(withKey: "MVMCoreUISwitch_buttonlabel") + setUpViewWithState(isOn) + accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "MVMCoreUISwitch_buttonlabel") + } + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + + public override init(frame: CGRect) { + super.init(frame: frame) + setupView() + } + + public convenience init() { + self.init(frame: frame) } public required init?(coder: NSCoder) { - if super.init(coder: coder) != nil { - setupView() - } + super.init(coder: coder) + fatalError("Switch does not support xib") } - public init(frame: CGRect) { - if super.init(frame: frame) != nil { - setupView() - } - } - - public init() { - if super.init() { - setupView() - } - } + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- public class func mvmSwitchDefault() -> Self { - let mySwitch = self.init(frame: CGRect.zero) + + let mySwitch = self.init(frame: .zero) mySwitch?.translatesAutoresizingMaskIntoConstraints = false return mySwitch } public class func mvmSwitchDefault(with block: ValueChangeBlock?) -> Self { - let mySwitch = self.init(frame: CGRect.zero) + + let mySwitch = self.init(frame: .zero) mySwitch?.valueChangedBlock = block return mySwitch } public func setUpViewWithState(_ on: Bool) { - if !self.baseView { - isUserInteractionEnabled = true - valueShouldChange = true - - let baseView = MVMCoreUICommonViewsUtility.commonView() - if let baseView = baseView { - addSubview(baseView) - } - NSLayoutConstraint.constraintPinSubview(toSuperview: baseView) - let constraints = NSLayoutConstraint.constraintPinView(baseView, heightConstraint: true, heightConstant: MVMCoreUISwitch.getHeight(), widthConstraint: true, widthConstant: MVMCoreUISwitch.getWidth()) - self.height = constraints.object(forKey: ConstraintHeight, ofType: NSLayoutConstraint.self) - self.width = constraints.object(forKey: ConstraintWidth, ofType: NSLayoutConstraint.self) - baseView?.layer.cornerRadius = MVMCoreUISwitch.getHeight() / 2.0 - - onKnobTintColor = UIColor.white - offKnobTintColor = UIColor.white - - let knobView = MVMCoreUICommonViewsUtility.commonView() - knobView?.backgroundColor = UIColor.white - knobView?.layer.cornerRadius = MVMCoreUISwitch.getKnobHeight() * 0.5 - if let knobView = knobView { - baseView?.addSubview(knobView) - } - let heightWidth = NSLayoutConstraint.constraintPinView(knobView, heightConstraint: true, heightConstant: MVMCoreUISwitch.getKnobHeight(), widthConstraint: true, widthConstant: MVMCoreUISwitch.getKnobWidth()) - let height = heightWidth.object(forKey: ConstraintHeight, ofType: NSLayoutConstraint.self) - let width = heightWidth.object(forKey: ConstraintWidth, ofType: NSLayoutConstraint.self) - knobHeightConstraint = height - knobWidthConstraint = width - let leadingTrailingDic = NSLayoutConstraint.constraintPinSubview(knobView, pinTop: false, topConstant: 0, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 1, pinRight: true, rightConstant: 1) - - let leadingTrailingDic = NSLayoutConstraint.constraintPinSubview(knobView, pinTop: false, topConstant: 0, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 1, pinRight: true, rightConstant: 1) - let `left` = leadingTrailingDic.object(forKey: ConstraintLeading, ofType: NSLayoutConstraint.self) - let `right` = leadingTrailingDic.object(forKey: ConstraintTrailing, ofType: NSLayoutConstraint.self) - NSLayoutConstraint.constraintPinSubview(knobView, pinCenterX: false, centerXConstant: 0, pinCenterY: true, centerYConstant: 0) - `right`?.constant = 15 - knobLeftConstraint = `left` - knobRightConstraint = `right` - baseView.bringSubviewToFront(knobView) - - //baseView = baseView // Skipping redundant initializing to itself - //knobView = knobView // Skipping redundant initializing to itself - - baseView.isUserInteractionEnabled = false - knobView.isUserInteractionEnabled = false - shouldTouchToSwitch = false - setState(on, animated: false) - shouldTouchToSwitch = true + + guard baseView == nil else { return } + + isUserInteractionEnabled = true + valueShouldChange = true + + let baseView = MVMCoreUICommonViewsUtility.commonView() + + if let baseView = baseView { + addSubview(baseView) } - // MARK: - MVMCoreUIMoleculeViewProtocol - public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { - self.json = json - delegate = delegateObject - - FormValidator.setupValidation(withMolecule: self, delegate: delegateObject?.formValidationProtocol) - - var color = json?.string("onTintColor") - if color != nil { - onTintColor = UIColor.mfGet(forHex: color) - } - - color = json?.string("offTintColor") - if color != nil { - offTintColor = UIColor.mfGet(forHex: color) - } - - color = json?.string("onKnobTintColor") - if color != nil { - onKnobTintColor = UIColor.mfGet(forHex: color) - } - - color = json?.string("offKnobTintColor") - if color != nil { - offKnobTintColor = UIColor.mfGet(forHex: color) - } - - setState(json?.bool(forKey: "state"), animated: false) - - let actionMap = json?.dict("actionMap") - if actionMap != nil { - addTarget(self, action: #selector(addCustomAction), for: .touchUpInside) - } + NSLayoutConstraint.constraintPinSubview(toSuperview: baseView) + let constraints = NSLayoutConstraint.constraintPinView(baseView, heightConstraint: true, heightConstant: MVMCoreUISwitch.getHeight(), widthConstraint: true, widthConstant: MVMCoreUISwitch.getWidth()) + self.height = constraints.object(forKey: ConstraintHeight, ofType: NSLayoutConstraint.self) + self.width = constraints.object(forKey: ConstraintWidth, ofType: NSLayoutConstraint.self) + baseView?.layer.cornerRadius = MVMCoreUISwitch.getHeight() / 2.0 + + onthumbTintColor = UIColor.white + offthumbTintColor = UIColor.white + + let thumbView = MVMCoreUICommonViewsUtility.commonView() + thumbView?.backgroundColor = UIColor.white + thumbView?.layer.cornerRadius = MVMCoreUISwitch.getthumbHeight() * 0.5 + + if let thumbView = thumbView { + baseView?.addSubview(thumbView) } - public @objc func addCustomAction() { - if actionBlock { - actionBlock() - } + let heightWidth = NSLayoutConstraint.constraintPinView(thumbView, heightConstraint: true, heightConstant: MVMCoreUISwitch.getthumbHeight(), widthConstraint: true, widthConstant: MVMCoreUISwitch.getthumbWidth()) + let height = heightWidth.object(forKey: ConstraintHeight, ofType: NSLayoutConstraint.self) + let width = heightWidth.object(forKey: ConstraintWidth, ofType: NSLayoutConstraint.self) + thumbHeightConstraint = height + thumbWidthConstraint = width + let leadingTrailingDic = NSLayoutConstraint.constraintPinSubview(thumbView, pinTop: false, topConstant: 0, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 1, pinRight: true, rightConstant: 1) + + let leadingTrailingDic = NSLayoutConstraint.constraintPinSubview(thumbView, pinTop: false, topConstant: 0, pinBottom: false, bottomConstant: 0, pinLeft: true, leftConstant: 1, pinRight: true, rightConstant: 1) + let `left` = leadingTrailingDic.object(forKey: ConstraintLeading, ofType: NSLayoutConstraint.self) + let `right` = leadingTrailingDic.object(forKey: ConstraintTrailing, ofType: NSLayoutConstraint.self) + NSLayoutConstraint.constraintPinSubview(thumbView, pinCenterX: false, centerXConstant: 0, pinCenterY: true, centerYConstant: 0) + `right`?.constant = 15 + thumbLeftConstraint = `left` + thumbRightConstraint = `right` + baseView.bringSubviewToFront(thumbView) + + //baseView = baseView // Skipping redundant initializing to itself + //thumbView = thumbView // Skipping redundant initializing to itself + + baseView.isUserInteractionEnabled = false + thumbView.isUserInteractionEnabled = false + shouldTouchToSwitch = false + setState(on, animated: false) + shouldTouchToSwitch = true + } + + @objc func addCustomAction() { + + actionBlock?() + } + + public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + + return Switch.getSwitchHeight() + } + + // MARK: - UIResponder overide + public func touchesBegan(_ touches: Set, with event: UIEvent) { + + thumbEnlargeAnimation() + sendActions(for: .touchDown) + } + + public func touchesEnded(_ touches: Set, with event: UIEvent) { + + if shouldTouchToSwitch && valueShouldChange{ + changeValue() } - public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - return self.getSwitchHeight() - } + sendActions(for: .touchUpInside) + thumbMoveAnitmationTo(on: isOn) + thumbShakeAnitmationTo(on: isOn) + thumbReformAnimation(true) + valueShouldChange = true + } + + public func touchesMoved(_ touches: Set, with event: UIEvent) { - // MARK: - MVMCoreUIMoleculeViewProtocol - public func needsToBeConstrained() -> Bool { - return true - } - - public func alignment() -> UIStackView.Alignment { - return .trailing - } - - // MARK: - UIResponder overide - public func touchesBegan(_ touches: Set, with event: UIEvent) { - knobEnlargeAnimation() - sendActions(for: .touchDown) - } - - public func touchesEnded(_ touches: Set, with event: UIEvent) { - if shouldTouchToSwitch { - if valueShouldChange { - changeValue() - } - } - sendActions(for: .touchUpInside) - knobMoveAnitmationTo(on: isOn) - knobShakeAnitmationTo(on: isOn) - knobReformAnimation(true) - valueShouldChange = true - } - - public func touchesMoved(_ touches: Set, with event: UIEvent) { - if shouldTouchToSwitch { - if touchMoves(toLeft: touches) { - knobMoveAnitmationTo(on: false) - knobShakeAnitmationTo(on: false) - knobReformAnimation(true) - } else { - knobMoveAnitmationTo(on: true) - knobShakeAnitmationTo(on: true) - knobReformAnimation(true) - } - } - if touchIsOutSide(touches) { - sendActions(for: .touchDragOutside) - if !shouldTouchToSwitch { - knobReformAnimation(true) - } + if shouldTouchToSwitch { + if touchMoves(toLeft: touches) { + thumbMoveAnitmationTo(on: false) + thumbShakeAnitmationTo(on: false) + thumbReformAnimation(true) } else { - sendActions(for: .touchDragInside) + thumbMoveAnitmationTo(on: true) + thumbShakeAnitmationTo(on: true) + thumbReformAnimation(true) } } - public func touchesCancelled(_ touches: Set, with event: UIEvent) { - if shouldTouchToSwitch { - knobReformAnimation(true) - canChangeValue = true - } - sendActions(for: .touchCancel) - } - - // MARK: - animation - public func knobEnlargeAnimation() { - UIView.animate(withDuration: 0.1, animations: { - self.knobWidthConstraint.constant += PaddingOne - self.layoutIfNeeded() - }) - } - - public func knobReformAnimation(_ animated: Bool) { - if animated { - UIView.animate(withDuration: 0.1, animations: { - self.knobWidthConstraint.constant = MVMCoreUISwitch.getKnobWidth() - self.layoutIfNeeded() - }) { finished in - } - } else { - knobWidthConstraint.constant = MVMCoreUISwitch.getKnobWidth() - layoutIfNeeded() - } - } - - public func knobMoveAnitmationTo(on toOn: Bool) { - UIView.animate(withDuration: 0.1, animations: { - if toOn { - self.knobLeftConstraint.priority = 1 - self.knobRightConstraint.priority = 999 - self.knobRightConstraint.constant = 1 - } else { - self.knobLeftConstraint.priority = 999 - self.knobRightConstraint.priority = 1 - self.knobLeftConstraint.constant = 1 - } - self.setBaseColorToOn(toOn, animated: true) - self.knobWidthConstraint.constant = MVMCoreUISwitch.getKnobWidth() + PaddingOne - self.valueShouldChange = toOn != self.on - self.layoutIfNeeded() - }) - } - - public func setBaseColorToOn(_ toOn: Bool, animated: Bool) { - if animated { - UIView.beginAnimations(nil, context: nil) - UIView.setAnimationDuration(0.2) - UIView.setAnimationCurve(.easeIn) - if toOn { - knobView.backgroundColor = onKnobTintColor - baseView.backgroundColor = onTintColor - } else { - knobView.backgroundColor = offKnobTintColor - baseView.backgroundColor = offTintColor - } - UIView.commitAnimations() - } else if on { - knobView.backgroundColor = onKnobTintColor - baseView.backgroundColor = onTintColor - } else { - knobView.backgroundColor = offKnobTintColor - baseView.backgroundColor = offTintColor - } - } - - //used after knob moving to match the behavior of default uiswitch - public func knobShakeAnitmationTo(on toOn: Bool) { - UIView.animate(withDuration: 0.1, delay: 0.1, options: .curveEaseIn, animations: { - if toOn { - self.knobRightConstraint.constant = SwitchShakeIntensity - } else { - self.knobLeftConstraint.constant = SwitchShakeIntensity - } - self.layoutIfNeeded() - }) { finished in - } - UIView.animate(withDuration: 0.2, delay: 0.1, options: [], animations: { - if toOn { - self.knobRightConstraint.constant = 1 - } else { - self.knobLeftConstraint.constant = 1 - } - self.layoutIfNeeded() - }) { finished in - self.valueShouldChange = true - } - } - - // MARK: - switch logic - public func setState(_ state: Bool, animated: Bool) { - setState(state, withoutBlockAnimated: animated) - if valueChangedBlock { - valueChangedBlock() - } - - if delegate && delegate.responds(to: #selector(formValidationProtocol)) && delegate.perform(#selector(formValidationProtocol)).responds(to: #selector(Unmanaged.formValidatorModel)) { - let formValidator = delegate.perform(#selector(formValidationProtocol)).perform(#selector(Unmanaged.formValidatorModel)) as? FormValidator - formValidator?.enableByValidation() - } - } - - public func setState(_ state: Bool, withoutBlockAnimated animated: Bool) { - on = state + if touchIsOutSide(touches) { + sendActions(for: .touchDragOutside) if !shouldTouchToSwitch { - knobEnlargeAnimation() - knobMoveAnitmationTo(on: on) - knobShakeAnitmationTo(on: on) + thumbReformAnimation(true) } - if on { - knobLeftConstraint.priority = 1 - knobRightConstraint.priority = 999 - knobRightConstraint.constant = 1 - } else { - knobRightConstraint.priority = 1 - knobLeftConstraint.priority = 999 - knobLeftConstraint.constant = 1 + } else { + sendActions(for: .touchDragInside) + } + } + + public func touchesCancelled(_ touches: Set, with event: UIEvent) { + + if shouldTouchToSwitch { + thumbReformAnimation(true) + canChangeValue = true + } + + sendActions(for: .touchCancel) + } + + // MARK: - animation + public func thumbEnlargeAnimation() { + + UIView.animate(withDuration: 0.1, animations: { + self.thumbWidthConstraint?.constant += PaddingOne + self.layoutIfNeeded() + }) + } + + public func thumbReformAnimation(_ animated: Bool) { + + if animated { + UIView.animate(withDuration: 0.1, animations: { + self.thumbWidthConstraint?.constant = MVMCoreUISwitch.getthumbWidth() + self.layoutIfNeeded() + }) { finished in } - - setBaseColorToOn(on, animated: animated) - knobReformAnimation(animated) - accessibilityValue = state ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") - setNeedsLayout() + } else { + thumbWidthConstraint?.constant = MVMCoreUISwitch.getthumbWidth() layoutIfNeeded() } + } + + public func thumbMoveAnitmationTo(on toOn: Bool) { - public func changeValue() -> Bool { - on ^= true - shouldTouchToSwitch = false - setState(on, animated: true) - shouldTouchToSwitch = true - sendActions(for: .valueChanged) - return on + UIView.animate(withDuration: 0.1, animations: { + if toOn { + self.thumbLeftConstraint?.priority = UILayoutPriority(1) + self.thumbRightConstraint?.priority = UILayoutPriority(999) + self.thumbRightConstraint?.constant = 1 + } else { + self.thumbLeftConstraint?.priority = UILayoutPriority(999) + self.thumbRightConstraint?.priority = UILayoutPriority(1) + self.thumbLeftConstraint?.constant = 1 + } + self.setBaseColorToOn(toOn, animated: true) + self.thumbWidthConstraint?.constant = MVMCoreUISwitch.getThumbWidth() + PaddingOne + self.valueShouldChange = toOn != self.isOn + self.layoutIfNeeded() + }) + } + + public func setBaseColorToOn(_ toOn: Bool, animated: Bool) { + + if animated { + UIView.beginAnimations(nil, context: nil) + UIView.setAnimationDuration(0.2) + UIView.setAnimationCurve(.easeIn) + + if toOn { + thumbView?.backgroundColor = thumbTintColor!.on + baseView?.backgroundColor = trackTintColor!.on + } else { + thumbView?.backgroundColor = thumbTintColor!.off + baseView?.backgroundColor = trackTintColor!.off + } + UIView.commitAnimations() + } else if isOn { + thumbView?.backgroundColor = thumbTintColor!.on + baseView?.backgroundColor = trackTintColor!.on + } else { + thumbView?.backgroundColor = thumbTintColor!.off + baseView?.backgroundColor = trackTintColor!.off } } + + //used after thumb moving to match the behavior of default uiswitch + public func thumbShakeAnitmationTo(on toOn: Bool) { + UIView.animate(withDuration: 0.1, delay: 0.1, options: .curveEaseIn, animations: { + if toOn { + self.thumbRightConstraint?.constant = Switch.shakeIntensity + } else { + self.thumbLeftConstraint?.constant = Switch.shakeIntensity + } + self.layoutIfNeeded() + }) { finished in + } + UIView.animate(withDuration: 0.2, delay: 0.1, options: [], animations: { + if toOn { + self.thumbRightConstraint?.constant = 1 + } else { + self.thumbLeftConstraint?.constant = 1 + } + self.layoutIfNeeded() + }) { finished in + self.valueShouldChange = true + } + } + + public func setState(_ state: Bool, animated: Bool) { + setState(state, withoutBlockAnimated: animated) + + valueChangedBlock?() + + if delegate && delegate.responds(to: #selector(formValidationProtocol)) && delegate.perform(#selector(formValidationProtocol)).responds(to: #selector(Unmanaged.formValidatorModel)) { + let formValidator = delegate.perform(#selector(formValidationProtocol)).perform(#selector(Unmanaged.formValidatorModel)) as? FormValidator + formValidator?.enableByValidation() + } + } + + public func setState(_ state: Bool, withoutBlockAnimated animated: Bool) { + + isOn = state + + if !shouldTouchToSwitch { + thumbEnlargeAnimation() + thumbMoveAnitmationTo(on: isOn) + thumbShakeAnitmationTo(on: isOn) + } + + if isOn { + thumbLeftConstraint?.priority = UILayoutPriority(1) + thumbRightConstraint?.priority = UILayoutPriority(999) + thumbRightConstraint?.constant = 1 + } else { + thumbRightConstraint?.priority = UILayoutPriority(1) + thumbLeftConstraint?.priority = UILayoutPriority(999) + thumbLeftConstraint?.constant = 1 + } + + setBaseColorToOn(isOn, animated: animated) + thumbReformAnimation(animated) + accessibilityValue = state ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") + setNeedsLayout() + layoutIfNeeded() + } + + public func changeValue() -> Bool { + isOn ^= true + shouldTouchToSwitch = false + setState(isOn, animated: true) + shouldTouchToSwitch = true + sendActions(for: .valueChanged) + return isOn + } + + + // MARK: - helper + func touchIsOutSide(_ touches: Set?) -> Bool { + + let location = touches?.first?.location(in: self) + let x = Float(location?.x ?? 0.0) + let y = Float(location?.y ?? 0.0) + return x < 0 || x > frame.size.width || y < 0 || y > frame.size.height + } + + func touchMoves(toLeft touches: Set?) -> Bool { + + let location = touches?.first?.location(in: self) + let x = Float(location?.x ?? 0.0) + return x < frame.size.width / 2.0 + } + + class func getSwitchWidth() -> CGFloat { + return (MFSizeObject(standardSize: Switch.width, standardiPadPortraitSize: Double(SwitchWidth) * 1.5)).getValueBasedOnApplicationWidth() + } + + class func getSwitchHeight() -> CGFloat { + return (MFSizeObject(standardSize: Switch.height, standardiPadPortraitSize: Double(SwitchHeight) * 1.5)).getValueBasedOnApplicationWidth() + } + + class func getSwitchthumbWidth() -> CGFloat { + return (MFSizeObject(standardSize: Switch.thumbWidth, standardiPadPortraitSize: Double(SwitchthumbWidth) * 1.5)).getValueBasedOnApplicationWidth() + } + + class func getSwitchthumbHeight() -> CGFloat { + return (MFSizeObject(standardSize: Switch.thumbHeight, standardiPadPortraitSize: Double(SwitchthumbHeight) * 1.5)).getValueBasedOnApplicationWidth() + } } +// MARK: - Accessibility +extension Switch { + + func formFieldGroupName() -> String? { + return json.string("groupName") + } +} + +// MARK: FormValidationProtocol +extension Switch { + + func isValidField() -> Bool { + return isOn && json.bool(forKey: "required") + } + + func formFieldName() -> String? { + return json.string(KeyFieldKey) + } + + func formFieldValue() -> Any? { + return NSNumber(value: isOn) + } +} + +// MARK: - MVMCoreUIMoleculeViewProtocol +extension Switch: MVMCoreUIMoleculeViewProtocol { + + public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + self.json = json + delegate = delegateObject + + guard let dictionary = json else { return } + + FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) + + if let color = dictionary["onTintColor"] as? String { + trackTintColor?.on = UIColor.mfGet(forHex: color) + } + + if let color = dictionary["offTintColor"] as? String { + trackTintColor?.off = UIColor.mfGet(forHex: color) + } + + if let color = dictionary["onthumbTintColor"] as? String { + thumbTintColor?.on = UIColor.mfGet(forHex: color) + } + + if let color = dictionary["offthumbTintColor"] as? String { + thumbTintColor?.off = UIColor.mfGet(forHex: color) + } + + setState(json?.bool(forKey: "state"), animated: false) + + let actionMap = json?.dict("actionMap") + if actionMap != nil { + addTarget(self, action: #selector(addCustomAction), for: .touchUpInside) + } + } + + public func needsToBeConstrained() -> Bool { + return true + } + + public func alignment() -> UIStackView.Alignment { + return .trailing + } +} diff --git a/MVMCoreUI/BaseClasses/Control.swift b/MVMCoreUI/BaseClasses/Control.swift index fdf8204f..e1690306 100644 --- a/MVMCoreUI/BaseClasses/Control.swift +++ b/MVMCoreUI/BaseClasses/Control.swift @@ -9,6 +9,7 @@ import UIKit public class Control: UIControl { + var json: [AnyHashable: Any]? private var initialSetupPerformed = false @@ -37,8 +38,8 @@ public class Control: UIControl { } extension Control: MVMCoreViewProtocol { - public func updateView(_ size: CGFloat) { - } + + public func updateView(_ size: CGFloat) { } /// Will be called only once. public func setupView() {