Files
2022-09-23 21:35:57 +03:00

185 lines
6.7 KiB
Swift

//
// 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)
}
}