-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathConnectButton+SwitchControl.swift
107 lines (84 loc) · 4.22 KB
/
ConnectButton+SwitchControl.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//
// ConnectButton+SwitchControl.swift
// IFTTT SDK
//
// Copyright © 2019 IFTTT. All rights reserved.
//
import UIKit
extension ConnectButton {
/// A `UIView` subclass composed of a knob and track that represents the switch of the connect button.
final class SwitchControl: UIView {
/// A `PillView` subclass that adds an icon image view to represent the circular switch of the connect button.
final class Knob: PillView {
/// A `UIImageView` to display an icon on the knob.
let iconView = UIImageView()
override init() {
super.init()
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.16
layer.shadowRadius = 6
layer.shadowOffset = CGSize(width: 0, height: 3)
addSubview(iconView)
iconView.constrain.center(in: self)
iconView.constrain.square(length: Layout.serviceIconDiameter)
}
}
/// Whether the connect button's switch is on or not.
var isOn: Bool = false {
didSet {
centerKnobConstraint.isActive = false
offConstraint.isActive = !isOn
track.layoutIfNeeded()
}
}
/// Configures the knob with the service coloring and fetches the service's associated icon.
///
/// - Parameters:
/// - service: The `Service` model to used to configure the styling of the knob.
/// - networkController: An optional `ImageViewNetworkController` for fetching the service's icon.
/// - trackColor: The color of the track to use in determining what color to make the knob color.
func configure(with service: Service, networkController: ImageViewNetworkController?, trackColor: UIColor) {
networkController?.setImage(with: service.iconURL, for: knob.iconView)
let color = service.brandColor
// If the B component of the knob color is too close to the track color, set the background color to be a contrasting version of the color
if color.distance(from: trackColor, comparing: .b) < 0.2 {
knob.backgroundColor = color.contrasting(brighteningAdjustment: 0.25)
} else {
knob.backgroundColor = color
}
}
/// The connect button's circular switch.
let knob = Knob()
private let track = PassthroughView()
/// Used to prime particular button animations where the know should start in the center
func primeAnimation_centerKnob() {
UIView.performWithoutAnimation {
self.offConstraint.isActive = false
self.centerKnobConstraint.isActive = true
self.layoutIfNeeded()
}
}
private var centerKnobConstraint: NSLayoutConstraint!
private var offConstraint: NSLayoutConstraint!
/// Creates a `SwitchControl`.
init() {
super.init(frame: .zero)
addSubview(track)
track.addSubview(knob)
track.constrain.edges(to: self)
knob.constrain.square(length: Layout.knobDiameter)
knob.centerYAnchor.constraint(equalTo: track.centerYAnchor).isActive = true
centerKnobConstraint = knob.centerXAnchor.constraint(equalTo: track.centerXAnchor)
centerKnobConstraint.isActive = false
offConstraint = knob.leftAnchor.constraint(equalTo: track.leftAnchor, constant: Layout.knobInset)
offConstraint.isActive = true
let onConstraint = knob.rightAnchor.constraint(equalTo: track.rightAnchor, constant: -Layout.knobInset)
onConstraint.priority = .defaultHigh // Lower than off constraint, so we can toggle by enabling / disabling off
onConstraint.isActive = true
}
@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
}