// // CommonSwitch.swift // Wallet // // Created by Igor on 11.02.2021. // Copyright © 2021 AM. All rights reserved. // import UIKit class CommonSwitch: CommonControlCustom { @IBOutlet private weak var actionBtn: UIButton! @IBOutlet private weak var backBtn: UIButton! @IBOutlet private weak var backPosition: NSLayoutConstraint! @IBOutlet private weak var frontBtn: UIButton! @IBOutlet private weak var frontPosition: NSLayoutConstraint! @IBOutlet private weak var frontHeight: NSLayoutConstraint! private var switchWidth: NSLayoutConstraint! @IBInspectable var cornerRadius: CGFloat = 10 { didSet { updateContent() } } private var _isSelected: Bool = false override open var isSelected: Bool { get { _isSelected } set { set(isSelected: newValue, animated: false) } } func set(isSelected: Bool, animated: Bool) { guard _isSelected != isSelected else { return } _isSelected = isSelected update(animated: animated) } @IBInspectable var frontInset: CGFloat = 0 { didSet { updateContent() } } @IBInspectable var isLight: Bool = false { didSet { updateContent() } } @IBInspectable var isActive: Bool = false { didSet { updateContent() } } @IBInspectable var imageBack: UIImage? { didSet { updateContent() } } @IBInspectable var lzTextBack: String? { didSet { updateContent() } } @IBInspectable var imageBackSelected: UIImage? { didSet { updateContent() } } @IBInspectable var lzTextBackSelected: String? { didSet { updateContent() } } @IBInspectable var imageFront: UIImage? { didSet { updateContent() } } @IBInspectable var lzTextFront: String? { didSet { updateContent() } } @IBInspectable var imageFrontSelected: UIImage? { didSet { updateContent() } } @IBInspectable var lzTextFrontSelected: String? { didSet { updateContent() } } @IBInspectable var canChange: Bool = true func toggle(animated: Bool = true) { _isSelected = !isSelected update(animated: animated) } private func updateContent() { if isActive { backgroundColor = isLight ? Asset.marble.color : Asset.deepWater.color } else { backgroundColor = Asset.disabled.color } layer.cornerRadius = cornerRadius backBtn.contentEdgeInsets = .init(top: 0, left: 8, bottom: 0, right: 8) frontBtn.contentEdgeInsets = .init(top: 0, left: 8, bottom: 0, right: 8) frontBtn.backgroundColor = isLight ? Asset.deepWater.color : Asset.snow.color frontBtn.layer.cornerRadius = cornerRadius - frontInset frontBtn.clipsToBounds = true frontBtn.contentEdgeInsets = .init(top: 0, left: 4, bottom: 0, right: 4) frontHeight.constant = frame.size.height - frontInset*2 self.isUserInteractionEnabled = isActive self.isEnabled = isActive layoutIfNeeded() update(animated: false) } private func update(animated: Bool) { backPosition.constant = 0 frontPosition.constant = 0 if animated { UIView.animate(withDuration: Animation.fastest) { self.layoutIfNeeded() } completion: { _ in self.updateComplete(animated: true) } } else { updateComplete(animated: false) } } override func layoutSubviews() { super.layoutSubviews() if switchWidth != nil, widthConstraint() != nil { updateComplete(animated: true) } } private func widthConstraint() -> NSLayoutConstraint? { constraints.filter({ NSStringFromClass($0.classForCoder) != "NSAutoresizingMaskLayoutConstraint" && $0.firstAttribute == .width && $0.priority.rawValue >= (switchWidth?.priority.rawValue ?? 0) && $0 != switchWidth }).first } private func updateComplete(animated: Bool) { let backTextColor = isLight ? Asset.textGranite.color : Asset.textSnow.color let frontTextColor = isLight ? Asset.textSnow.color : Asset.textGranite.color backBtn.setImage(isSelected ? imageBackSelected : imageBack, for: .normal) backBtn.setAttributedTitle( (isSelected ? lzTextBackSelected : lzTextBack)?.localized.attributed(style: .medium, size: 14, color: backTextColor), for: .normal ) if backBtn.image(for: .normal) != nil, backBtn.attributedTitle(for: .normal) != nil { backBtn.titleEdgeInsets = .init(top: 0, left: 4, bottom: 0, right: 0) backBtn.imageEdgeInsets = .init(top: 0, left: 0, bottom: 0, right: 4) } else { backBtn.titleEdgeInsets = .zero backBtn.imageEdgeInsets = .zero } frontBtn.setImage(isSelected ? imageFrontSelected : imageFront, for: .normal) frontBtn.setAttributedTitle( (isSelected ? lzTextFrontSelected : lzTextFront)?.localized.attributed(style: .medium, size: 14, color: frontTextColor), for: .normal ) if frontBtn.image(for: .normal) != nil, frontBtn.attributedTitle(for: .normal) != nil { frontBtn.titleEdgeInsets = .init(top: 0, left: 4, bottom: 0, right: 0) frontBtn.imageEdgeInsets = .init(top: 0, left: 0, bottom: 0, right: 4) } else { frontBtn.titleEdgeInsets = .zero frontBtn.imageEdgeInsets = .zero } if let constraint = widthConstraint(), switchWidth != nil { removeConstraint(switchWidth) switchWidth = constraint } layoutIfNeeded() let width = backBtn.frame.width + frontBtn.frame.width + frontInset*2 if switchWidth == nil { switchWidth = widthConstraint() ?? widthAnchor.constraint(equalToConstant: width) switchWidth.isActive = true } switchWidth.constant = width backPosition.constant = (isSelected ? -width + backBtn.frame.width : width - backBtn.frame.width)/2 frontPosition.constant = (isSelected ? width - frontBtn.frame.width - frontInset*2 : -width + frontBtn.frame.width + frontInset*2)/2 frontHeight.constant = frame.height - frontInset*2 animated ? UIView.animate(withDuration: Animation.fastest) { self.layoutIfNeeded() } : layoutIfNeeded() } @IBAction func onChangeState(_: AnyObject?) { frontBtn.isHighlighted = actionBtn.isHighlighted } @IBAction func onToggle(_: AnyObject?) { frontBtn.isHighlighted = actionBtn.isHighlighted if canChange { toggle(animated: true) } sendActions(for: .valueChanged) } }