21 |
22 | NHRangeSlider Reference
23 |
24 | Enums Reference
25 |
26 |
27 |
21 |
22 | NHRangeSlider Reference
23 |
24 | Enums Reference
25 |
26 |
27 |
21 |
22 | NHRangeSlider Reference
23 |
24 | Protocols Reference
25 |
26 |
27 |
21 |
22 | NHRangeSlider Reference
23 |
24 | Protocols Reference
25 |
26 |
27 |
22 |
23 | NHRangeSlider Reference
24 |
25 | NHRangeSliderViewDelegate Protocol Reference
26 |
27 |
28 |
22 |
23 | NHRangeSlider Reference
24 |
25 | NHRangeSliderViewDelegate Protocol Reference
26 |
27 |
28 | ' do
27 | pod 'NHRangeSlider', '~> 0.2'
28 | end
29 | ```
30 |
31 | Then, run the:
32 |
33 | ```bash
34 | $ pod install
35 | ```
36 |
37 | ### Carthage
38 |
39 | Put the following in your Cartfile:
40 |
41 | ```ogdl
42 | github "thehung111/NHRangeSlider" ~> 0.2
43 | ```
44 |
45 | Run `carthage update --platform iOS --no-use-binaries`
46 |
47 |
48 | ### Manual
49 |
50 | You can just copy the 2 source files (NHRangeSlider and NHRangeSliderView) under NHRangeSlider/NHRangeSlider folder into your project.
51 |
52 | ## Usage
53 |
54 | ### Default Slider
55 |
56 | By default, the title label is not shown and the left and right thumbs will be circles (`curvaceousness` set to 1). You can add the view in code or via story board:
57 |
58 | ```swift
59 | override func viewDidLoad() {
60 | super.viewDidLoad()
61 |
62 | // default slider. Configure the frame
63 | let sliderView = NHRangeSliderView(frame: CGRect(x: 16, y: 20, width: self.view.bounds.width - 32, height: 80) )
64 | // call size to fit to resize the height to fit exactly
65 | sliderView.sizeToFit()
66 | self.view.addSubview(sliderView)
67 |
68 | }
69 | ```
70 |
71 | ### Slider with Square Thumbs
72 |
73 | ```swift
74 | let sliderSquareView = NHRangeSliderView(frame: ...)
75 |
76 | // set to 0 for square
77 | sliderSquareView.curvaceousness = 0.0
78 |
79 | sliderSquareView.trackHighlightTintColor = UIColor.red
80 | sliderSquareView.lowerValue = 20.0
81 | sliderSquareView.upperValue = 80.0
82 | sliderSquareView.sizeToFit()
83 | self.view.addSubview(sliderSquareView)
84 | ```
85 |
86 | ### Slider with title
87 |
88 | ```swift
89 | let sliderSquareWithLabelView = NHRangeSliderView(frame: ...)
90 | sliderSquareWithLabelView.curvaceousness = 0.0
91 | sliderSquareWithLabelView.trackHighlightTintColor = UIColor.brown
92 | sliderSquareWithLabelView.lowerValue = 20.0
93 | sliderSquareWithLabelView.upperValue = 80.0
94 |
95 | // set title text
96 | sliderSquareWithLabelView.titleLabel?.text = "Slider with title label"
97 |
98 | sliderSquareWithLabelView.sizeToFit()
99 | self.view.addSubview(sliderSquareWithLabelView)
100 | ```
101 |
102 | ### Slider with labels following thumbs
103 |
104 | ```swift
105 | let sliderWithLabelFollowView = NHRangeSliderView(frame: ...)
106 | sliderWithLabelFollowView.trackHighlightTintColor = UIColor.black
107 | sliderWithLabelFollowView.lowerValue = 30.0
108 | sliderWithLabelFollowView.upperValue = 70.0
109 | sliderWithLabelFollowView.gapBetweenThumbs = 5
110 |
111 | // set style to follow
112 | sliderWithLabelFollowView.thumbLabelStyle = .FOLLOW
113 |
114 | sliderWithLabelFollowView.titleLabel?.text = "Slider with labels follow thumbs"
115 | sliderWithLabelFollowView.sizeToFit()
116 | self.view.addSubview(sliderWithLabelFollowView)
117 | ```
118 |
119 | ### Slider with custom format
120 |
121 | ```swift
122 | let sliderCustomStringView = NHRangeSliderView(frame: ...)
123 | sliderCustomStringView.trackHighlightTintColor = UIColor.black
124 | sliderCustomStringView.lowerValue = 30.0
125 | sliderCustomStringView.upperValue = 70.0
126 | sliderCustomStringView.stepValue = 10
127 | sliderCustomStringView.gapBetweenThumbs = 10
128 |
129 | sliderCustomStringView.thumbLabelStyle = .FOLLOW
130 |
131 | sliderCustomStringView.titleLabel?.text = "Stepped slider with custom format"
132 | sliderCustomStringView.lowerDisplayStringFormat = "Min: $%.0f"
133 | sliderCustomStringView.upperDisplayStringFormat = "Max: $%.0f"
134 | sliderCustomStringView.sizeToFit()
135 | self.view.addSubview(sliderCustomStringView)
136 |
137 | ```
138 |
139 | ### Stepped Slider
140 |
141 | Handle stepped values. The slider will snap to discrete points (after dragging stopped) along the slider based on the stepped value.
142 |
143 | ```swift
144 | sliderSquareWithLabelView.stepValue = 5.0
145 | ```
146 |
147 | ## Configuration
148 |
149 | The range slider view (**NHRangeSliderView**) can be customized and information can be accessed through these properties :
150 |
151 | + `titleLabel` : label for title (optional)
152 | + `lowerLabel` : label for lower thumb
153 | + `upperLabel` : label for upper thumb
154 | + `minimumValue` : The minimum possible value of the range
155 | + `maximumValue` : The maximum possible value of the range
156 | + `lowerValue` : The value corresponding to the left thumb current position
157 | + `upperValue` : The value corresponding to the right thumb current position
158 | + `stepValue` : If set, will snap to discrete step points along the slider . Default to nil.
159 | + `trackTintColor` : The track color
160 | + `trackHighlightTintColor` : The color of the section of the track located between the two thumbs
161 | + `thumbTintColor`: The thumb color
162 | + `thumbBorderColor`: The thumb border color
163 | + `thumbBorderWidth`: The width of the thumb border
164 | + `curvaceousness` : From 0.0 for square thumbs to 1.0 for circle thumbs
165 | + `lowerDisplayStringFormat` : display format for lower thumb value. Default to `%.0f` to display value as Int. Change this if you need to display decimal places or want a different label.
166 | + `upperDisplayStringFormat` : display format for upper thumb value. Default to `%.0f` to display value as Int. Change this if you need to display decimal places or want a different label.
167 | + `spacing` : vertical spacing between the labels and thumbs
168 | + `thumbLabelStyle` : position of thumb labels. Set to STICKY to stick to left and right positions. Set to FOLLOW to follow left and right thumbs
169 | + `gapBetweenThumbs` : minimum distance between thumbs
170 |
171 | To listen for value changes event, you can set the delegate (`NHRangeSliderViewDelegate`): sliderValueChanged(slider:)
172 |
173 | ## API Reference
174 |
175 | [https://thehung111.github.io/NHRangeSlider/](https://thehung111.github.io/NHRangeSlider/)
176 |
177 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/docs/Classes/RangeSliderTrackLayer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RangeSliderTrackLayer Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | NHRangeSlider Reference
24 |
25 | RangeSliderTrackLayer Class Reference
26 |
27 |
28 |
29 |
66 |
67 |
68 |
69 | RangeSliderTrackLayer
70 |
71 |
72 |
public class RangeSliderTrackLayer : CALayer
73 |
74 |
75 |
76 | Range slider track layer. Responsible for drawing the horizontal track
77 |
78 |
79 |
80 |
81 |
82 |
83 |
90 |
91 |
92 |
93 |
94 |
95 |
draw the track between 2 thumbs
96 |
97 |
98 |
Parameter
99 | Parameter ctx: current graphics context
100 |
101 |
102 |
103 |
104 |
105 |
Declaration
106 |
107 |
Swift
108 |
override open func draw ( in ctx : CGContext )
109 |
110 |
111 |
112 |
113 |
Parameters
114 |
115 |
116 |
117 |
118 |
119 | ctx
120 |
121 |
122 |
123 |
124 |
current graphics context
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
143 |
144 |
145 |
146 |
147 |
148 |
--------------------------------------------------------------------------------
/docs/docsets/NHRangeSlider.docset/Contents/Resources/Documents/Classes/RangeSliderTrackLayer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RangeSliderTrackLayer Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | NHRangeSlider Reference
24 |
25 | RangeSliderTrackLayer Class Reference
26 |
27 |
28 |
29 |
66 |
67 |
68 |
69 | RangeSliderTrackLayer
70 |
71 |
72 |
public class RangeSliderTrackLayer : CALayer
73 |
74 |
75 |
76 | Range slider track layer. Responsible for drawing the horizontal track
77 |
78 |
79 |
80 |
81 |
82 |
83 |
90 |
91 |
92 |
93 |
94 |
95 |
draw the track between 2 thumbs
96 |
97 |
98 |
Parameter
99 | Parameter ctx: current graphics context
100 |
101 |
102 |
103 |
104 |
105 |
Declaration
106 |
107 |
Swift
108 |
override open func draw ( in ctx : CGContext )
109 |
110 |
111 |
112 |
113 |
Parameters
114 |
115 |
116 |
117 |
118 |
119 | ctx
120 |
121 |
122 |
123 |
124 |
current graphics context
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
143 |
144 |
145 |
146 |
147 |
148 |
--------------------------------------------------------------------------------
/docs/Enums/NHSliderLabelStyle.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | NHSliderLabelStyle Enum Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | NHRangeSlider Reference
24 |
25 | NHSliderLabelStyle Enum Reference
26 |
27 |
28 |
29 |
66 |
67 |
68 |
69 | NHSliderLabelStyle
70 |
71 |
72 |
public enum NHSliderLabelStyle : Int
73 |
74 |
75 |
76 | enum for label positions
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | STICKY
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
lower and upper labels stick to the left and right of slider
96 |
97 |
98 |
99 |
Declaration
100 |
101 |
Swift
102 |
case STICKY
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | FOLLOW
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
lower and upper labels follow position of lower and upper thumbs
127 |
128 |
129 |
130 |
Declaration
131 |
132 |
Swift
133 |
case FOLLOW
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
148 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/docs/docsets/NHRangeSlider.docset/Contents/Resources/Documents/Enums/NHSliderLabelStyle.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | NHSliderLabelStyle Enum Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | NHRangeSlider Reference
24 |
25 | NHSliderLabelStyle Enum Reference
26 |
27 |
28 |
29 |
66 |
67 |
68 |
69 | NHSliderLabelStyle
70 |
71 |
72 |
public enum NHSliderLabelStyle : Int
73 |
74 |
75 |
76 | enum for label positions
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | STICKY
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
lower and upper labels stick to the left and right of slider
96 |
97 |
98 |
99 |
Declaration
100 |
101 |
Swift
102 |
case STICKY
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | FOLLOW
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
lower and upper labels follow position of lower and upper thumbs
127 |
128 |
129 |
130 |
Declaration
131 |
132 |
Swift
133 |
case FOLLOW
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
148 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/docs/css/jazzy.css:
--------------------------------------------------------------------------------
1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td {
2 | background: transparent;
3 | border: 0;
4 | margin: 0;
5 | outline: 0;
6 | padding: 0;
7 | vertical-align: baseline; }
8 |
9 | body {
10 | background-color: #f2f2f2;
11 | font-family: Helvetica, freesans, Arial, sans-serif;
12 | font-size: 14px;
13 | -webkit-font-smoothing: subpixel-antialiased;
14 | word-wrap: break-word; }
15 |
16 | h1, h2, h3 {
17 | margin-top: 0.8em;
18 | margin-bottom: 0.3em;
19 | font-weight: 100;
20 | color: black; }
21 |
22 | h1 {
23 | font-size: 2.5em; }
24 |
25 | h2 {
26 | font-size: 2em;
27 | border-bottom: 1px solid #e2e2e2; }
28 |
29 | h4 {
30 | font-size: 13px;
31 | line-height: 1.5;
32 | margin-top: 21px; }
33 |
34 | h5 {
35 | font-size: 1.1em; }
36 |
37 | h6 {
38 | font-size: 1.1em;
39 | color: #777; }
40 |
41 | .section-name {
42 | color: gray;
43 | display: block;
44 | font-family: Helvetica;
45 | font-size: 22px;
46 | font-weight: 100;
47 | margin-bottom: 15px; }
48 |
49 | pre, code {
50 | font: 0.95em Menlo, monospace;
51 | color: #777;
52 | word-wrap: normal; }
53 |
54 | p code, li code {
55 | background-color: #eee;
56 | padding: 2px 4px;
57 | border-radius: 4px; }
58 |
59 | a {
60 | color: #0088cc;
61 | text-decoration: none; }
62 |
63 | ul {
64 | padding-left: 15px; }
65 |
66 | li {
67 | line-height: 1.8em; }
68 |
69 | img {
70 | max-width: 100%; }
71 |
72 | blockquote {
73 | margin-left: 0;
74 | padding: 0 10px;
75 | border-left: 4px solid #ccc; }
76 |
77 | .content-wrapper {
78 | margin: 0 auto;
79 | width: 980px; }
80 |
81 | header {
82 | font-size: 0.85em;
83 | line-height: 26px;
84 | background-color: #414141;
85 | position: fixed;
86 | width: 100%;
87 | z-index: 1; }
88 | header img {
89 | padding-right: 6px;
90 | vertical-align: -4px;
91 | height: 16px; }
92 | header a {
93 | color: #fff; }
94 | header p {
95 | float: left;
96 | color: #999; }
97 | header .header-right {
98 | float: right;
99 | margin-left: 16px; }
100 |
101 | #breadcrumbs {
102 | background-color: #f2f2f2;
103 | height: 27px;
104 | padding-top: 17px;
105 | position: fixed;
106 | width: 100%;
107 | z-index: 1;
108 | margin-top: 26px; }
109 | #breadcrumbs #carat {
110 | height: 10px;
111 | margin: 0 5px; }
112 |
113 | .sidebar {
114 | background-color: #f9f9f9;
115 | border: 1px solid #e2e2e2;
116 | overflow-y: auto;
117 | overflow-x: hidden;
118 | position: fixed;
119 | top: 70px;
120 | bottom: 0;
121 | width: 230px;
122 | word-wrap: normal; }
123 |
124 | .nav-groups {
125 | list-style-type: none;
126 | background: #fff;
127 | padding-left: 0; }
128 |
129 | .nav-group-name {
130 | border-bottom: 1px solid #e2e2e2;
131 | font-size: 1.1em;
132 | font-weight: 100;
133 | padding: 15px 0 15px 20px; }
134 | .nav-group-name > a {
135 | color: #333; }
136 |
137 | .nav-group-tasks {
138 | margin-top: 5px; }
139 |
140 | .nav-group-task {
141 | font-size: 0.9em;
142 | list-style-type: none;
143 | white-space: nowrap; }
144 | .nav-group-task a {
145 | color: #888; }
146 |
147 | .main-content {
148 | background-color: #fff;
149 | border: 1px solid #e2e2e2;
150 | margin-left: 246px;
151 | position: absolute;
152 | overflow: hidden;
153 | padding-bottom: 60px;
154 | top: 70px;
155 | width: 734px; }
156 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote {
157 | margin-bottom: 1em; }
158 | .main-content p {
159 | line-height: 1.8em; }
160 | .main-content section .section:first-child {
161 | margin-top: 0;
162 | padding-top: 0; }
163 | .main-content section .task-group-section .task-group:first-of-type {
164 | padding-top: 10px; }
165 | .main-content section .task-group-section .task-group:first-of-type .section-name {
166 | padding-top: 15px; }
167 |
168 | .section {
169 | padding: 0 25px; }
170 |
171 | .highlight {
172 | background-color: #eee;
173 | padding: 10px 12px;
174 | border: 1px solid #e2e2e2;
175 | border-radius: 4px;
176 | overflow-x: auto; }
177 |
178 | .declaration .highlight {
179 | overflow-x: initial;
180 | padding: 0 40px 40px 0;
181 | margin-bottom: -25px;
182 | background-color: transparent;
183 | border: none; }
184 |
185 | .section-name {
186 | margin: 0;
187 | margin-left: 18px; }
188 |
189 | .task-group-section {
190 | padding-left: 6px;
191 | border-top: 1px solid #e2e2e2; }
192 |
193 | .task-group {
194 | padding-top: 0px; }
195 |
196 | .task-name-container a[name]:before {
197 | content: "";
198 | display: block;
199 | padding-top: 70px;
200 | margin: -70px 0 0; }
201 |
202 | .item {
203 | padding-top: 8px;
204 | width: 100%;
205 | list-style-type: none; }
206 | .item a[name]:before {
207 | content: "";
208 | display: block;
209 | padding-top: 70px;
210 | margin: -70px 0 0; }
211 | .item code {
212 | background-color: transparent;
213 | padding: 0; }
214 | .item .token {
215 | padding-left: 3px;
216 | margin-left: 15px;
217 | font-size: 11.9px; }
218 | .item .declaration-note {
219 | font-size: .85em;
220 | color: gray;
221 | font-style: italic; }
222 |
223 | .pointer-container {
224 | border-bottom: 1px solid #e2e2e2;
225 | left: -23px;
226 | padding-bottom: 13px;
227 | position: relative;
228 | width: 110%; }
229 |
230 | .pointer {
231 | background: #f9f9f9;
232 | border-left: 1px solid #e2e2e2;
233 | border-top: 1px solid #e2e2e2;
234 | height: 12px;
235 | left: 21px;
236 | top: -7px;
237 | -webkit-transform: rotate(45deg);
238 | -moz-transform: rotate(45deg);
239 | -o-transform: rotate(45deg);
240 | transform: rotate(45deg);
241 | position: absolute;
242 | width: 12px; }
243 |
244 | .height-container {
245 | display: none;
246 | left: -25px;
247 | padding: 0 25px;
248 | position: relative;
249 | width: 100%;
250 | overflow: hidden; }
251 | .height-container .section {
252 | background: #f9f9f9;
253 | border-bottom: 1px solid #e2e2e2;
254 | left: -25px;
255 | position: relative;
256 | width: 100%;
257 | padding-top: 10px;
258 | padding-bottom: 5px; }
259 |
260 | .aside, .language {
261 | padding: 6px 12px;
262 | margin: 12px 0;
263 | border-left: 5px solid #dddddd;
264 | overflow-y: hidden; }
265 | .aside .aside-title, .language .aside-title {
266 | font-size: 9px;
267 | letter-spacing: 2px;
268 | text-transform: uppercase;
269 | padding-bottom: 0;
270 | margin: 0;
271 | color: #aaa;
272 | -webkit-user-select: none; }
273 | .aside p:last-child, .language p:last-child {
274 | margin-bottom: 0; }
275 |
276 | .language {
277 | border-left: 5px solid #cde9f4; }
278 | .language .aside-title {
279 | color: #4b8afb; }
280 |
281 | .aside-warning {
282 | border-left: 5px solid #ff6666; }
283 | .aside-warning .aside-title {
284 | color: #ff0000; }
285 |
286 | .graybox {
287 | border-collapse: collapse;
288 | width: 100%; }
289 | .graybox p {
290 | margin: 0;
291 | word-break: break-word;
292 | min-width: 50px; }
293 | .graybox td {
294 | border: 1px solid #e2e2e2;
295 | padding: 5px 25px 5px 10px;
296 | vertical-align: middle; }
297 | .graybox tr td:first-of-type {
298 | text-align: right;
299 | padding: 7px;
300 | vertical-align: top;
301 | word-break: normal;
302 | width: 40px; }
303 |
304 | .slightly-smaller {
305 | font-size: 0.9em; }
306 |
307 | #footer {
308 | position: absolute;
309 | bottom: 10px;
310 | margin-left: 25px; }
311 | #footer p {
312 | margin: 0;
313 | color: #aaa;
314 | font-size: 0.8em; }
315 |
316 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar {
317 | display: none; }
318 | html.dash .main-content {
319 | width: 980px;
320 | margin-left: 0;
321 | border: none;
322 | width: 100%;
323 | top: 0;
324 | padding-bottom: 0; }
325 | html.dash .height-container {
326 | display: block; }
327 | html.dash .item .token {
328 | margin-left: 0; }
329 | html.dash .content-wrapper {
330 | width: auto; }
331 | html.dash #footer {
332 | position: static; }
333 |
--------------------------------------------------------------------------------
/docs/docsets/NHRangeSlider.docset/Contents/Resources/Documents/css/jazzy.css:
--------------------------------------------------------------------------------
1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td {
2 | background: transparent;
3 | border: 0;
4 | margin: 0;
5 | outline: 0;
6 | padding: 0;
7 | vertical-align: baseline; }
8 |
9 | body {
10 | background-color: #f2f2f2;
11 | font-family: Helvetica, freesans, Arial, sans-serif;
12 | font-size: 14px;
13 | -webkit-font-smoothing: subpixel-antialiased;
14 | word-wrap: break-word; }
15 |
16 | h1, h2, h3 {
17 | margin-top: 0.8em;
18 | margin-bottom: 0.3em;
19 | font-weight: 100;
20 | color: black; }
21 |
22 | h1 {
23 | font-size: 2.5em; }
24 |
25 | h2 {
26 | font-size: 2em;
27 | border-bottom: 1px solid #e2e2e2; }
28 |
29 | h4 {
30 | font-size: 13px;
31 | line-height: 1.5;
32 | margin-top: 21px; }
33 |
34 | h5 {
35 | font-size: 1.1em; }
36 |
37 | h6 {
38 | font-size: 1.1em;
39 | color: #777; }
40 |
41 | .section-name {
42 | color: gray;
43 | display: block;
44 | font-family: Helvetica;
45 | font-size: 22px;
46 | font-weight: 100;
47 | margin-bottom: 15px; }
48 |
49 | pre, code {
50 | font: 0.95em Menlo, monospace;
51 | color: #777;
52 | word-wrap: normal; }
53 |
54 | p code, li code {
55 | background-color: #eee;
56 | padding: 2px 4px;
57 | border-radius: 4px; }
58 |
59 | a {
60 | color: #0088cc;
61 | text-decoration: none; }
62 |
63 | ul {
64 | padding-left: 15px; }
65 |
66 | li {
67 | line-height: 1.8em; }
68 |
69 | img {
70 | max-width: 100%; }
71 |
72 | blockquote {
73 | margin-left: 0;
74 | padding: 0 10px;
75 | border-left: 4px solid #ccc; }
76 |
77 | .content-wrapper {
78 | margin: 0 auto;
79 | width: 980px; }
80 |
81 | header {
82 | font-size: 0.85em;
83 | line-height: 26px;
84 | background-color: #414141;
85 | position: fixed;
86 | width: 100%;
87 | z-index: 1; }
88 | header img {
89 | padding-right: 6px;
90 | vertical-align: -4px;
91 | height: 16px; }
92 | header a {
93 | color: #fff; }
94 | header p {
95 | float: left;
96 | color: #999; }
97 | header .header-right {
98 | float: right;
99 | margin-left: 16px; }
100 |
101 | #breadcrumbs {
102 | background-color: #f2f2f2;
103 | height: 27px;
104 | padding-top: 17px;
105 | position: fixed;
106 | width: 100%;
107 | z-index: 1;
108 | margin-top: 26px; }
109 | #breadcrumbs #carat {
110 | height: 10px;
111 | margin: 0 5px; }
112 |
113 | .sidebar {
114 | background-color: #f9f9f9;
115 | border: 1px solid #e2e2e2;
116 | overflow-y: auto;
117 | overflow-x: hidden;
118 | position: fixed;
119 | top: 70px;
120 | bottom: 0;
121 | width: 230px;
122 | word-wrap: normal; }
123 |
124 | .nav-groups {
125 | list-style-type: none;
126 | background: #fff;
127 | padding-left: 0; }
128 |
129 | .nav-group-name {
130 | border-bottom: 1px solid #e2e2e2;
131 | font-size: 1.1em;
132 | font-weight: 100;
133 | padding: 15px 0 15px 20px; }
134 | .nav-group-name > a {
135 | color: #333; }
136 |
137 | .nav-group-tasks {
138 | margin-top: 5px; }
139 |
140 | .nav-group-task {
141 | font-size: 0.9em;
142 | list-style-type: none;
143 | white-space: nowrap; }
144 | .nav-group-task a {
145 | color: #888; }
146 |
147 | .main-content {
148 | background-color: #fff;
149 | border: 1px solid #e2e2e2;
150 | margin-left: 246px;
151 | position: absolute;
152 | overflow: hidden;
153 | padding-bottom: 60px;
154 | top: 70px;
155 | width: 734px; }
156 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote {
157 | margin-bottom: 1em; }
158 | .main-content p {
159 | line-height: 1.8em; }
160 | .main-content section .section:first-child {
161 | margin-top: 0;
162 | padding-top: 0; }
163 | .main-content section .task-group-section .task-group:first-of-type {
164 | padding-top: 10px; }
165 | .main-content section .task-group-section .task-group:first-of-type .section-name {
166 | padding-top: 15px; }
167 |
168 | .section {
169 | padding: 0 25px; }
170 |
171 | .highlight {
172 | background-color: #eee;
173 | padding: 10px 12px;
174 | border: 1px solid #e2e2e2;
175 | border-radius: 4px;
176 | overflow-x: auto; }
177 |
178 | .declaration .highlight {
179 | overflow-x: initial;
180 | padding: 0 40px 40px 0;
181 | margin-bottom: -25px;
182 | background-color: transparent;
183 | border: none; }
184 |
185 | .section-name {
186 | margin: 0;
187 | margin-left: 18px; }
188 |
189 | .task-group-section {
190 | padding-left: 6px;
191 | border-top: 1px solid #e2e2e2; }
192 |
193 | .task-group {
194 | padding-top: 0px; }
195 |
196 | .task-name-container a[name]:before {
197 | content: "";
198 | display: block;
199 | padding-top: 70px;
200 | margin: -70px 0 0; }
201 |
202 | .item {
203 | padding-top: 8px;
204 | width: 100%;
205 | list-style-type: none; }
206 | .item a[name]:before {
207 | content: "";
208 | display: block;
209 | padding-top: 70px;
210 | margin: -70px 0 0; }
211 | .item code {
212 | background-color: transparent;
213 | padding: 0; }
214 | .item .token {
215 | padding-left: 3px;
216 | margin-left: 15px;
217 | font-size: 11.9px; }
218 | .item .declaration-note {
219 | font-size: .85em;
220 | color: gray;
221 | font-style: italic; }
222 |
223 | .pointer-container {
224 | border-bottom: 1px solid #e2e2e2;
225 | left: -23px;
226 | padding-bottom: 13px;
227 | position: relative;
228 | width: 110%; }
229 |
230 | .pointer {
231 | background: #f9f9f9;
232 | border-left: 1px solid #e2e2e2;
233 | border-top: 1px solid #e2e2e2;
234 | height: 12px;
235 | left: 21px;
236 | top: -7px;
237 | -webkit-transform: rotate(45deg);
238 | -moz-transform: rotate(45deg);
239 | -o-transform: rotate(45deg);
240 | transform: rotate(45deg);
241 | position: absolute;
242 | width: 12px; }
243 |
244 | .height-container {
245 | display: none;
246 | left: -25px;
247 | padding: 0 25px;
248 | position: relative;
249 | width: 100%;
250 | overflow: hidden; }
251 | .height-container .section {
252 | background: #f9f9f9;
253 | border-bottom: 1px solid #e2e2e2;
254 | left: -25px;
255 | position: relative;
256 | width: 100%;
257 | padding-top: 10px;
258 | padding-bottom: 5px; }
259 |
260 | .aside, .language {
261 | padding: 6px 12px;
262 | margin: 12px 0;
263 | border-left: 5px solid #dddddd;
264 | overflow-y: hidden; }
265 | .aside .aside-title, .language .aside-title {
266 | font-size: 9px;
267 | letter-spacing: 2px;
268 | text-transform: uppercase;
269 | padding-bottom: 0;
270 | margin: 0;
271 | color: #aaa;
272 | -webkit-user-select: none; }
273 | .aside p:last-child, .language p:last-child {
274 | margin-bottom: 0; }
275 |
276 | .language {
277 | border-left: 5px solid #cde9f4; }
278 | .language .aside-title {
279 | color: #4b8afb; }
280 |
281 | .aside-warning {
282 | border-left: 5px solid #ff6666; }
283 | .aside-warning .aside-title {
284 | color: #ff0000; }
285 |
286 | .graybox {
287 | border-collapse: collapse;
288 | width: 100%; }
289 | .graybox p {
290 | margin: 0;
291 | word-break: break-word;
292 | min-width: 50px; }
293 | .graybox td {
294 | border: 1px solid #e2e2e2;
295 | padding: 5px 25px 5px 10px;
296 | vertical-align: middle; }
297 | .graybox tr td:first-of-type {
298 | text-align: right;
299 | padding: 7px;
300 | vertical-align: top;
301 | word-break: normal;
302 | width: 40px; }
303 |
304 | .slightly-smaller {
305 | font-size: 0.9em; }
306 |
307 | #footer {
308 | position: absolute;
309 | bottom: 10px;
310 | margin-left: 25px; }
311 | #footer p {
312 | margin: 0;
313 | color: #aaa;
314 | font-size: 0.8em; }
315 |
316 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar {
317 | display: none; }
318 | html.dash .main-content {
319 | width: 980px;
320 | margin-left: 0;
321 | border: none;
322 | width: 100%;
323 | top: 0;
324 | padding-bottom: 0; }
325 | html.dash .height-container {
326 | display: block; }
327 | html.dash .item .token {
328 | margin-left: 0; }
329 | html.dash .content-wrapper {
330 | width: auto; }
331 | html.dash #footer {
332 | position: static; }
333 |
--------------------------------------------------------------------------------
/docs/Classes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Classes Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 | NHRangeSlider Reference
23 |
24 | Classes Reference
25 |
26 |
27 |
28 |
65 |
66 |
67 |
68 | Classes
69 | The following classes are available globally.
70 |
71 |
72 |
73 |
74 |
75 |
76 |
83 |
84 |
85 |
86 |
87 |
88 |
Range slider track layer. Responsible for drawing the horizontal track
89 |
90 |
See more
91 |
92 |
93 |
Declaration
94 |
95 |
Swift
96 |
public class RangeSliderTrackLayer : CALayer
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
111 |
112 |
113 |
114 |
115 |
116 |
the thumb for upper , lower bounds
117 |
118 |
See more
119 |
120 |
121 |
Declaration
122 |
123 |
Swift
124 |
public class RangeSliderThumbLayer : CALayer
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
139 |
140 |
141 |
142 |
143 |
144 |
Range slider view with upper, lower bounds
145 |
146 |
See more
147 |
148 |
149 |
Declaration
150 |
151 |
Swift
152 |
open class NHRangeSlider : UIControl
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
171 |
172 |
173 |
174 |
175 |
176 |
Range slider with labels for upper and lower thumbs, title label and configurable step value (optional)
177 |
178 |
See more
179 |
180 |
181 |
Declaration
182 |
183 |
Swift
184 |
open class NHRangeSliderView : UIView
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
199 |
200 |
201 |
202 |
203 |
204 |
--------------------------------------------------------------------------------
/docs/docsets/NHRangeSlider.docset/Contents/Resources/Documents/Classes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Classes Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 | NHRangeSlider Reference
23 |
24 | Classes Reference
25 |
26 |
27 |
28 |
65 |
66 |
67 |
68 | Classes
69 | The following classes are available globally.
70 |
71 |
72 |
73 |
74 |
75 |
76 |
83 |
84 |
85 |
86 |
87 |
88 |
Range slider track layer. Responsible for drawing the horizontal track
89 |
90 |
See more
91 |
92 |
93 |
Declaration
94 |
95 |
Swift
96 |
public class RangeSliderTrackLayer : CALayer
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
111 |
112 |
113 |
114 |
115 |
116 |
the thumb for upper , lower bounds
117 |
118 |
See more
119 |
120 |
121 |
Declaration
122 |
123 |
Swift
124 |
public class RangeSliderThumbLayer : CALayer
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
139 |
140 |
141 |
142 |
143 |
144 |
Range slider view with upper, lower bounds
145 |
146 |
See more
147 |
148 |
149 |
Declaration
150 |
151 |
Swift
152 |
open class NHRangeSlider : UIControl
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
171 |
172 |
173 |
174 |
175 |
176 |
Range slider with labels for upper and lower thumbs, title label and configurable step value (optional)
177 |
178 |
See more
179 |
180 |
181 |
Declaration
182 |
183 |
Swift
184 |
open class NHRangeSliderView : UIView
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
199 |
200 |
201 |
202 |
203 |
204 |
--------------------------------------------------------------------------------
/docs/Classes/RangeSliderThumbLayer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RangeSliderThumbLayer Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | NHRangeSlider Reference
24 |
25 | RangeSliderThumbLayer Class Reference
26 |
27 |
28 |
29 |
66 |
67 |
68 |
69 | RangeSliderThumbLayer
70 |
71 |
72 |
public class RangeSliderThumbLayer : CALayer
73 |
74 |
75 |
76 | the thumb for upper , lower bounds
77 |
78 |
79 |
80 |
81 |
82 |
83 |
90 |
91 |
92 |
93 |
94 |
95 |
whether this thumb is currently highlighted i.e. touched by user
96 |
97 |
98 |
99 |
Declaration
100 |
101 |
Swift
102 |
public var highlighted : Bool = false
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
117 |
118 |
119 |
120 |
121 |
122 |
stroke color
123 |
124 |
125 |
126 |
Declaration
127 |
128 |
Swift
129 |
public var strokeColor : UIColor = UIColor . gray
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 | lineWidth
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
line width
150 |
151 |
152 |
153 |
Declaration
154 |
155 |
Swift
156 |
public var lineWidth : CGFloat = 0.5
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 | draw(in:)
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
draw the thumb
177 |
178 |
179 |
Parameter
180 | Parameter ctx: current graphics context
181 |
182 |
183 |
184 |
185 |
186 |
Declaration
187 |
188 |
Swift
189 |
override open func draw ( in ctx : CGContext )
190 |
191 |
192 |
193 |
194 |
Parameters
195 |
196 |
197 |
198 |
199 |
200 | ctx
201 |
202 |
203 |
204 |
205 |
current graphics context
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
224 |
225 |
226 |
227 |
228 |
229 |
--------------------------------------------------------------------------------
/docs/docsets/NHRangeSlider.docset/Contents/Resources/Documents/Classes/RangeSliderThumbLayer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RangeSliderThumbLayer Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | NHRangeSlider Reference
24 |
25 | RangeSliderThumbLayer Class Reference
26 |
27 |
28 |
29 |
66 |
67 |
68 |
69 | RangeSliderThumbLayer
70 |
71 |
72 |
public class RangeSliderThumbLayer : CALayer
73 |
74 |
75 |
76 | the thumb for upper , lower bounds
77 |
78 |
79 |
80 |
81 |
82 |
83 |
90 |
91 |
92 |
93 |
94 |
95 |
whether this thumb is currently highlighted i.e. touched by user
96 |
97 |
98 |
99 |
Declaration
100 |
101 |
Swift
102 |
public var highlighted : Bool = false
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
117 |
118 |
119 |
120 |
121 |
122 |
stroke color
123 |
124 |
125 |
126 |
Declaration
127 |
128 |
Swift
129 |
public var strokeColor : UIColor = UIColor . gray
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 | lineWidth
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
line width
150 |
151 |
152 |
153 |
Declaration
154 |
155 |
Swift
156 |
public var lineWidth : CGFloat = 0.5
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 | draw(in:)
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
draw the thumb
177 |
178 |
179 |
Parameter
180 | Parameter ctx: current graphics context
181 |
182 |
183 |
184 |
185 |
186 |
Declaration
187 |
188 |
Swift
189 |
override open func draw ( in ctx : CGContext )
190 |
191 |
192 |
193 |
194 |
Parameters
195 |
196 |
197 |
198 |
199 |
200 | ctx
201 |
202 |
203 |
204 |
205 |
current graphics context
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
224 |
225 |
226 |
227 |
228 |
229 |
--------------------------------------------------------------------------------
/NHRangeSlider/NHRangeSlider/NHRangeSliderView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NHRangeSliderView.swift
3 | // NHRangeSlider
4 | //
5 | // Created by Hung on 17/12/16.
6 | // Copyright © 2016 Hung. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// enum for label positions
12 | public enum NHSliderLabelStyle : Int {
13 | /// lower and upper labels stick to the left and right of slider
14 | case STICKY
15 |
16 | /// lower and upper labels follow position of lower and upper thumbs
17 | case FOLLOW
18 | }
19 |
20 | /// delegate for changed value
21 | public protocol NHRangeSliderViewDelegate: class {
22 | /// slider value changed
23 | func sliderValueChanged(slider: NHRangeSlider?)
24 | }
25 |
26 | /// optional implementation
27 | public extension NHRangeSliderViewDelegate{
28 | func sliderValueChanged(slider: NHRangeSlider?){}
29 | }
30 |
31 | /// Range slider with labels for upper and lower thumbs, title label and configurable step value (optional)
32 | open class NHRangeSliderView: UIView {
33 |
34 | //MARK: properties
35 |
36 | open var delegate: NHRangeSliderViewDelegate? = nil
37 |
38 | /// Range slider
39 | open var rangeSlider : NHRangeSlider? = nil
40 |
41 | /// Display title
42 | open var titleLabel : UILabel? = nil
43 |
44 | // lower value label for displaying selected lower value
45 | open var lowerLabel : UILabel? = nil
46 |
47 | /// upper value label for displaying selected upper value
48 | open var upperLabel : UILabel? = nil
49 |
50 | /// display format for lower value. Default to %.0f to display value as Int
51 | open var lowerDisplayStringFormat: String = "%.0f" {
52 | didSet {
53 | updateLabelDisplay()
54 | }
55 | }
56 |
57 | /// display format for upper value. Default to %.0f to display value as Int
58 | open var upperDisplayStringFormat: String = "%.0f" {
59 | didSet {
60 | updateLabelDisplay()
61 | }
62 | }
63 |
64 | /// vertical spacing
65 | open var spacing: CGFloat = 4.0
66 |
67 | /// position of thumb labels. Set to STICKY to stick to left and right positions. Set to FOLLOW to follow left and right thumbs
68 | open var thumbLabelStyle: NHSliderLabelStyle = .STICKY
69 |
70 | /// minimum value
71 | @IBInspectable open var minimumValue: Double = 0.0 {
72 | didSet {
73 | self.rangeSlider?.minimumValue = minimumValue
74 | }
75 | }
76 |
77 | /// max value
78 | @IBInspectable open var maximumValue: Double = 100.0 {
79 | didSet {
80 | self.rangeSlider?.maximumValue = maximumValue
81 | }
82 | }
83 |
84 | /// value for lower thumb
85 | @IBInspectable open var lowerValue: Double = 0.0 {
86 | didSet {
87 | self.rangeSlider?.lowerValue = lowerValue
88 | self.updateLabelDisplay()
89 | }
90 | }
91 |
92 | /// value for upper thumb
93 | @IBInspectable open var upperValue: Double = 100.0 {
94 | didSet {
95 | self.rangeSlider?.upperValue = upperValue
96 | self.updateLabelDisplay()
97 | }
98 | }
99 |
100 | /// stepValue. If set, will snap to discrete step points along the slider . Default to nil
101 | @IBInspectable open var stepValue: Double? = nil {
102 | didSet {
103 | self.rangeSlider?.stepValue = stepValue
104 | }
105 | }
106 |
107 | /// minimum distance between the upper and lower thumbs.
108 | open var gapBetweenThumbs: Double = 2.0 {
109 | didSet {
110 | self.rangeSlider?.gapBetweenThumbs = gapBetweenThumbs
111 | }
112 | }
113 |
114 | /// tint color for track between 2 thumbs
115 | @IBInspectable open var trackTintColor: UIColor = UIColor(white: 0.9, alpha: 1.0) {
116 | didSet {
117 | self.rangeSlider?.trackTintColor = trackTintColor
118 | }
119 | }
120 |
121 |
122 | /// track highlight tint color
123 | @IBInspectable open var trackHighlightTintColor: UIColor = UIColor(red: 0.0, green: 0.45, blue: 0.94, alpha: 1.0) {
124 | didSet {
125 | self.rangeSlider?.trackHighlightTintColor = trackHighlightTintColor
126 | }
127 | }
128 |
129 |
130 | /// thumb tint color
131 | @IBInspectable open var thumbTintColor: UIColor = UIColor.white {
132 | didSet {
133 | self.rangeSlider?.thumbTintColor = thumbTintColor
134 | }
135 | }
136 |
137 | /// thumb border color
138 | @IBInspectable open var thumbBorderColor: UIColor = UIColor.gray {
139 | didSet {
140 | self.rangeSlider?.thumbBorderColor = thumbBorderColor
141 | }
142 | }
143 |
144 |
145 | /// thumb border width
146 | @IBInspectable open var thumbBorderWidth: CGFloat = 0.5 {
147 | didSet {
148 | self.rangeSlider?.thumbBorderWidth = thumbBorderWidth
149 |
150 | }
151 | }
152 |
153 | /// set 0.0 for square thumbs to 1.0 for circle thumbs
154 | @IBInspectable open var curvaceousness: CGFloat = 1.0 {
155 | didSet {
156 | self.rangeSlider?.curvaceousness = curvaceousness
157 | }
158 | }
159 |
160 | /// thumb width and height
161 | @IBInspectable open var thumbSize: CGFloat = 32.0 {
162 | didSet {
163 | if let slider = self.rangeSlider {
164 | var oldFrame = slider.frame
165 | oldFrame.size.height = thumbSize
166 | slider.frame = oldFrame
167 | }
168 | }
169 | }
170 |
171 | //MARK: init
172 |
173 | public override init(frame: CGRect) {
174 | super.init(frame: frame)
175 |
176 | setup()
177 | }
178 |
179 | required public init?(coder aDecoder: NSCoder) {
180 | super.init(coder: aDecoder)
181 |
182 | setup()
183 | }
184 |
185 | /// setup
186 | open func setup() {
187 | self.autoresizingMask = [.flexibleWidth]
188 |
189 | self.titleLabel = UILabel(frame: .zero)
190 | self.titleLabel?.numberOfLines = 1
191 | self.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16.0)
192 | self.titleLabel?.text = ""
193 | self.addSubview(self.titleLabel!)
194 |
195 | self.lowerLabel = UILabel(frame: .zero)
196 | self.lowerLabel?.numberOfLines = 1
197 | self.lowerLabel?.font = UIFont.systemFont(ofSize: 14.0)
198 | self.lowerLabel?.text = ""
199 | self.lowerLabel?.textAlignment = .center
200 | self.addSubview(self.lowerLabel!)
201 |
202 | self.upperLabel = UILabel(frame: .zero)
203 | self.upperLabel?.numberOfLines = 1
204 | self.upperLabel?.font = UIFont.systemFont(ofSize: 14.0)
205 | self.upperLabel?.text = ""
206 | self.upperLabel?.textAlignment = .center
207 | self.addSubview(self.upperLabel!)
208 |
209 | self.rangeSlider = NHRangeSlider(frame: .zero)
210 | self.addSubview(self.rangeSlider!)
211 |
212 | self.updateLabelDisplay()
213 |
214 | self.rangeSlider?.addTarget(self, action: #selector(self.rangeSliderValueChanged(_:)), for: .valueChanged)
215 | }
216 |
217 | //MARK: range slider delegage
218 |
219 | /// Range slider change events. Upper / lower labels will be updated accordingly.
220 | /// Selected value for filterItem will also be updated
221 | ///
222 | /// - Parameter rangeSlider: the changed rangeSlider
223 | open func rangeSliderValueChanged(_ rangeSlider: NHRangeSlider) {
224 |
225 | delegate?.sliderValueChanged(slider: rangeSlider)
226 |
227 | self.updateLabelDisplay()
228 |
229 | }
230 |
231 | //MARK: -
232 |
233 | // update labels display
234 | open func updateLabelDisplay() {
235 |
236 | self.lowerLabel?.text = String(format: self.lowerDisplayStringFormat, rangeSlider!.lowerValue )
237 | self.upperLabel?.text = String(format: self.upperDisplayStringFormat, rangeSlider!.upperValue )
238 |
239 | if self.lowerLabel != nil {
240 |
241 | // for stepped value we animate the labels
242 | if self.stepValue != nil && self.thumbLabelStyle == .FOLLOW {
243 | UIView.animate(withDuration: 0.1, animations: {
244 | self.layoutSubviews()
245 | })
246 | }
247 | else {
248 | self.setNeedsLayout()
249 | self.layoutIfNeeded()
250 | }
251 | }
252 | }
253 |
254 | /// layout subviews
255 | override open func layoutSubviews() {
256 | super.layoutSubviews()
257 |
258 | if let titleLabel = self.titleLabel , let lowerLabel = self.lowerLabel ,
259 | let upperLabel = self.upperLabel , let rangeSlider = self.rangeSlider {
260 |
261 | let commonWidth = self.bounds.width
262 | var titleLabelMaxY : CGFloat = 0
263 |
264 | if !titleLabel.isHidden && titleLabel.text != nil && titleLabel.text!.characters.count > 0 {
265 | titleLabel.frame = CGRect(x: 0,
266 | y: 0,
267 | width: commonWidth ,
268 | height: (titleLabel.font.lineHeight + self.spacing ) )
269 |
270 | titleLabelMaxY = titleLabel.frame.origin.y + titleLabel.frame.size.height
271 | }
272 |
273 | rangeSlider.frame = CGRect(x: 0,
274 | y: titleLabelMaxY + lowerLabel.font.lineHeight + self.spacing,
275 | width: commonWidth ,
276 | height: thumbSize )
277 |
278 | let lowerWidth = self.estimatelabelSize(font: lowerLabel.font, string: lowerLabel.text!, constrainedToWidth: Double(commonWidth)).width
279 | let upperWidth = self.estimatelabelSize(font: upperLabel.font, string: upperLabel.text!, constrainedToWidth: Double(commonWidth)).width
280 |
281 | var lowerLabelX : CGFloat = 0
282 | var upperLabelX : CGFloat = 0
283 |
284 |
285 | if self.thumbLabelStyle == .FOLLOW {
286 | lowerLabelX = rangeSlider.lowerThumbLayer.frame.midX - lowerWidth / 2
287 | upperLabelX = rangeSlider.upperThumbLayer.frame.midX - upperWidth / 2
288 | }
289 | else {
290 | // fix lower label to left and upper label to right
291 | lowerLabelX = rangeSlider.frame.origin.x + self.spacing
292 | upperLabelX = rangeSlider.frame.origin.x + rangeSlider.frame.size.width - thumbSize + self.spacing
293 | }
294 |
295 | lowerLabel.frame = CGRect( x: lowerLabelX,
296 | y: titleLabelMaxY,
297 | width: lowerWidth ,
298 | height: lowerLabel.font.lineHeight + self.spacing )
299 |
300 | upperLabel.frame = CGRect( x: upperLabelX,
301 | y: titleLabelMaxY,
302 | width: upperWidth ,
303 | height: upperLabel.font.lineHeight + self.spacing )
304 |
305 | }
306 |
307 | }
308 |
309 | // return the best size that fit within the box
310 | open override func sizeThatFits(_ size: CGSize) -> CGSize {
311 |
312 | if let titleLabel = self.titleLabel , let lowerLabel = self.lowerLabel {
313 |
314 | var height : CGFloat = 0
315 |
316 | var titleLabelMaxY : CGFloat = 0
317 |
318 | if !titleLabel.isHidden && titleLabel.text != nil && titleLabel.text!.characters.count > 0 {
319 | titleLabelMaxY = titleLabel.font.lineHeight + self.spacing
320 | }
321 |
322 | height = titleLabelMaxY + lowerLabel.font.lineHeight + self.spacing + thumbSize
323 |
324 | return CGSize(width: size.width, height: height)
325 |
326 | }
327 |
328 | return size
329 |
330 | }
331 |
332 | /// get size for string of this font
333 | ///
334 | /// - parameter font: font
335 | /// - parameter string: a string
336 | /// - parameter width: constrained width
337 | ///
338 | /// - returns: string size for constrained width
339 | private func estimatelabelSize(font: UIFont,string: String, constrainedToWidth width: Double) -> CGSize{
340 | return string.boundingRect(with: CGSize(width: width, height: DBL_MAX),
341 | options: NSStringDrawingOptions.usesLineFragmentOrigin,
342 | attributes: [NSFontAttributeName: font],
343 | context: nil).size
344 |
345 | }
346 |
347 |
348 | }
349 |
--------------------------------------------------------------------------------
/NHRangeSlider/NHRangeSlider/NHRangeSlider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NHRangeSlider.swift
3 | // NHRangeSlider
4 | //
5 | // Created by Hung on 17/12/16.
6 | // Copyright © 2016 Hung. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import QuartzCore
11 |
12 | /// Range slider track layer. Responsible for drawing the horizontal track
13 | public class RangeSliderTrackLayer: CALayer {
14 |
15 | /// owner slider
16 | weak var rangeSlider: NHRangeSlider?
17 |
18 | /// draw the track between 2 thumbs
19 | ///
20 | /// - Parameter ctx: current graphics context
21 | override open func draw(in ctx: CGContext) {
22 | guard let slider = rangeSlider else {
23 | return
24 | }
25 |
26 | // Clip
27 | let cornerRadius = bounds.height * slider.curvaceousness / 2.0
28 | let path = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius)
29 | ctx.addPath(path.cgPath)
30 |
31 | // Fill the track
32 | ctx.setFillColor(slider.trackTintColor.cgColor)
33 | ctx.addPath(path.cgPath)
34 | ctx.fillPath()
35 |
36 | // Fill the highlighted range
37 | ctx.setFillColor(slider.trackHighlightTintColor.cgColor)
38 | let lowerValuePosition = CGFloat(slider.positionForValue(slider.lowerValue))
39 | let upperValuePosition = CGFloat(slider.positionForValue(slider.upperValue))
40 | let rect = CGRect(x: lowerValuePosition, y: 0.0, width: upperValuePosition - lowerValuePosition, height: bounds.height)
41 | ctx.fill(rect)
42 | }
43 | }
44 |
45 | /// the thumb for upper , lower bounds
46 | public class RangeSliderThumbLayer: CALayer {
47 |
48 | /// owner slider
49 | weak var rangeSlider: NHRangeSlider?
50 |
51 | /// whether this thumb is currently highlighted i.e. touched by user
52 | public var highlighted: Bool = false {
53 | didSet {
54 | setNeedsDisplay()
55 | }
56 | }
57 |
58 | /// stroke color
59 | public var strokeColor: UIColor = UIColor.gray {
60 | didSet {
61 | setNeedsDisplay()
62 | }
63 | }
64 |
65 | /// line width
66 | public var lineWidth: CGFloat = 0.5 {
67 | didSet {
68 | setNeedsDisplay()
69 | }
70 | }
71 |
72 |
73 | /// draw the thumb
74 | ///
75 | /// - Parameter ctx: current graphics context
76 | override open func draw(in ctx: CGContext) {
77 | guard let slider = rangeSlider else {
78 | return
79 | }
80 |
81 | let thumbFrame = bounds.insetBy(dx: 2.0, dy: 2.0)
82 | let cornerRadius = thumbFrame.height * slider.curvaceousness / 2.0
83 | let thumbPath = UIBezierPath(roundedRect: thumbFrame, cornerRadius: cornerRadius)
84 |
85 | // Fill
86 | ctx.setFillColor(slider.thumbTintColor.cgColor)
87 | ctx.addPath(thumbPath.cgPath)
88 | ctx.fillPath()
89 |
90 | // Outline
91 | ctx.setStrokeColor(strokeColor.cgColor)
92 | ctx.setLineWidth(lineWidth)
93 | ctx.addPath(thumbPath.cgPath)
94 | ctx.strokePath()
95 |
96 | if highlighted {
97 | ctx.setFillColor(UIColor(white: 0.0, alpha: 0.1).cgColor)
98 | ctx.addPath(thumbPath.cgPath)
99 | ctx.fillPath()
100 | }
101 | }
102 | }
103 |
104 |
105 | /// Range slider view with upper, lower bounds
106 | @IBDesignable
107 | open class NHRangeSlider: UIControl {
108 |
109 | //MARK: properties
110 |
111 | /// minimum value
112 | @IBInspectable open var minimumValue: Double = 0.0 {
113 | willSet(newValue) {
114 | assert(newValue < maximumValue, "NHRangeSlider: minimumValue should be lower than maximumValue")
115 | }
116 | didSet {
117 | updateLayerFrames()
118 | }
119 | }
120 |
121 | /// max value
122 | @IBInspectable open var maximumValue: Double = 100.0 {
123 | willSet(newValue) {
124 | assert(newValue > minimumValue, "NHRangeSlider: maximumValue should be greater than minimumValue")
125 | }
126 | didSet {
127 | updateLayerFrames()
128 | }
129 | }
130 |
131 | /// value for lower thumb
132 | @IBInspectable open var lowerValue: Double = 0.0 {
133 | didSet {
134 | if lowerValue < minimumValue {
135 | lowerValue = minimumValue
136 | }
137 | updateLayerFrames()
138 | }
139 | }
140 |
141 | /// value for upper thumb
142 | @IBInspectable open var upperValue: Double = 100.0 {
143 | didSet {
144 | if upperValue > maximumValue {
145 | upperValue = maximumValue
146 | }
147 | updateLayerFrames()
148 | }
149 | }
150 |
151 |
152 | /// stepValue. If set, will snap to discrete step points along the slider . Default to nil
153 | @IBInspectable open var stepValue: Double? = nil {
154 | willSet(newValue) {
155 | if newValue != nil {
156 | assert(newValue! > 0, "NHRangeSlider: stepValue must be positive")
157 | }
158 | }
159 | didSet {
160 | if let val = stepValue {
161 | if val <= 0 {
162 | stepValue = nil
163 | }
164 | }
165 |
166 | updateLayerFrames()
167 | }
168 | }
169 |
170 |
171 |
172 | /// minimum distance between the upper and lower thumbs.
173 | @IBInspectable open var gapBetweenThumbs: Double = 2.0
174 |
175 | /// tint color for track between 2 thumbs
176 | @IBInspectable open var trackTintColor: UIColor = UIColor(white: 0.9, alpha: 1.0) {
177 | didSet {
178 | trackLayer.setNeedsDisplay()
179 | }
180 | }
181 |
182 | /// track highlight tint color
183 | @IBInspectable open var trackHighlightTintColor: UIColor = UIColor(red: 0.0, green: 0.45, blue: 0.94, alpha: 1.0) {
184 | didSet {
185 | trackLayer.setNeedsDisplay()
186 | }
187 | }
188 |
189 |
190 | /// thumb tint color
191 | @IBInspectable open var thumbTintColor: UIColor = UIColor.white {
192 | didSet {
193 | lowerThumbLayer.setNeedsDisplay()
194 | upperThumbLayer.setNeedsDisplay()
195 | }
196 | }
197 |
198 | /// thumb border color
199 | @IBInspectable open var thumbBorderColor: UIColor = UIColor.gray {
200 | didSet {
201 | lowerThumbLayer.strokeColor = thumbBorderColor
202 | upperThumbLayer.strokeColor = thumbBorderColor
203 | }
204 | }
205 |
206 |
207 | /// thumb border width
208 | @IBInspectable open var thumbBorderWidth: CGFloat = 0.5 {
209 | didSet {
210 | lowerThumbLayer.lineWidth = thumbBorderWidth
211 | upperThumbLayer.lineWidth = thumbBorderWidth
212 | }
213 | }
214 |
215 | /// set 0.0 for square thumbs to 1.0 for circle thumbs
216 | @IBInspectable open var curvaceousness: CGFloat = 1.0 {
217 | didSet {
218 | if curvaceousness < 0.0 {
219 | curvaceousness = 0.0
220 | }
221 |
222 | if curvaceousness > 1.0 {
223 | curvaceousness = 1.0
224 | }
225 |
226 | trackLayer.setNeedsDisplay()
227 | lowerThumbLayer.setNeedsDisplay()
228 | upperThumbLayer.setNeedsDisplay()
229 | }
230 | }
231 |
232 |
233 | /// previous touch location
234 | fileprivate var previouslocation = CGPoint()
235 |
236 | /// track layer
237 | fileprivate let trackLayer = RangeSliderTrackLayer()
238 |
239 | /// lower thumb layer
240 | public let lowerThumbLayer = RangeSliderThumbLayer()
241 |
242 | /// upper thumb layer
243 | public let upperThumbLayer = RangeSliderThumbLayer()
244 |
245 | /// thumb width
246 | fileprivate var thumbWidth: CGFloat {
247 | return CGFloat(bounds.height)
248 | }
249 |
250 | /// frame
251 | override open var frame: CGRect {
252 | didSet {
253 | updateLayerFrames()
254 | }
255 | }
256 |
257 | //MARK: init methods
258 | override public init(frame: CGRect) {
259 | super.init(frame: frame)
260 | initializeLayers()
261 | }
262 |
263 | required public init?(coder: NSCoder) {
264 | super.init(coder: coder)
265 | initializeLayers()
266 | }
267 |
268 | //MARK: layers
269 |
270 | /// layout sub layers
271 | ///
272 | /// - Parameter of: layer
273 | override open func layoutSublayers(of: CALayer) {
274 | super.layoutSublayers(of:layer)
275 | updateLayerFrames()
276 | }
277 |
278 | /// init layers
279 | fileprivate func initializeLayers() {
280 | layer.backgroundColor = UIColor.clear.cgColor
281 |
282 | trackLayer.rangeSlider = self
283 | trackLayer.contentsScale = UIScreen.main.scale
284 | layer.addSublayer(trackLayer)
285 |
286 | lowerThumbLayer.rangeSlider = self
287 | lowerThumbLayer.contentsScale = UIScreen.main.scale
288 | layer.addSublayer(lowerThumbLayer)
289 |
290 | upperThumbLayer.rangeSlider = self
291 | upperThumbLayer.contentsScale = UIScreen.main.scale
292 | layer.addSublayer(upperThumbLayer)
293 | }
294 |
295 | /// update layer frames
296 | open func updateLayerFrames() {
297 | CATransaction.begin()
298 | CATransaction.setDisableActions(true)
299 |
300 | trackLayer.frame = bounds.insetBy(dx: 0.0, dy: bounds.height/3)
301 | trackLayer.setNeedsDisplay()
302 |
303 | let lowerThumbCenter = CGFloat(positionForValue(lowerValue))
304 | lowerThumbLayer.frame = CGRect(x: lowerThumbCenter - thumbWidth/2.0, y: 0.0, width: thumbWidth, height: thumbWidth)
305 | lowerThumbLayer.setNeedsDisplay()
306 |
307 | let upperThumbCenter = CGFloat(positionForValue(upperValue))
308 | upperThumbLayer.frame = CGRect(x: upperThumbCenter - thumbWidth/2.0, y: 0.0, width: thumbWidth, height: thumbWidth)
309 | upperThumbLayer.setNeedsDisplay()
310 |
311 | CATransaction.commit()
312 | }
313 |
314 | /// thumb x position for new value
315 | open func positionForValue(_ value: Double) -> Double {
316 | if (maximumValue == minimumValue) {
317 | return 0
318 | }
319 |
320 | return Double(bounds.width - thumbWidth) * (value - minimumValue) / (maximumValue - minimumValue)
321 | + Double(thumbWidth/2.0)
322 | }
323 |
324 |
325 | /// bound new value within lower and upper value
326 | ///
327 | /// - Parameters:
328 | /// - value: value to set
329 | /// - lowerValue: lower value
330 | /// - upperValue: upper value
331 | /// - Returns: current value
332 | open func boundValue(_ value: Double, toLowerValue lowerValue: Double, upperValue: Double) -> Double {
333 | return min(max(value, lowerValue), upperValue)
334 | }
335 |
336 |
337 | // MARK: - Touches
338 |
339 | /// begin tracking
340 | override open func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
341 | previouslocation = touch.location(in: self)
342 |
343 | // set highlighted positions for lower and upper thumbs
344 | if lowerThumbLayer.frame.contains(previouslocation) {
345 | lowerThumbLayer.highlighted = true
346 | }
347 |
348 | if upperThumbLayer.frame.contains(previouslocation) {
349 | upperThumbLayer.highlighted = true
350 | }
351 |
352 | return lowerThumbLayer.highlighted || upperThumbLayer.highlighted
353 | }
354 |
355 | /// update positions for lower and upper thumbs
356 | override open func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
357 | let location = touch.location(in: self)
358 |
359 | // Determine by how much the user has dragged
360 | let deltaLocation = Double(location.x - previouslocation.x)
361 | var deltaValue : Double = 0
362 |
363 | if (bounds.width != bounds.height) {
364 | deltaValue = (maximumValue - minimumValue) * deltaLocation / Double(bounds.width - bounds.height)
365 | }
366 |
367 |
368 | previouslocation = location
369 |
370 | // if both are highlighted. we need to decide which direction to drag
371 | if lowerThumbLayer.highlighted && upperThumbLayer.highlighted {
372 |
373 | if deltaLocation > 0 {
374 | // left to right
375 | upperValue = boundValue(upperValue + deltaValue, toLowerValue: lowerValue + gapBetweenThumbs, upperValue: maximumValue)
376 | }
377 | else {
378 | // right to left
379 | lowerValue = boundValue(lowerValue + deltaValue, toLowerValue: minimumValue, upperValue: upperValue - gapBetweenThumbs)
380 | }
381 | }
382 | else {
383 |
384 | // Update the values
385 | if lowerThumbLayer.highlighted {
386 | lowerValue = boundValue(lowerValue + deltaValue, toLowerValue: minimumValue, upperValue: upperValue - gapBetweenThumbs)
387 | } else if upperThumbLayer.highlighted {
388 | upperValue = boundValue(upperValue + deltaValue, toLowerValue: lowerValue + gapBetweenThumbs, upperValue: maximumValue)
389 | }
390 | }
391 |
392 | // only send changed value if stepValue is not set. We will trigger this later in endTracking
393 | if stepValue == nil {
394 | sendActions(for: .valueChanged)
395 | }
396 |
397 | return true
398 | }
399 |
400 | /// end touch tracking. Unhighlight the two thumbs
401 | override open func endTracking(_ touch: UITouch?, with event: UIEvent?) {
402 | lowerThumbLayer.highlighted = false
403 | upperThumbLayer.highlighted = false
404 |
405 | // let slider snap after user stop dragging
406 | if let stepValue = stepValue {
407 | lowerValue = round(lowerValue / stepValue) * stepValue
408 | upperValue = round(upperValue / stepValue) * stepValue
409 | sendActions(for: .valueChanged)
410 | }
411 |
412 |
413 | }
414 |
415 | }
416 |
--------------------------------------------------------------------------------
/NHRangeSlider/NHRangeSlider.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | BDBEB38F1E06606100FE2D6F /* NHRangeSlider.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDBEB3851E06606100FE2D6F /* NHRangeSlider.framework */; };
11 | BDBEB3941E06606100FE2D6F /* NHRangeSliderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDBEB3931E06606100FE2D6F /* NHRangeSliderTests.swift */; };
12 | BDBEB3961E06606100FE2D6F /* NHRangeSlider.h in Headers */ = {isa = PBXBuildFile; fileRef = BDBEB3881E06606100FE2D6F /* NHRangeSlider.h */; settings = {ATTRIBUTES = (Public, ); }; };
13 | BDBEB3A11E06608900FE2D6F /* NHRangeSliderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDBEB39F1E06608900FE2D6F /* NHRangeSliderView.swift */; };
14 | BDBEB3A21E06608900FE2D6F /* NHRangeSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDBEB3A01E06608900FE2D6F /* NHRangeSlider.swift */; };
15 | /* End PBXBuildFile section */
16 |
17 | /* Begin PBXContainerItemProxy section */
18 | BDBEB3901E06606100FE2D6F /* PBXContainerItemProxy */ = {
19 | isa = PBXContainerItemProxy;
20 | containerPortal = BDBEB37C1E06606100FE2D6F /* Project object */;
21 | proxyType = 1;
22 | remoteGlobalIDString = BDBEB3841E06606100FE2D6F;
23 | remoteInfo = NHRangeSlider;
24 | };
25 | /* End PBXContainerItemProxy section */
26 |
27 | /* Begin PBXFileReference section */
28 | BDBEB3851E06606100FE2D6F /* NHRangeSlider.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NHRangeSlider.framework; sourceTree = BUILT_PRODUCTS_DIR; };
29 | BDBEB3881E06606100FE2D6F /* NHRangeSlider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NHRangeSlider.h; sourceTree = ""; };
30 | BDBEB3891E06606100FE2D6F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
31 | BDBEB38E1E06606100FE2D6F /* NHRangeSliderTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NHRangeSliderTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
32 | BDBEB3931E06606100FE2D6F /* NHRangeSliderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NHRangeSliderTests.swift; sourceTree = ""; };
33 | BDBEB3951E06606100FE2D6F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
34 | BDBEB39F1E06608900FE2D6F /* NHRangeSliderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NHRangeSliderView.swift; sourceTree = ""; };
35 | BDBEB3A01E06608900FE2D6F /* NHRangeSlider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NHRangeSlider.swift; sourceTree = ""; };
36 | /* End PBXFileReference section */
37 |
38 | /* Begin PBXFrameworksBuildPhase section */
39 | BDBEB3811E06606100FE2D6F /* Frameworks */ = {
40 | isa = PBXFrameworksBuildPhase;
41 | buildActionMask = 2147483647;
42 | files = (
43 | );
44 | runOnlyForDeploymentPostprocessing = 0;
45 | };
46 | BDBEB38B1E06606100FE2D6F /* Frameworks */ = {
47 | isa = PBXFrameworksBuildPhase;
48 | buildActionMask = 2147483647;
49 | files = (
50 | BDBEB38F1E06606100FE2D6F /* NHRangeSlider.framework in Frameworks */,
51 | );
52 | runOnlyForDeploymentPostprocessing = 0;
53 | };
54 | /* End PBXFrameworksBuildPhase section */
55 |
56 | /* Begin PBXGroup section */
57 | BDBEB37B1E06606100FE2D6F = {
58 | isa = PBXGroup;
59 | children = (
60 | BDBEB3871E06606100FE2D6F /* NHRangeSlider */,
61 | BDBEB3921E06606100FE2D6F /* NHRangeSliderTests */,
62 | BDBEB3861E06606100FE2D6F /* Products */,
63 | );
64 | sourceTree = "";
65 | };
66 | BDBEB3861E06606100FE2D6F /* Products */ = {
67 | isa = PBXGroup;
68 | children = (
69 | BDBEB3851E06606100FE2D6F /* NHRangeSlider.framework */,
70 | BDBEB38E1E06606100FE2D6F /* NHRangeSliderTests.xctest */,
71 | );
72 | name = Products;
73 | sourceTree = "";
74 | };
75 | BDBEB3871E06606100FE2D6F /* NHRangeSlider */ = {
76 | isa = PBXGroup;
77 | children = (
78 | BDBEB39F1E06608900FE2D6F /* NHRangeSliderView.swift */,
79 | BDBEB3A01E06608900FE2D6F /* NHRangeSlider.swift */,
80 | BDBEB3881E06606100FE2D6F /* NHRangeSlider.h */,
81 | BDBEB3891E06606100FE2D6F /* Info.plist */,
82 | );
83 | path = NHRangeSlider;
84 | sourceTree = "";
85 | };
86 | BDBEB3921E06606100FE2D6F /* NHRangeSliderTests */ = {
87 | isa = PBXGroup;
88 | children = (
89 | BDBEB3931E06606100FE2D6F /* NHRangeSliderTests.swift */,
90 | BDBEB3951E06606100FE2D6F /* Info.plist */,
91 | );
92 | path = NHRangeSliderTests;
93 | sourceTree = "";
94 | };
95 | /* End PBXGroup section */
96 |
97 | /* Begin PBXHeadersBuildPhase section */
98 | BDBEB3821E06606100FE2D6F /* Headers */ = {
99 | isa = PBXHeadersBuildPhase;
100 | buildActionMask = 2147483647;
101 | files = (
102 | BDBEB3961E06606100FE2D6F /* NHRangeSlider.h in Headers */,
103 | );
104 | runOnlyForDeploymentPostprocessing = 0;
105 | };
106 | /* End PBXHeadersBuildPhase section */
107 |
108 | /* Begin PBXNativeTarget section */
109 | BDBEB3841E06606100FE2D6F /* NHRangeSlider */ = {
110 | isa = PBXNativeTarget;
111 | buildConfigurationList = BDBEB3991E06606100FE2D6F /* Build configuration list for PBXNativeTarget "NHRangeSlider" */;
112 | buildPhases = (
113 | BDBEB3801E06606100FE2D6F /* Sources */,
114 | BDBEB3811E06606100FE2D6F /* Frameworks */,
115 | BDBEB3821E06606100FE2D6F /* Headers */,
116 | BDBEB3831E06606100FE2D6F /* Resources */,
117 | );
118 | buildRules = (
119 | );
120 | dependencies = (
121 | );
122 | name = NHRangeSlider;
123 | productName = NHRangeSlider;
124 | productReference = BDBEB3851E06606100FE2D6F /* NHRangeSlider.framework */;
125 | productType = "com.apple.product-type.framework";
126 | };
127 | BDBEB38D1E06606100FE2D6F /* NHRangeSliderTests */ = {
128 | isa = PBXNativeTarget;
129 | buildConfigurationList = BDBEB39C1E06606100FE2D6F /* Build configuration list for PBXNativeTarget "NHRangeSliderTests" */;
130 | buildPhases = (
131 | BDBEB38A1E06606100FE2D6F /* Sources */,
132 | BDBEB38B1E06606100FE2D6F /* Frameworks */,
133 | BDBEB38C1E06606100FE2D6F /* Resources */,
134 | );
135 | buildRules = (
136 | );
137 | dependencies = (
138 | BDBEB3911E06606100FE2D6F /* PBXTargetDependency */,
139 | );
140 | name = NHRangeSliderTests;
141 | productName = NHRangeSliderTests;
142 | productReference = BDBEB38E1E06606100FE2D6F /* NHRangeSliderTests.xctest */;
143 | productType = "com.apple.product-type.bundle.unit-test";
144 | };
145 | /* End PBXNativeTarget section */
146 |
147 | /* Begin PBXProject section */
148 | BDBEB37C1E06606100FE2D6F /* Project object */ = {
149 | isa = PBXProject;
150 | attributes = {
151 | LastSwiftUpdateCheck = 0820;
152 | LastUpgradeCheck = 0820;
153 | ORGANIZATIONNAME = Hung;
154 | TargetAttributes = {
155 | BDBEB3841E06606100FE2D6F = {
156 | CreatedOnToolsVersion = 8.2;
157 | DevelopmentTeam = NKN6QECX9M;
158 | LastSwiftMigration = 0820;
159 | ProvisioningStyle = Automatic;
160 | };
161 | BDBEB38D1E06606100FE2D6F = {
162 | CreatedOnToolsVersion = 8.2;
163 | DevelopmentTeam = NKN6QECX9M;
164 | ProvisioningStyle = Automatic;
165 | };
166 | };
167 | };
168 | buildConfigurationList = BDBEB37F1E06606100FE2D6F /* Build configuration list for PBXProject "NHRangeSlider" */;
169 | compatibilityVersion = "Xcode 3.2";
170 | developmentRegion = English;
171 | hasScannedForEncodings = 0;
172 | knownRegions = (
173 | en,
174 | );
175 | mainGroup = BDBEB37B1E06606100FE2D6F;
176 | productRefGroup = BDBEB3861E06606100FE2D6F /* Products */;
177 | projectDirPath = "";
178 | projectRoot = "";
179 | targets = (
180 | BDBEB3841E06606100FE2D6F /* NHRangeSlider */,
181 | BDBEB38D1E06606100FE2D6F /* NHRangeSliderTests */,
182 | );
183 | };
184 | /* End PBXProject section */
185 |
186 | /* Begin PBXResourcesBuildPhase section */
187 | BDBEB3831E06606100FE2D6F /* Resources */ = {
188 | isa = PBXResourcesBuildPhase;
189 | buildActionMask = 2147483647;
190 | files = (
191 | );
192 | runOnlyForDeploymentPostprocessing = 0;
193 | };
194 | BDBEB38C1E06606100FE2D6F /* Resources */ = {
195 | isa = PBXResourcesBuildPhase;
196 | buildActionMask = 2147483647;
197 | files = (
198 | );
199 | runOnlyForDeploymentPostprocessing = 0;
200 | };
201 | /* End PBXResourcesBuildPhase section */
202 |
203 | /* Begin PBXSourcesBuildPhase section */
204 | BDBEB3801E06606100FE2D6F /* Sources */ = {
205 | isa = PBXSourcesBuildPhase;
206 | buildActionMask = 2147483647;
207 | files = (
208 | BDBEB3A21E06608900FE2D6F /* NHRangeSlider.swift in Sources */,
209 | BDBEB3A11E06608900FE2D6F /* NHRangeSliderView.swift in Sources */,
210 | );
211 | runOnlyForDeploymentPostprocessing = 0;
212 | };
213 | BDBEB38A1E06606100FE2D6F /* Sources */ = {
214 | isa = PBXSourcesBuildPhase;
215 | buildActionMask = 2147483647;
216 | files = (
217 | BDBEB3941E06606100FE2D6F /* NHRangeSliderTests.swift in Sources */,
218 | );
219 | runOnlyForDeploymentPostprocessing = 0;
220 | };
221 | /* End PBXSourcesBuildPhase section */
222 |
223 | /* Begin PBXTargetDependency section */
224 | BDBEB3911E06606100FE2D6F /* PBXTargetDependency */ = {
225 | isa = PBXTargetDependency;
226 | target = BDBEB3841E06606100FE2D6F /* NHRangeSlider */;
227 | targetProxy = BDBEB3901E06606100FE2D6F /* PBXContainerItemProxy */;
228 | };
229 | /* End PBXTargetDependency section */
230 |
231 | /* Begin XCBuildConfiguration section */
232 | BDBEB3971E06606100FE2D6F /* Debug */ = {
233 | isa = XCBuildConfiguration;
234 | buildSettings = {
235 | ALWAYS_SEARCH_USER_PATHS = NO;
236 | CLANG_ANALYZER_NONNULL = YES;
237 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
238 | CLANG_CXX_LIBRARY = "libc++";
239 | CLANG_ENABLE_MODULES = YES;
240 | CLANG_ENABLE_OBJC_ARC = YES;
241 | CLANG_WARN_BOOL_CONVERSION = YES;
242 | CLANG_WARN_CONSTANT_CONVERSION = YES;
243 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
244 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
245 | CLANG_WARN_EMPTY_BODY = YES;
246 | CLANG_WARN_ENUM_CONVERSION = YES;
247 | CLANG_WARN_INFINITE_RECURSION = YES;
248 | CLANG_WARN_INT_CONVERSION = YES;
249 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
250 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
251 | CLANG_WARN_UNREACHABLE_CODE = YES;
252 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
253 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
254 | COPY_PHASE_STRIP = NO;
255 | CURRENT_PROJECT_VERSION = 1;
256 | DEBUG_INFORMATION_FORMAT = dwarf;
257 | ENABLE_STRICT_OBJC_MSGSEND = YES;
258 | ENABLE_TESTABILITY = YES;
259 | GCC_C_LANGUAGE_STANDARD = gnu99;
260 | GCC_DYNAMIC_NO_PIC = NO;
261 | GCC_NO_COMMON_BLOCKS = YES;
262 | GCC_OPTIMIZATION_LEVEL = 0;
263 | GCC_PREPROCESSOR_DEFINITIONS = (
264 | "DEBUG=1",
265 | "$(inherited)",
266 | );
267 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
268 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
269 | GCC_WARN_UNDECLARED_SELECTOR = YES;
270 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
271 | GCC_WARN_UNUSED_FUNCTION = YES;
272 | GCC_WARN_UNUSED_VARIABLE = YES;
273 | IPHONEOS_DEPLOYMENT_TARGET = 10.2;
274 | MTL_ENABLE_DEBUG_INFO = YES;
275 | ONLY_ACTIVE_ARCH = YES;
276 | SDKROOT = iphoneos;
277 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
278 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
279 | TARGETED_DEVICE_FAMILY = "1,2";
280 | VERSIONING_SYSTEM = "apple-generic";
281 | VERSION_INFO_PREFIX = "";
282 | };
283 | name = Debug;
284 | };
285 | BDBEB3981E06606100FE2D6F /* Release */ = {
286 | isa = XCBuildConfiguration;
287 | buildSettings = {
288 | ALWAYS_SEARCH_USER_PATHS = NO;
289 | CLANG_ANALYZER_NONNULL = YES;
290 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
291 | CLANG_CXX_LIBRARY = "libc++";
292 | CLANG_ENABLE_MODULES = YES;
293 | CLANG_ENABLE_OBJC_ARC = YES;
294 | CLANG_WARN_BOOL_CONVERSION = YES;
295 | CLANG_WARN_CONSTANT_CONVERSION = YES;
296 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
297 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
298 | CLANG_WARN_EMPTY_BODY = YES;
299 | CLANG_WARN_ENUM_CONVERSION = YES;
300 | CLANG_WARN_INFINITE_RECURSION = YES;
301 | CLANG_WARN_INT_CONVERSION = YES;
302 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
303 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
304 | CLANG_WARN_UNREACHABLE_CODE = YES;
305 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
306 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
307 | COPY_PHASE_STRIP = NO;
308 | CURRENT_PROJECT_VERSION = 1;
309 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
310 | ENABLE_NS_ASSERTIONS = NO;
311 | ENABLE_STRICT_OBJC_MSGSEND = YES;
312 | GCC_C_LANGUAGE_STANDARD = gnu99;
313 | GCC_NO_COMMON_BLOCKS = YES;
314 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
315 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
316 | GCC_WARN_UNDECLARED_SELECTOR = YES;
317 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
318 | GCC_WARN_UNUSED_FUNCTION = YES;
319 | GCC_WARN_UNUSED_VARIABLE = YES;
320 | IPHONEOS_DEPLOYMENT_TARGET = 10.2;
321 | MTL_ENABLE_DEBUG_INFO = NO;
322 | SDKROOT = iphoneos;
323 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
324 | TARGETED_DEVICE_FAMILY = "1,2";
325 | VALIDATE_PRODUCT = YES;
326 | VERSIONING_SYSTEM = "apple-generic";
327 | VERSION_INFO_PREFIX = "";
328 | };
329 | name = Release;
330 | };
331 | BDBEB39A1E06606100FE2D6F /* Debug */ = {
332 | isa = XCBuildConfiguration;
333 | buildSettings = {
334 | CLANG_ENABLE_MODULES = YES;
335 | CODE_SIGN_IDENTITY = "";
336 | DEFINES_MODULE = YES;
337 | DEVELOPMENT_TEAM = NKN6QECX9M;
338 | DYLIB_COMPATIBILITY_VERSION = 1;
339 | DYLIB_CURRENT_VERSION = 1;
340 | DYLIB_INSTALL_NAME_BASE = "@rpath";
341 | INFOPLIST_FILE = NHRangeSlider/Info.plist;
342 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
343 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
344 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
345 | PRODUCT_BUNDLE_IDENTIFIER = com.ngohung.NHRangeSlider;
346 | PRODUCT_NAME = "$(TARGET_NAME)";
347 | SKIP_INSTALL = YES;
348 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
349 | SWIFT_VERSION = 3.0;
350 | };
351 | name = Debug;
352 | };
353 | BDBEB39B1E06606100FE2D6F /* Release */ = {
354 | isa = XCBuildConfiguration;
355 | buildSettings = {
356 | CLANG_ENABLE_MODULES = YES;
357 | CODE_SIGN_IDENTITY = "";
358 | DEFINES_MODULE = YES;
359 | DEVELOPMENT_TEAM = NKN6QECX9M;
360 | DYLIB_COMPATIBILITY_VERSION = 1;
361 | DYLIB_CURRENT_VERSION = 1;
362 | DYLIB_INSTALL_NAME_BASE = "@rpath";
363 | INFOPLIST_FILE = NHRangeSlider/Info.plist;
364 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
365 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
366 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
367 | PRODUCT_BUNDLE_IDENTIFIER = com.ngohung.NHRangeSlider;
368 | PRODUCT_NAME = "$(TARGET_NAME)";
369 | SKIP_INSTALL = YES;
370 | SWIFT_VERSION = 3.0;
371 | };
372 | name = Release;
373 | };
374 | BDBEB39D1E06606100FE2D6F /* Debug */ = {
375 | isa = XCBuildConfiguration;
376 | buildSettings = {
377 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
378 | DEVELOPMENT_TEAM = NKN6QECX9M;
379 | INFOPLIST_FILE = NHRangeSliderTests/Info.plist;
380 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
381 | PRODUCT_BUNDLE_IDENTIFIER = com.ngohung.NHRangeSliderTests;
382 | PRODUCT_NAME = "$(TARGET_NAME)";
383 | SWIFT_VERSION = 3.0;
384 | };
385 | name = Debug;
386 | };
387 | BDBEB39E1E06606100FE2D6F /* Release */ = {
388 | isa = XCBuildConfiguration;
389 | buildSettings = {
390 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
391 | DEVELOPMENT_TEAM = NKN6QECX9M;
392 | INFOPLIST_FILE = NHRangeSliderTests/Info.plist;
393 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
394 | PRODUCT_BUNDLE_IDENTIFIER = com.ngohung.NHRangeSliderTests;
395 | PRODUCT_NAME = "$(TARGET_NAME)";
396 | SWIFT_VERSION = 3.0;
397 | };
398 | name = Release;
399 | };
400 | /* End XCBuildConfiguration section */
401 |
402 | /* Begin XCConfigurationList section */
403 | BDBEB37F1E06606100FE2D6F /* Build configuration list for PBXProject "NHRangeSlider" */ = {
404 | isa = XCConfigurationList;
405 | buildConfigurations = (
406 | BDBEB3971E06606100FE2D6F /* Debug */,
407 | BDBEB3981E06606100FE2D6F /* Release */,
408 | );
409 | defaultConfigurationIsVisible = 0;
410 | defaultConfigurationName = Release;
411 | };
412 | BDBEB3991E06606100FE2D6F /* Build configuration list for PBXNativeTarget "NHRangeSlider" */ = {
413 | isa = XCConfigurationList;
414 | buildConfigurations = (
415 | BDBEB39A1E06606100FE2D6F /* Debug */,
416 | BDBEB39B1E06606100FE2D6F /* Release */,
417 | );
418 | defaultConfigurationIsVisible = 0;
419 | defaultConfigurationName = Release;
420 | };
421 | BDBEB39C1E06606100FE2D6F /* Build configuration list for PBXNativeTarget "NHRangeSliderTests" */ = {
422 | isa = XCConfigurationList;
423 | buildConfigurations = (
424 | BDBEB39D1E06606100FE2D6F /* Debug */,
425 | BDBEB39E1E06606100FE2D6F /* Release */,
426 | );
427 | defaultConfigurationIsVisible = 0;
428 | defaultConfigurationName = Release;
429 | };
430 | /* End XCConfigurationList section */
431 | };
432 | rootObject = BDBEB37C1E06606100FE2D6F /* Project object */;
433 | }
434 |
--------------------------------------------------------------------------------