@@ -20,10 +20,9 @@ class SpringInterfaceViewController: InterfaceViewController {
20
20
21
21
private lazy var dampingSliderView : SliderView = {
22
22
let sliderView = SliderView ( )
23
- sliderView. translatesAutoresizingMaskIntoConstraints = false
24
- sliderView. title = " DAMPING (BOUNCINESS) "
25
- sliderView. minValue = 0.1
26
- sliderView. maxValue = 1
23
+ sliderView. valueFormatter = { String ( format: " %i%% " , Int ( $0 * 100 ) ) }
24
+ sliderView. title = " DAMPING "
25
+ sliderView. range = 0.1 ... 1
27
26
sliderView. value = dampingRatio
28
27
sliderView. sliderMovedAction = { self . dampingRatio = $0 }
29
28
sliderView. sliderFinishedMovingAction = { self . resetAnimation ( ) }
@@ -32,10 +31,9 @@ class SpringInterfaceViewController: InterfaceViewController {
32
31
33
32
private lazy var frequencySliderView : SliderView = {
34
33
let sliderView = SliderView ( )
35
- sliderView. translatesAutoresizingMaskIntoConstraints = false
36
- sliderView. title = " RESPONSE (SPEED) "
37
- sliderView. minValue = 0.1
38
- sliderView. maxValue = 2
34
+ sliderView. valueFormatter = { String ( format: " %.2fs " , $0) }
35
+ sliderView. title = " RESPONSE "
36
+ sliderView. range = 0.1 ... 2
39
37
sliderView. value = frequencyResponse
40
38
sliderView. sliderMovedAction = { self . frequencyResponse = $0 }
41
39
sliderView. sliderFinishedMovingAction = { self . resetAnimation ( ) }
@@ -46,26 +44,37 @@ class SpringInterfaceViewController: InterfaceViewController {
46
44
private var frequencyResponse : CGFloat = 1
47
45
48
46
private let margin : CGFloat = 30
47
+
48
+ private var leadingAnchor , trailingAnchor : NSLayoutConstraint !
49
49
50
50
override func viewDidLoad( ) {
51
51
super. viewDidLoad ( )
52
52
53
53
view. addSubview ( dampingSliderView)
54
- dampingSliderView. leadingAnchor. constraint ( equalTo: view. leadingAnchor, constant: margin) . isActive = true
55
- dampingSliderView. trailingAnchor. constraint ( equalTo: view. trailingAnchor, constant: - margin) . isActive = true
56
- dampingSliderView. centerYAnchor. constraint ( equalTo: view. centerYAnchor, constant: 0 ) . isActive = true
54
+ UIView . activate ( constraints: [
55
+ dampingSliderView. leadingAnchor. constraint ( equalTo: view. leadingAnchor, constant: margin) ,
56
+ dampingSliderView. trailingAnchor. constraint ( equalTo: view. trailingAnchor, constant: - margin) ,
57
+ dampingSliderView. centerYAnchor. constraint ( equalTo: view. centerYAnchor, constant: 0 )
58
+ ] )
57
59
58
60
view. addSubview ( frequencySliderView)
59
- frequencySliderView. leadingAnchor. constraint ( equalTo: view. leadingAnchor, constant: margin) . isActive = true
60
- frequencySliderView. trailingAnchor. constraint ( equalTo: view. trailingAnchor, constant: - margin) . isActive = true
61
- frequencySliderView. centerYAnchor. constraint ( equalTo: view. centerYAnchor, constant: 140 ) . isActive = true
61
+ UIView . activate ( constraints: [
62
+ frequencySliderView. leadingAnchor. constraint ( equalTo: view. leadingAnchor, constant: margin) ,
63
+ frequencySliderView. trailingAnchor. constraint ( equalTo: view. trailingAnchor, constant: - margin) ,
64
+ frequencySliderView. centerYAnchor. constraint ( equalTo: view. centerYAnchor, constant: 140 )
65
+ ] )
62
66
63
67
view. addSubview ( springView)
64
- springView. heightAnchor. constraint ( equalToConstant: 80 ) . isActive = true
65
- springView. widthAnchor. constraint ( equalToConstant: 80 ) . isActive = true
66
- springView. leadingAnchor. constraint ( equalTo: view. leadingAnchor, constant: margin) . isActive = true
67
- springView. bottomAnchor. constraint ( equalTo: dampingSliderView. topAnchor, constant: - 80 ) . isActive = true
68
-
68
+ UIView . activate ( constraints: [
69
+ springView. heightAnchor. constraint ( equalToConstant: 80 ) ,
70
+ springView. widthAnchor. constraint ( equalToConstant: 80 ) ,
71
+ springView. bottomAnchor. constraint ( equalTo: dampingSliderView. topAnchor, constant: - 80 )
72
+ ] )
73
+ self . leadingAnchor = springView. leadingAnchor. constraint ( equalTo: view. leadingAnchor, constant: margin)
74
+ self . leadingAnchor. isActive = true
75
+ self . trailingAnchor = springView. trailingAnchor. constraint ( equalTo: view. trailingAnchor, constant: - margin)
76
+ self . trailingAnchor. isActive = false
77
+
69
78
animateView ( )
70
79
71
80
}
@@ -74,22 +83,21 @@ class SpringInterfaceViewController: InterfaceViewController {
74
83
75
84
/// Repeatedly animates the view using the current `dampingRatio` and `frequencyResponse`.
76
85
private func animateView( ) {
86
+ self . view. layoutIfNeeded ( )
87
+
77
88
let timingParameters = UISpringTimingParameters ( damping: dampingRatio, response: frequencyResponse)
78
89
animator = UIViewPropertyAnimator ( duration: 0 , timingParameters: timingParameters)
79
90
animator. addAnimations {
80
- let translation = self . view. bounds. width - 2 * self . margin - 80
81
- self . springView. transform = CGAffineTransform ( translationX: translation, y: 0 )
82
- }
83
- animator. addCompletion { _ in
84
- self . springView. transform = . identity
85
- self . animateView ( )
91
+ self . leadingAnchor. isActive = !self . leadingAnchor. isActive
92
+ self . trailingAnchor. isActive = !self . trailingAnchor. isActive
93
+ self . view. layoutIfNeeded ( )
86
94
}
95
+ animator. addCompletion { _ in self . animateView ( ) }
87
96
animator. startAnimation ( )
88
97
}
89
98
90
99
private func resetAnimation( ) {
91
100
animator. stopAnimation ( true )
92
- self . springView. transform = . identity
93
101
animateView ( )
94
102
}
95
103
@@ -110,22 +118,20 @@ class SliderView: UIView {
110
118
}
111
119
set {
112
120
slider. value = Float ( newValue)
113
- valueLabel. text = String ( format : " %.2f " , newValue)
121
+ valueLabel. text = valueFormatter ( newValue)
114
122
}
115
123
}
116
124
117
- public var minValue : CGFloat = 0 {
125
+ public var range : ClosedRange < Float > = 0 ... 1 {
118
126
didSet {
119
- slider. minimumValue = Float ( minValue)
120
- }
121
- }
122
-
123
- public var maxValue : CGFloat = 1 {
124
- didSet {
125
- slider. maximumValue = Float ( maxValue)
127
+ slider. minimumValue = range. lowerBound
128
+ slider. maximumValue = range. upperBound
126
129
}
127
130
}
128
131
132
+ /// Code to format the value to a string for the valueLabel
133
+ public var valueFormatter : ( CGFloat ) -> ( String ) = { String ( format: " %.2f " , $0) }
134
+
129
135
/// Code that's executed when the slider moves.
130
136
public var sliderMovedAction : ( CGFloat ) -> ( ) = { _ in }
131
137
@@ -185,7 +191,7 @@ class SliderView: UIView {
185
191
}
186
192
187
193
@objc private func sliderMoved( slider: UISlider , event: UIEvent ) {
188
- valueLabel. text = String ( format : " %.2f " , slider. value)
194
+ valueLabel. text = valueFormatter ( CGFloat ( slider. value) )
189
195
sliderMovedAction ( CGFloat ( slider. value) )
190
196
if event. allTouches? . first? . phase == . ended { sliderFinishedMovingAction ( ) }
191
197
}
0 commit comments