Grooming process in converting objc to swift with Switch.
This commit is contained in:
parent
8a796467e6
commit
a00fdbad60
@ -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<UITouch>, with event: UIEvent) {
|
||||
|
||||
thumbEnlargeAnimation()
|
||||
sendActions(for: .touchDown)
|
||||
}
|
||||
|
||||
public func touchesEnded(_ touches: Set<UITouch>, 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<UITouch>, 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<UITouch>, with event: UIEvent) {
|
||||
knobEnlargeAnimation()
|
||||
sendActions(for: .touchDown)
|
||||
}
|
||||
|
||||
public func touchesEnded(_ touches: Set<UITouch>, 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<UITouch>, 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<UITouch>, 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<AnyObject>.formValidatorModel)) {
|
||||
let formValidator = delegate.perform(#selector(formValidationProtocol)).perform(#selector(Unmanaged<AnyObject>.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<UITouch>, 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<AnyObject>.formValidatorModel)) {
|
||||
let formValidator = delegate.perform(#selector(formValidationProtocol)).perform(#selector(Unmanaged<AnyObject>.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<UITouch>?) -> 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<UITouch>?) -> 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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user