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