├── .gitignore ├── ACVRangeSelector ├── ACVRangeSelector.bundle │ └── Images │ │ ├── connector.png │ │ ├── connector@2x.png │ │ ├── handle.png │ │ ├── handle@2x.png │ │ ├── pointer-handle.png │ │ ├── pointer-handle@2x.png │ │ ├── track.png │ │ └── track@2x.png ├── ACVRangeSelector.h └── ACVRangeSelector.m ├── LICENSE.markdown ├── README.markdown ├── SampleApp └── RangeSelectorSample │ ├── RangeSelectorSample.xcodeproj │ └── project.pbxproj │ └── RangeSelectorSample │ ├── ACVAppDelegate.h │ ├── ACVAppDelegate.m │ ├── ACVViewController.h │ ├── ACVViewController.m │ ├── Default-568h@2x.png │ ├── Default.png │ ├── Default@2x.png │ ├── Images │ ├── Icon.png │ ├── Icon72.png │ ├── connector.png │ ├── left-handle.png │ ├── middle-handle.png │ └── right-handle.png │ ├── RangeSelectorSample-Info.plist │ ├── RangeSelectorSample-Prefix.pch │ ├── en.lproj │ ├── ACVViewController_iPad.xib │ ├── ACVViewController_iPhone.xib │ └── InfoPlist.strings │ └── main.m └── sample.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore patterns 2 | *.pyc 3 | *.swp 4 | 5 | # xcode noise 6 | build 7 | *.pbxuser 8 | *.mode1v3 9 | *.mode2v3 10 | !default.pbxuser 11 | !default.mode1v3 12 | !default.mode2v3 13 | xcuserdata 14 | *.perspective 15 | *.perspectivev3 16 | 17 | *~.nib 18 | *~.xib 19 | 20 | # old skool 21 | .svn 22 | 23 | # osx noise 24 | .DS_Store 25 | profile 26 | 27 | *.xcworkspace -------------------------------------------------------------------------------- /ACVRangeSelector/ACVRangeSelector.bundle/Images/connector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/ACVRangeSelector/ACVRangeSelector.bundle/Images/connector.png -------------------------------------------------------------------------------- /ACVRangeSelector/ACVRangeSelector.bundle/Images/connector@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/ACVRangeSelector/ACVRangeSelector.bundle/Images/connector@2x.png -------------------------------------------------------------------------------- /ACVRangeSelector/ACVRangeSelector.bundle/Images/handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/ACVRangeSelector/ACVRangeSelector.bundle/Images/handle.png -------------------------------------------------------------------------------- /ACVRangeSelector/ACVRangeSelector.bundle/Images/handle@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/ACVRangeSelector/ACVRangeSelector.bundle/Images/handle@2x.png -------------------------------------------------------------------------------- /ACVRangeSelector/ACVRangeSelector.bundle/Images/pointer-handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/ACVRangeSelector/ACVRangeSelector.bundle/Images/pointer-handle.png -------------------------------------------------------------------------------- /ACVRangeSelector/ACVRangeSelector.bundle/Images/pointer-handle@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/ACVRangeSelector/ACVRangeSelector.bundle/Images/pointer-handle@2x.png -------------------------------------------------------------------------------- /ACVRangeSelector/ACVRangeSelector.bundle/Images/track.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/ACVRangeSelector/ACVRangeSelector.bundle/Images/track.png -------------------------------------------------------------------------------- /ACVRangeSelector/ACVRangeSelector.bundle/Images/track@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/ACVRangeSelector/ACVRangeSelector.bundle/Images/track@2x.png -------------------------------------------------------------------------------- /ACVRangeSelector/ACVRangeSelector.h: -------------------------------------------------------------------------------- 1 | // 2 | // RangeSelectControl.h 3 | // FunBox 4 | // 5 | // Created by Antonio Cabezuelo Vivo on 28/11/12. 6 | // 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, TrackingThumb) { 12 | TrackingNone, 13 | TrackingLeftThumb, 14 | TrackingRightThumb, 15 | TrackingMiddleThumb, 16 | }; 17 | 18 | 19 | @interface ACVRangeSelector : UIControl 20 | 21 | @property (assign, nonatomic) CGFloat minimumValue; // Defaults to 0 22 | @property (assign, nonatomic) CGFloat maximumValue; // Defaults to 100 23 | 24 | @property (assign, nonatomic) CGFloat leftValue; 25 | @property (assign, nonatomic) CGFloat rightValue; 26 | @property (assign, nonatomic) CGFloat middleValue; 27 | 28 | @property (assign, nonatomic) NSInteger leftPointerOffset; // Distance from the left border to the left ponter 29 | @property (assign, nonatomic) NSInteger rightPointerOffset; // Distance from the right border to the right pointer 30 | @property (assign, nonatomic) NSInteger connectionOffset; // Number of points that the connections overlap with handles. Connections are always positioned below the handles. 31 | 32 | @property (assign, nonatomic) TrackingThumb trackingThumb; // The thumb currently being tracked 33 | 34 | @property (assign, nonatomic) BOOL scaleMiddleThumb; // If the left and right thumbs overlap middle thumb, this is scaled. Default to YES 35 | 36 | @property (strong, nonatomic) UIImage *trackImage UI_APPEARANCE_SELECTOR; // Image to be used for the track background. Should be horizontally resizable 37 | 38 | - (void)setLeftThumbImage:(UIImage*)image forState:(UIControlState)state UI_APPEARANCE_SELECTOR; 39 | - (void)setRightThumbImage:(UIImage*)image forState:(UIControlState)state UI_APPEARANCE_SELECTOR; 40 | - (void)setMiddleThumbImage:(UIImage*)image forState:(UIControlState)state UI_APPEARANCE_SELECTOR; 41 | - (void)setConnectionImage:(UIImage*)image forState:(UIControlState)state UI_APPEARANCE_SELECTOR; 42 | 43 | - (UIImage*)leftThumbImageForState:(UIControlState)state; 44 | - (UIImage*)rightThumbImageForState:(UIControlState)state; 45 | - (UIImage*)middleThumbImageForState:(UIControlState)state; 46 | - (UIImage*)connectionImageForState:(UIControlState)state; 47 | 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /ACVRangeSelector/ACVRangeSelector.m: -------------------------------------------------------------------------------- 1 | // 2 | // RangeSelectControl.m 3 | // FunBox 4 | // 5 | // Created by Antonio Cabezuelo Vivo on 28/11/12. 6 | // 7 | // 8 | 9 | #import "ACVRangeSelector.h" 10 | 11 | #if !__has_feature(objc_arc) 12 | #error ACVRangeSelector must be built with ARC. 13 | // You can turn on ARC for only ACVRangeSelector files by adding -fobjc-arc to the build phase for each of its files. 14 | #endif 15 | 16 | #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0 17 | #error ACVRangeSelector needs a deployment target of 5.0+ 18 | #endif 19 | 20 | static NSString * const kLeftThumbImage = @"leftThumbImage"; 21 | static NSString * const kRightThumbImage = @"rightThumbImage"; 22 | static NSString * const kMiddleThumbImage = @"middleThumbImage"; 23 | static NSString * const kConnectionImage = @"connectionImage"; 24 | 25 | 26 | 27 | @interface ACVRangeSelector () 28 | @property (assign, readonly, nonatomic) CGFloat distance; 29 | @property (strong, nonatomic) NSMutableDictionary* statesData; 30 | @property (weak, nonatomic) UIImageView *leftThumbImageView; 31 | @property (weak, nonatomic) UIImageView *rightThumbImageView; 32 | @property (weak, nonatomic) UIImageView *middleThumbImageView; 33 | @property (weak, nonatomic) UIImageView *leftConnectionImageView; 34 | @property (weak, nonatomic) UIImageView *rightConnectionImageView; 35 | @end 36 | 37 | 38 | @implementation ACVRangeSelector { 39 | CGFloat _startTrackingValue; 40 | CGPoint _startLocation; 41 | } 42 | 43 | #pragma mark - Initialization 44 | 45 | - (void)commonSetup { 46 | UIImageView *iV; 47 | 48 | self.backgroundColor = [UIColor clearColor]; 49 | _minimumValue = 0; 50 | _maximumValue = 100; 51 | _leftValue = 0; 52 | _rightValue = 100; 53 | _scaleMiddleThumb = YES; 54 | 55 | self.statesData = [[NSMutableDictionary alloc] init]; 56 | 57 | iV = [[UIImageView alloc] initWithFrame:CGRectZero]; 58 | [self addSubview:iV]; 59 | self.leftConnectionImageView = iV; 60 | 61 | iV = [[UIImageView alloc] initWithFrame:CGRectZero]; 62 | [self addSubview:iV]; 63 | self.rightConnectionImageView = iV; 64 | 65 | iV = [[UIImageView alloc] initWithFrame:CGRectZero]; 66 | [self addSubview:iV]; 67 | self.leftThumbImageView = iV; 68 | 69 | iV = [[UIImageView alloc] initWithFrame:CGRectZero]; 70 | [self addSubview:iV]; 71 | self.rightThumbImageView = iV; 72 | 73 | iV = [[UIImageView alloc] initWithFrame:CGRectZero]; 74 | [self addSubview:iV]; 75 | self.middleThumbImageView = iV; 76 | 77 | NSBundle *selectorBundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"ACVRangeSelector" ofType:@"bundle"]]; 78 | 79 | if (selectorBundle) { 80 | _leftPointerOffset = 11; 81 | _rightPointerOffset = 11; 82 | _connectionOffset = 2; 83 | 84 | _trackImage = [[UIImage imageNamed:@"ACVRangeSelector.bundle/Images/track.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 3, 0, 3)]; 85 | 86 | NSMutableDictionary *data = [self dataForState:UIControlStateNormal create:YES]; 87 | data[kLeftThumbImage] = [UIImage imageNamed:@"ACVRangeSelector.bundle/Images/pointer-handle.png"]; 88 | data[kRightThumbImage] = [UIImage imageNamed:@"ACVRangeSelector.bundle/Images/pointer-handle.png"]; 89 | data[kMiddleThumbImage] = [UIImage imageNamed:@"ACVRangeSelector.bundle/Images/handle.png"]; 90 | data[kConnectionImage] = [[UIImage imageNamed:@"ACVRangeSelector.bundle/Images/connector.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 4, 0, 4)]; 91 | } 92 | } 93 | 94 | - (id)initWithFrame:(CGRect)frame 95 | { 96 | self = [super initWithFrame:frame]; 97 | if (self) { 98 | [self commonSetup]; 99 | } 100 | return self; 101 | } 102 | 103 | - (id)initWithCoder:(NSCoder *)decoder { 104 | self = [super initWithCoder: decoder]; 105 | if (self != nil) { 106 | [self commonSetup]; 107 | 108 | if ([decoder containsValueForKey:@"leftValue"]) 109 | self.leftValue = [decoder decodeFloatForKey:@"leftValue"]; 110 | if ([decoder containsValueForKey:@"rightValue"]) 111 | self.rightValue = [decoder decodeFloatForKey:@"rightValue"]; 112 | if ([decoder containsValueForKey:@"middleValue"]) 113 | self.middleValue = [decoder decodeFloatForKey:@"middleValue"]; 114 | if ([decoder containsValueForKey:@"minimumValue"]) 115 | self.minimumValue = [decoder decodeFloatForKey:@"minimumValue"]; 116 | if ([decoder containsValueForKey:@"maximumValue"]) 117 | self.maximumValue = [decoder decodeFloatForKey:@"maximumValue"]; 118 | if ([decoder containsValueForKey:@"leftPointerOffset"]) 119 | self.leftPointerOffset = [decoder decodeFloatForKey:@"leftPointerOffset"]; 120 | if ([decoder containsValueForKey:@"rightPointerOffset"]) 121 | self.rightPointerOffset = [decoder decodeFloatForKey:@"rightPointerOffset"]; 122 | if ([decoder containsValueForKey:@"connectionOffset"]) 123 | self.rightPointerOffset = [decoder decodeFloatForKey:@"connectionOffset"]; 124 | 125 | } 126 | return self; 127 | } 128 | 129 | - (void)encodeWithCoder:(NSCoder *)encoder { 130 | [super encodeWithCoder:encoder]; 131 | [encoder encodeFloat:self.leftValue forKey:@"leftValue"]; 132 | [encoder encodeFloat:self.rightValue forKey:@"rightValue"]; 133 | [encoder encodeFloat:self.middleValue forKey:@"middleValue"]; 134 | [encoder encodeFloat:self.minimumValue forKey:@"minimumValue"]; 135 | [encoder encodeFloat:self.maximumValue forKey:@"maximumValue"]; 136 | [encoder encodeInteger:self.leftPointerOffset forKey:@"leftPointerOffset"]; 137 | [encoder encodeInteger:self.rightPointerOffset forKey:@"rightPointerOffset"]; 138 | [encoder encodeInteger:self.connectionOffset forKey:@"connectionOffset"]; 139 | } 140 | 141 | #pragma mark - 142 | 143 | - (void)setEnabled:(BOOL)enabled { 144 | [super setEnabled:enabled]; 145 | [self updateUI]; 146 | } 147 | 148 | - (void)setSelected:(BOOL)selected { 149 | if (selected != self.isSelected) { 150 | [super setSelected:selected]; 151 | [self updateUI]; 152 | } 153 | } 154 | 155 | 156 | - (void)setHighlighted:(BOOL)highlighted { 157 | if (highlighted != self.isHighlighted) { 158 | [super setHighlighted:highlighted]; 159 | [self updateUI]; 160 | } 161 | } 162 | 163 | #pragma mark - 164 | 165 | - (void)setLeftThumbImage:(UIImage*)image forState:(UIControlState)state { 166 | NSMutableDictionary *data = [self dataForState:state create:YES]; 167 | if (image) { 168 | data[kLeftThumbImage] = image; 169 | } else { 170 | [data removeObjectForKey:kLeftThumbImage]; 171 | } 172 | 173 | [self updateUI]; 174 | } 175 | 176 | - (void)setRightThumbImage:(UIImage*)image forState:(UIControlState)state { 177 | NSMutableDictionary *data = [self dataForState:state create:YES]; 178 | if (image) { 179 | data[kRightThumbImage] = image; 180 | } else { 181 | [data removeObjectForKey:kRightThumbImage]; 182 | } 183 | [self updateUI]; 184 | } 185 | 186 | - (void)setMiddleThumbImage:(UIImage*)image forState:(UIControlState)state { 187 | NSMutableDictionary *data = [self dataForState:state create:YES]; 188 | if (image) { 189 | data[kMiddleThumbImage] = image; 190 | } else { 191 | [data removeObjectForKey:kMiddleThumbImage]; 192 | } 193 | [self updateUI]; 194 | } 195 | 196 | - (void)setConnectionImage:(UIImage*)image forState:(UIControlState)state { 197 | NSMutableDictionary *data = [self dataForState:state create:YES]; 198 | if (image) { 199 | data[kConnectionImage] = image; 200 | } else { 201 | [data removeObjectForKey:kConnectionImage]; 202 | } 203 | [self updateUI]; 204 | } 205 | 206 | - (UIImage*)leftThumbImageForState:(UIControlState)state { 207 | UIControlState lookupState = state != UIControlStateHighlighted || (state == UIControlStateHighlighted && self.trackingThumb == TrackingLeftThumb) ? state : UIControlStateNormal; 208 | return [self dataForState:lookupState][kLeftThumbImage]; 209 | } 210 | 211 | - (UIImage*)rightThumbImageForState:(UIControlState)state { 212 | UIControlState lookupState = state != UIControlStateHighlighted || (state == UIControlStateHighlighted && self.trackingThumb == TrackingRightThumb) ? state : UIControlStateNormal; 213 | return [self dataForState:lookupState][kRightThumbImage]; 214 | } 215 | 216 | - (UIImage*)middleThumbImageForState:(UIControlState)state { 217 | UIControlState lookupState = state != UIControlStateHighlighted || (state == UIControlStateHighlighted && self.trackingThumb == TrackingMiddleThumb) ? state : UIControlStateNormal; 218 | return [self dataForState:lookupState][kMiddleThumbImage]; 219 | } 220 | 221 | - (UIImage*)connectionImageForState:(UIControlState)state { 222 | UIControlState lookupState = state != UIControlStateHighlighted ? state : UIControlStateNormal; 223 | return [self dataForState:lookupState][kConnectionImage]; 224 | } 225 | 226 | 227 | - (void)setLeftValue:(CGFloat)value { 228 | if (value != self.leftValue) { 229 | if (value < self.minimumValue) 230 | value = self.minimumValue; 231 | 232 | if (value > self.rightValue) 233 | value = self.rightValue; 234 | 235 | _leftValue = value; 236 | 237 | [self setNeedsLayout]; 238 | } 239 | } 240 | 241 | - (void)setRightValue:(CGFloat)value { 242 | if (value != self.rightValue) { 243 | if (value > self.maximumValue) 244 | value = self.maximumValue; 245 | 246 | if (value < self.leftValue) 247 | value = self.leftValue; 248 | 249 | _rightValue = value; 250 | 251 | [self setNeedsLayout]; 252 | } 253 | } 254 | 255 | - (CGFloat)distance { 256 | return self.rightValue - self.leftValue; 257 | } 258 | 259 | - (CGFloat)middleValue { 260 | return self.leftValue + self.distance/2.0f; 261 | } 262 | 263 | - (void)setMiddleValue:(CGFloat)value { 264 | float offset = self.distance/2.0f; 265 | 266 | value = MAX(MIN(value, self.maximumValue - offset), self.minimumValue + offset); 267 | 268 | self.leftValue = value - offset; 269 | self.rightValue = value + offset; 270 | } 271 | 272 | 273 | - (void)setMinimumValue:(CGFloat)value { 274 | _minimumValue = value; 275 | if (self.leftValue < value) { 276 | self.leftValue = value; 277 | } 278 | } 279 | 280 | - (void)setMaximumValue:(CGFloat)value { 281 | _maximumValue = value; 282 | if (self.rightValue > value) { 283 | self.rightValue = value; 284 | } 285 | } 286 | 287 | #pragma mark - 288 | 289 | - (void)willMoveToSuperview:(UIView *)newSuperview { 290 | [super willMoveToSuperview:newSuperview]; 291 | 292 | [self updateUI]; 293 | } 294 | 295 | - (NSMutableDictionary*)dataForState:(UIControlState)state { 296 | return [self dataForState:state create:NO]; 297 | } 298 | 299 | - (NSMutableDictionary*)dataForState:(UIControlState)state create:(BOOL)create { 300 | NSMutableDictionary* data = self.statesData[@(state)]; 301 | if (!data && create) { 302 | data = [[NSMutableDictionary alloc] init]; 303 | self.statesData[@(state)] = data; 304 | } 305 | 306 | return data; 307 | } 308 | 309 | 310 | - (NSMutableDictionary*)currentDataForState:(UIControlState)state { 311 | NSMutableDictionary* data = self.statesData[@(state)]; 312 | if (!data) 313 | data = self.statesData[@(UIControlStateNormal)]; 314 | 315 | return data; 316 | } 317 | 318 | - (void)updateUI { 319 | 320 | NSDictionary *stateData = [self currentDataForState:self.state]; 321 | 322 | if ( stateData[kLeftThumbImage] != nil && (self.state != UIControlStateHighlighted || (self.state == UIControlStateHighlighted && self.trackingThumb == TrackingLeftThumb))) { 323 | self.leftThumbImageView.image = stateData[kLeftThumbImage]; 324 | } 325 | 326 | if (stateData[kMiddleThumbImage] && (self.state != UIControlStateHighlighted || (self.state == UIControlStateHighlighted && self.trackingThumb == TrackingMiddleThumb))) { 327 | self.middleThumbImageView.image = stateData[kMiddleThumbImage]; 328 | } 329 | 330 | if (stateData[kRightThumbImage] && (self.state != UIControlStateHighlighted || (self.state == UIControlStateHighlighted && self.trackingThumb == TrackingRightThumb))) { 331 | self.rightThumbImageView.image = stateData[kRightThumbImage]; 332 | } 333 | 334 | if (stateData[kConnectionImage] && self.state != UIControlStateHighlighted) { 335 | self.leftConnectionImageView.image = stateData[kConnectionImage]; 336 | self.rightConnectionImageView.image = stateData[kConnectionImage]; 337 | } 338 | } 339 | 340 | 341 | - (float)valueForLocation:(CGPoint)location { 342 | CGRect r = [self tracRect]; 343 | 344 | CGFloat newValue = [self minimumValue]+(([self maximumValue]-[self minimumValue])*((location.x - CGRectGetMinX(r)) / CGRectGetWidth(r))); 345 | 346 | if (newValue < self.minimumValue) 347 | newValue = self.minimumValue; 348 | 349 | if (newValue > self.maximumValue) 350 | newValue = self.maximumValue; 351 | 352 | return newValue; 353 | } 354 | 355 | - (float)locationForValue:(float)value { 356 | CGRect r = [self tracRect]; 357 | return CGRectGetMinX(r) + (CGRectGetWidth(r) * (value-self.minimumValue) / (self.maximumValue-self.minimumValue)); 358 | } 359 | 360 | 361 | - (CGRect)tracRect { 362 | return CGRectMake(self.leftPointerOffset, floorf((CGRectGetHeight(self.bounds)-self.trackImage.size.height)/2.0), CGRectGetWidth(self.bounds)-self.leftPointerOffset-self.rightPointerOffset, self.trackImage.size.height); 363 | } 364 | 365 | 366 | #pragma mark - 367 | 368 | - (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { 369 | _startLocation = [touch locationInView:self]; 370 | 371 | float distanceFromLeft = fabsf(CGRectGetMidX(self.leftThumbImageView.frame)-_startLocation.x); 372 | float distanceFromRight = fabsf(CGRectGetMidX(self.rightThumbImageView.frame)-_startLocation.x); 373 | float distanceFromMiddle = fabsf(CGRectGetMidX(self.middleThumbImageView.frame)-_startLocation.x); 374 | 375 | if (distanceFromLeft < distanceFromMiddle) { 376 | if (CGRectContainsPoint(CGRectInset(self.leftThumbImageView.frame, -10, -10), _startLocation)) { 377 | self.trackingThumb = TrackingLeftThumb; 378 | _startTrackingValue = self.leftValue; 379 | return YES; 380 | } 381 | } else if (distanceFromRight < distanceFromMiddle) { 382 | if (CGRectContainsPoint(CGRectInset(self.rightThumbImageView.frame, -10, -10), _startLocation)) { 383 | self.trackingThumb = TrackingRightThumb; 384 | _startTrackingValue = self.rightValue; 385 | return YES; 386 | } 387 | } else { 388 | if (CGRectContainsPoint(CGRectInset(self.middleThumbImageView.frame, -10, -10), _startLocation)) { 389 | self.trackingThumb = TrackingMiddleThumb; 390 | _startTrackingValue = self.middleValue; 391 | return YES; 392 | } 393 | } 394 | 395 | self.trackingThumb = TrackingNone; 396 | return [super beginTrackingWithTouch:touch withEvent:event]; 397 | 398 | } 399 | 400 | - (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { 401 | CGPoint location = [touch locationInView:self]; 402 | 403 | if (self.trackingThumb == TrackingLeftThumb) { 404 | self.leftValue = _startTrackingValue + [self valueForLocation:location] - [self valueForLocation:_startLocation]; 405 | [self sendActionsForControlEvents: UIControlEventValueChanged]; 406 | return YES; 407 | } 408 | 409 | if (self.trackingThumb == TrackingRightThumb) { 410 | self.rightValue = _startTrackingValue + [self valueForLocation:location] - [self valueForLocation:_startLocation]; 411 | [self sendActionsForControlEvents: UIControlEventValueChanged]; 412 | return YES; 413 | } 414 | 415 | if (self.trackingThumb == TrackingMiddleThumb) { 416 | self.middleValue = _startTrackingValue + [self valueForLocation:location] - [self valueForLocation:_startLocation]; 417 | [self sendActionsForControlEvents: UIControlEventValueChanged]; 418 | return YES; 419 | } 420 | 421 | self.trackingThumb = TrackingNone; 422 | return [super continueTrackingWithTouch:touch withEvent:event]; 423 | } 424 | 425 | - (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { 426 | self.trackingThumb = TrackingNone; 427 | [super endTrackingWithTouch:touch withEvent:event]; 428 | 429 | } 430 | 431 | - (void)cancelTrackingWithEvent:(UIEvent *)event { 432 | self.trackingThumb = TrackingNone; 433 | [super cancelTrackingWithEvent:event]; 434 | } 435 | 436 | - (void)layoutSubviews { 437 | [super layoutSubviews]; 438 | 439 | CGRect f = self.leftThumbImageView.frame; 440 | f.size = self.leftThumbImageView.image.size; 441 | f.origin.x = floorf([self locationForValue:self.leftValue]-self.leftPointerOffset); 442 | f.origin.y = floorf((CGRectGetHeight(self.bounds)-CGRectGetHeight(f))/2.0f); 443 | self.leftThumbImageView.frame = f; 444 | 445 | f = self.rightThumbImageView.frame; 446 | f.size = self.rightThumbImageView.image.size; 447 | f.origin.x = floorf([self locationForValue:self.rightValue]-(CGRectGetWidth(f)-self.leftPointerOffset)); 448 | f.origin.y = floorf((CGRectGetHeight(self.bounds)-CGRectGetHeight(f))/2.0f); 449 | self.rightThumbImageView.frame = f; 450 | 451 | self.middleThumbImageView.transform = CGAffineTransformIdentity; 452 | f = self.middleThumbImageView.frame; 453 | f.size = self.middleThumbImageView.image.size; 454 | f.origin.x = floorf([self locationForValue:self.middleValue]-CGRectGetWidth(f)/2.0f); 455 | f.origin.y = floorf((CGRectGetHeight(self.bounds)-CGRectGetHeight(f))/2.0f); 456 | self.middleThumbImageView.frame = f; 457 | 458 | if (self.scaleMiddleThumb) { 459 | // Scales the middle handle if the left and right handles are too close 460 | float middleScale = MIN(CGRectGetWidth(f), CGRectGetMinX(self.rightThumbImageView.frame)-CGRectGetMaxX(self.leftThumbImageView.frame))/CGRectGetWidth(f); 461 | self.middleThumbImageView.transform = CGAffineTransformMakeScale(middleScale, middleScale); 462 | 463 | // Hide the middle handle if overlap left handle 464 | self.middleThumbImageView.hidden = middleScale<0.4f; 465 | } else { 466 | // Hides middle handle if overlap with left and right handles 467 | self.middleThumbImageView.hidden = CGRectGetMaxX(self.leftThumbImageView.frame) > CGRectGetMinX(self.middleThumbImageView.frame) || CGRectGetMinX(self.rightThumbImageView.frame) < CGRectGetMaxX(self.middleThumbImageView.frame); 468 | } 469 | 470 | f = self.leftConnectionImageView.frame; 471 | f.size = self.leftConnectionImageView.image.size; 472 | f.origin.x = CGRectGetMaxX(self.leftThumbImageView.frame)-self.connectionOffset; 473 | f.origin.y = floorf((CGRectGetHeight(self.bounds)-CGRectGetHeight(f))/2.0f); 474 | if (self.middleThumbImageView.isHidden) { 475 | f.size.width = CGRectGetMinX(self.rightThumbImageView.frame)-CGRectGetMaxX(self.leftThumbImageView.frame)+self.connectionOffset*2; 476 | } else { 477 | f.size.width = CGRectGetMinX(self.middleThumbImageView.frame)-CGRectGetMaxX(self.leftThumbImageView.frame)+self.connectionOffset*2; 478 | } 479 | self.leftConnectionImageView.frame = f; 480 | 481 | // Hide left connection if the left and the right handles overlap 482 | self.leftConnectionImageView.hidden = (CGRectGetMinX(self.rightThumbImageView.frame)+self.connectionOffset*2 < CGRectGetMaxX(self.leftThumbImageView.frame)); 483 | 484 | self.rightConnectionImageView.hidden = self.middleThumbImageView.isHidden; 485 | 486 | if (!self.rightConnectionImageView.isHidden) { 487 | f = self.rightConnectionImageView.frame; 488 | f.size = self.rightConnectionImageView.image.size; 489 | f.origin.x = CGRectGetMaxX(self.middleThumbImageView.frame)-self.connectionOffset; 490 | f.origin.y = floorf((CGRectGetHeight(self.bounds)-CGRectGetHeight(f))/2.0f); 491 | f.size.width = CGRectGetMinX(self.rightThumbImageView.frame)-CGRectGetMaxX(self.middleThumbImageView.frame)+self.connectionOffset*2; 492 | self.rightConnectionImageView.frame = f; 493 | } 494 | 495 | } 496 | 497 | - (void)drawRect:(CGRect)rect { 498 | if (self.trackImage) { 499 | [self.trackImage drawInRect:CGRectInset([self tracRect], -self.trackImage.capInsets.left, 0)]; 500 | } 501 | } 502 | 503 | @end 504 | -------------------------------------------------------------------------------- /LICENSE.markdown: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | ## MIT License 4 | 5 | Copyright (c) 2013 Antonio Cabezuelo Vivo (http://tapsandswipes.com) 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # ACVRangeSelector 2 | 3 | ACVRangeSelector is a control similar to UISlider that allows you to select a range. 4 | 5 | ![Ramge Selector sample image](https://github.com/tapsandswipes/ACVRangeSelector/raw/master/sample.png) 6 | 7 | ###Installation 8 | 9 | #### Via CocoaPods 10 | 11 | The easiest way to install ACVRangeSelector is via [CocoaPods](http://cocoapods.org). Add this line to your Podfile: 12 | 13 | ```sh 14 | pod 'ACVRangeSelector' 15 | ``` 16 | 17 | and run `pod install`. 18 | 19 | #### Manual 20 | 21 | You can also install it manually by copying to your project these two files: 22 | 23 | ```objective-c 24 | ACVRangeSelector.h 25 | ACVRangeSelector.m 26 | ``` 27 | 28 | If you want to use the default appearance, add also the `ACVRangeSelector.bundle` to your project. 29 | 30 | ## Usage 31 | 32 | ACVRangeSelector uses ARC and the deploiment target is iOS 5.0 as it uses some functionality only available on iOS 5.0 and up. 33 | 34 | 35 | 36 | ## Contact 37 | 38 | - [Personal website](http://tapsandswipes.com) 39 | - [GitHub](http://github.com/tapsandswipes) 40 | - [Twitter](http://twitter.com/acvivo) 41 | - [LinkedIn](http://www.linkedin.com/in/acvivo) 42 | - [Email](mailto:antonio@tapsandswipes.com) 43 | 44 | If you use/enjoy ACVRangeSelector, let me know! 45 | 46 | 47 | ## License 48 | 49 | ### MIT License 50 | 51 | Copyright (c) 2013 Antonio Cabezuelo Vivo (http://tapsandswipes.com) 52 | 53 | Permission is hereby granted, free of charge, to any person obtaining a copy 54 | of this software and associated documentation files (the "Software"), to deal 55 | in the Software without restriction, including without limitation the rights 56 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 57 | copies of the Software, and to permit persons to whom the Software is 58 | furnished to do so, subject to the following conditions: 59 | 60 | The above copyright notice and this permission notice shall be included in 61 | all copies or substantial portions of the Software. 62 | 63 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 64 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 65 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 66 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 67 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 68 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 69 | THE SOFTWARE. -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A91D9DD116B4000200484DAC /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A91D9DD016B4000200484DAC /* UIKit.framework */; }; 11 | A91D9DD316B4000200484DAC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A91D9DD216B4000200484DAC /* Foundation.framework */; }; 12 | A91D9DD516B4000200484DAC /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A91D9DD416B4000200484DAC /* CoreGraphics.framework */; }; 13 | A91D9DDB16B4000200484DAC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A91D9DD916B4000200484DAC /* InfoPlist.strings */; }; 14 | A91D9DDD16B4000200484DAC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A91D9DDC16B4000200484DAC /* main.m */; }; 15 | A91D9DE116B4000200484DAC /* ACVAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A91D9DE016B4000200484DAC /* ACVAppDelegate.m */; }; 16 | A91D9DE316B4000200484DAC /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = A91D9DE216B4000200484DAC /* Default.png */; }; 17 | A91D9DE516B4000200484DAC /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A91D9DE416B4000200484DAC /* Default@2x.png */; }; 18 | A91D9DE716B4000200484DAC /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A91D9DE616B4000200484DAC /* Default-568h@2x.png */; }; 19 | A91D9DEA16B4000200484DAC /* ACVViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A91D9DE916B4000200484DAC /* ACVViewController.m */; }; 20 | A91D9DED16B4000200484DAC /* ACVViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = A91D9DEB16B4000200484DAC /* ACVViewController_iPhone.xib */; }; 21 | A91D9DF016B4000200484DAC /* ACVViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = A91D9DEE16B4000200484DAC /* ACVViewController_iPad.xib */; }; 22 | A91D9DFD16B4010A00484DAC /* ACVRangeSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = A91D9DFC16B4010A00484DAC /* ACVRangeSelector.m */; }; 23 | A91D9E0016B408AC00484DAC /* ACVRangeSelector.bundle in Resources */ = {isa = PBXBuildFile; fileRef = A91D9DFF16B408AC00484DAC /* ACVRangeSelector.bundle */; }; 24 | A91D9E0B16B452F500484DAC /* connector.png in Resources */ = {isa = PBXBuildFile; fileRef = A91D9E0716B452F500484DAC /* connector.png */; }; 25 | A91D9E0C16B452F500484DAC /* left-handle.png in Resources */ = {isa = PBXBuildFile; fileRef = A91D9E0816B452F500484DAC /* left-handle.png */; }; 26 | A91D9E0D16B452F500484DAC /* middle-handle.png in Resources */ = {isa = PBXBuildFile; fileRef = A91D9E0916B452F500484DAC /* middle-handle.png */; }; 27 | A91D9E0E16B452F500484DAC /* right-handle.png in Resources */ = {isa = PBXBuildFile; fileRef = A91D9E0A16B452F500484DAC /* right-handle.png */; }; 28 | A91D9E1216B4651D00484DAC /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = A91D9E1016B4651D00484DAC /* Icon.png */; }; 29 | A91D9E1316B4651D00484DAC /* Icon72.png in Resources */ = {isa = PBXBuildFile; fileRef = A91D9E1116B4651D00484DAC /* Icon72.png */; }; 30 | /* End PBXBuildFile section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | A91D9DCC16B4000200484DAC /* RangeSelectorSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RangeSelectorSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | A91D9DD016B4000200484DAC /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 35 | A91D9DD216B4000200484DAC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 36 | A91D9DD416B4000200484DAC /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 37 | A91D9DD816B4000200484DAC /* RangeSelectorSample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "RangeSelectorSample-Info.plist"; sourceTree = ""; }; 38 | A91D9DDA16B4000200484DAC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 39 | A91D9DDC16B4000200484DAC /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 40 | A91D9DDE16B4000200484DAC /* RangeSelectorSample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RangeSelectorSample-Prefix.pch"; sourceTree = ""; }; 41 | A91D9DDF16B4000200484DAC /* ACVAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ACVAppDelegate.h; sourceTree = ""; }; 42 | A91D9DE016B4000200484DAC /* ACVAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ACVAppDelegate.m; sourceTree = ""; }; 43 | A91D9DE216B4000200484DAC /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 44 | A91D9DE416B4000200484DAC /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 45 | A91D9DE616B4000200484DAC /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 46 | A91D9DE816B4000200484DAC /* ACVViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ACVViewController.h; sourceTree = ""; }; 47 | A91D9DE916B4000200484DAC /* ACVViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ACVViewController.m; sourceTree = ""; }; 48 | A91D9DEC16B4000200484DAC /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ACVViewController_iPhone.xib; sourceTree = ""; }; 49 | A91D9DEF16B4000200484DAC /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ACVViewController_iPad.xib; sourceTree = ""; }; 50 | A91D9DFB16B4010A00484DAC /* ACVRangeSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ACVRangeSelector.h; sourceTree = ""; }; 51 | A91D9DFC16B4010A00484DAC /* ACVRangeSelector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ACVRangeSelector.m; sourceTree = ""; }; 52 | A91D9DFF16B408AC00484DAC /* ACVRangeSelector.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = ACVRangeSelector.bundle; sourceTree = ""; }; 53 | A91D9E0716B452F500484DAC /* connector.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = connector.png; path = Images/connector.png; sourceTree = ""; }; 54 | A91D9E0816B452F500484DAC /* left-handle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "left-handle.png"; path = "Images/left-handle.png"; sourceTree = ""; }; 55 | A91D9E0916B452F500484DAC /* middle-handle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "middle-handle.png"; path = "Images/middle-handle.png"; sourceTree = ""; }; 56 | A91D9E0A16B452F500484DAC /* right-handle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "right-handle.png"; path = "Images/right-handle.png"; sourceTree = ""; }; 57 | A91D9E1016B4651D00484DAC /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon.png; path = Images/Icon.png; sourceTree = ""; }; 58 | A91D9E1116B4651D00484DAC /* Icon72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon72.png; path = Images/Icon72.png; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | A91D9DC916B4000200484DAC /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | A91D9DD116B4000200484DAC /* UIKit.framework in Frameworks */, 67 | A91D9DD316B4000200484DAC /* Foundation.framework in Frameworks */, 68 | A91D9DD516B4000200484DAC /* CoreGraphics.framework in Frameworks */, 69 | ); 70 | runOnlyForDeploymentPostprocessing = 0; 71 | }; 72 | /* End PBXFrameworksBuildPhase section */ 73 | 74 | /* Begin PBXGroup section */ 75 | A91D9DC116B4000100484DAC = { 76 | isa = PBXGroup; 77 | children = ( 78 | A91D9DFA16B4010A00484DAC /* ACVRangeSelector */, 79 | A91D9DD616B4000200484DAC /* RangeSelectorSample */, 80 | A91D9DCF16B4000200484DAC /* Frameworks */, 81 | A91D9DCD16B4000200484DAC /* Products */, 82 | ); 83 | sourceTree = ""; 84 | }; 85 | A91D9DCD16B4000200484DAC /* Products */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | A91D9DCC16B4000200484DAC /* RangeSelectorSample.app */, 89 | ); 90 | name = Products; 91 | sourceTree = ""; 92 | }; 93 | A91D9DCF16B4000200484DAC /* Frameworks */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | A91D9DD016B4000200484DAC /* UIKit.framework */, 97 | A91D9DD216B4000200484DAC /* Foundation.framework */, 98 | A91D9DD416B4000200484DAC /* CoreGraphics.framework */, 99 | ); 100 | name = Frameworks; 101 | sourceTree = ""; 102 | }; 103 | A91D9DD616B4000200484DAC /* RangeSelectorSample */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | A91D9E0116B415DD00484DAC /* Resources */, 107 | A91D9DDF16B4000200484DAC /* ACVAppDelegate.h */, 108 | A91D9DE016B4000200484DAC /* ACVAppDelegate.m */, 109 | A91D9DE816B4000200484DAC /* ACVViewController.h */, 110 | A91D9DE916B4000200484DAC /* ACVViewController.m */, 111 | A91D9DD716B4000200484DAC /* Supporting Files */, 112 | ); 113 | path = RangeSelectorSample; 114 | sourceTree = ""; 115 | }; 116 | A91D9DD716B4000200484DAC /* Supporting Files */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | A91D9DD816B4000200484DAC /* RangeSelectorSample-Info.plist */, 120 | A91D9DD916B4000200484DAC /* InfoPlist.strings */, 121 | A91D9DDC16B4000200484DAC /* main.m */, 122 | A91D9DDE16B4000200484DAC /* RangeSelectorSample-Prefix.pch */, 123 | A91D9DE216B4000200484DAC /* Default.png */, 124 | A91D9DE416B4000200484DAC /* Default@2x.png */, 125 | A91D9DE616B4000200484DAC /* Default-568h@2x.png */, 126 | ); 127 | name = "Supporting Files"; 128 | sourceTree = ""; 129 | }; 130 | A91D9DFA16B4010A00484DAC /* ACVRangeSelector */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | A91D9DFF16B408AC00484DAC /* ACVRangeSelector.bundle */, 134 | A91D9DFB16B4010A00484DAC /* ACVRangeSelector.h */, 135 | A91D9DFC16B4010A00484DAC /* ACVRangeSelector.m */, 136 | ); 137 | name = ACVRangeSelector; 138 | path = ../../ACVRangeSelector; 139 | sourceTree = ""; 140 | }; 141 | A91D9E0116B415DD00484DAC /* Resources */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | A91D9E0F16B461BA00484DAC /* XIBs */, 145 | A91D9E0216B415E600484DAC /* Images */, 146 | ); 147 | name = Resources; 148 | sourceTree = ""; 149 | }; 150 | A91D9E0216B415E600484DAC /* Images */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | A91D9E1016B4651D00484DAC /* Icon.png */, 154 | A91D9E1116B4651D00484DAC /* Icon72.png */, 155 | A91D9E0716B452F500484DAC /* connector.png */, 156 | A91D9E0816B452F500484DAC /* left-handle.png */, 157 | A91D9E0916B452F500484DAC /* middle-handle.png */, 158 | A91D9E0A16B452F500484DAC /* right-handle.png */, 159 | ); 160 | name = Images; 161 | sourceTree = ""; 162 | }; 163 | A91D9E0F16B461BA00484DAC /* XIBs */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | A91D9DEB16B4000200484DAC /* ACVViewController_iPhone.xib */, 167 | A91D9DEE16B4000200484DAC /* ACVViewController_iPad.xib */, 168 | ); 169 | name = XIBs; 170 | sourceTree = ""; 171 | }; 172 | /* End PBXGroup section */ 173 | 174 | /* Begin PBXNativeTarget section */ 175 | A91D9DCB16B4000200484DAC /* RangeSelectorSample */ = { 176 | isa = PBXNativeTarget; 177 | buildConfigurationList = A91D9DF316B4000200484DAC /* Build configuration list for PBXNativeTarget "RangeSelectorSample" */; 178 | buildPhases = ( 179 | A91D9DC816B4000200484DAC /* Sources */, 180 | A91D9DC916B4000200484DAC /* Frameworks */, 181 | A91D9DCA16B4000200484DAC /* Resources */, 182 | ); 183 | buildRules = ( 184 | ); 185 | dependencies = ( 186 | ); 187 | name = RangeSelectorSample; 188 | productName = RangeSelectorSample; 189 | productReference = A91D9DCC16B4000200484DAC /* RangeSelectorSample.app */; 190 | productType = "com.apple.product-type.application"; 191 | }; 192 | /* End PBXNativeTarget section */ 193 | 194 | /* Begin PBXProject section */ 195 | A91D9DC316B4000100484DAC /* Project object */ = { 196 | isa = PBXProject; 197 | attributes = { 198 | CLASSPREFIX = ACV; 199 | LastUpgradeCheck = 0450; 200 | ORGANIZATIONNAME = "Antonio Cabezuelo Vivo"; 201 | }; 202 | buildConfigurationList = A91D9DC616B4000100484DAC /* Build configuration list for PBXProject "RangeSelectorSample" */; 203 | compatibilityVersion = "Xcode 3.2"; 204 | developmentRegion = English; 205 | hasScannedForEncodings = 0; 206 | knownRegions = ( 207 | en, 208 | ); 209 | mainGroup = A91D9DC116B4000100484DAC; 210 | productRefGroup = A91D9DCD16B4000200484DAC /* Products */; 211 | projectDirPath = ""; 212 | projectRoot = ""; 213 | targets = ( 214 | A91D9DCB16B4000200484DAC /* RangeSelectorSample */, 215 | ); 216 | }; 217 | /* End PBXProject section */ 218 | 219 | /* Begin PBXResourcesBuildPhase section */ 220 | A91D9DCA16B4000200484DAC /* Resources */ = { 221 | isa = PBXResourcesBuildPhase; 222 | buildActionMask = 2147483647; 223 | files = ( 224 | A91D9DDB16B4000200484DAC /* InfoPlist.strings in Resources */, 225 | A91D9DE316B4000200484DAC /* Default.png in Resources */, 226 | A91D9DE516B4000200484DAC /* Default@2x.png in Resources */, 227 | A91D9DE716B4000200484DAC /* Default-568h@2x.png in Resources */, 228 | A91D9DED16B4000200484DAC /* ACVViewController_iPhone.xib in Resources */, 229 | A91D9DF016B4000200484DAC /* ACVViewController_iPad.xib in Resources */, 230 | A91D9E0016B408AC00484DAC /* ACVRangeSelector.bundle in Resources */, 231 | A91D9E0B16B452F500484DAC /* connector.png in Resources */, 232 | A91D9E0C16B452F500484DAC /* left-handle.png in Resources */, 233 | A91D9E0D16B452F500484DAC /* middle-handle.png in Resources */, 234 | A91D9E0E16B452F500484DAC /* right-handle.png in Resources */, 235 | A91D9E1216B4651D00484DAC /* Icon.png in Resources */, 236 | A91D9E1316B4651D00484DAC /* Icon72.png in Resources */, 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | }; 240 | /* End PBXResourcesBuildPhase section */ 241 | 242 | /* Begin PBXSourcesBuildPhase section */ 243 | A91D9DC816B4000200484DAC /* Sources */ = { 244 | isa = PBXSourcesBuildPhase; 245 | buildActionMask = 2147483647; 246 | files = ( 247 | A91D9DDD16B4000200484DAC /* main.m in Sources */, 248 | A91D9DE116B4000200484DAC /* ACVAppDelegate.m in Sources */, 249 | A91D9DEA16B4000200484DAC /* ACVViewController.m in Sources */, 250 | A91D9DFD16B4010A00484DAC /* ACVRangeSelector.m in Sources */, 251 | ); 252 | runOnlyForDeploymentPostprocessing = 0; 253 | }; 254 | /* End PBXSourcesBuildPhase section */ 255 | 256 | /* Begin PBXVariantGroup section */ 257 | A91D9DD916B4000200484DAC /* InfoPlist.strings */ = { 258 | isa = PBXVariantGroup; 259 | children = ( 260 | A91D9DDA16B4000200484DAC /* en */, 261 | ); 262 | name = InfoPlist.strings; 263 | sourceTree = ""; 264 | }; 265 | A91D9DEB16B4000200484DAC /* ACVViewController_iPhone.xib */ = { 266 | isa = PBXVariantGroup; 267 | children = ( 268 | A91D9DEC16B4000200484DAC /* en */, 269 | ); 270 | name = ACVViewController_iPhone.xib; 271 | sourceTree = ""; 272 | }; 273 | A91D9DEE16B4000200484DAC /* ACVViewController_iPad.xib */ = { 274 | isa = PBXVariantGroup; 275 | children = ( 276 | A91D9DEF16B4000200484DAC /* en */, 277 | ); 278 | name = ACVViewController_iPad.xib; 279 | sourceTree = ""; 280 | }; 281 | /* End PBXVariantGroup section */ 282 | 283 | /* Begin XCBuildConfiguration section */ 284 | A91D9DF116B4000200484DAC /* Debug */ = { 285 | isa = XCBuildConfiguration; 286 | buildSettings = { 287 | ALWAYS_SEARCH_USER_PATHS = NO; 288 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 289 | CLANG_CXX_LIBRARY = "libc++"; 290 | CLANG_ENABLE_OBJC_ARC = YES; 291 | CLANG_WARN_EMPTY_BODY = YES; 292 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 293 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 294 | COPY_PHASE_STRIP = NO; 295 | GCC_C_LANGUAGE_STANDARD = gnu99; 296 | GCC_DYNAMIC_NO_PIC = NO; 297 | GCC_OPTIMIZATION_LEVEL = 0; 298 | GCC_PREPROCESSOR_DEFINITIONS = ( 299 | "DEBUG=1", 300 | "$(inherited)", 301 | ); 302 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 303 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 304 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 305 | GCC_WARN_UNUSED_VARIABLE = YES; 306 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 307 | ONLY_ACTIVE_ARCH = YES; 308 | RUN_CLANG_STATIC_ANALYZER = YES; 309 | SDKROOT = iphoneos; 310 | TARGETED_DEVICE_FAMILY = "1,2"; 311 | }; 312 | name = Debug; 313 | }; 314 | A91D9DF216B4000200484DAC /* Release */ = { 315 | isa = XCBuildConfiguration; 316 | buildSettings = { 317 | ALWAYS_SEARCH_USER_PATHS = NO; 318 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 319 | CLANG_CXX_LIBRARY = "libc++"; 320 | CLANG_ENABLE_OBJC_ARC = YES; 321 | CLANG_WARN_EMPTY_BODY = YES; 322 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 323 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 324 | COPY_PHASE_STRIP = YES; 325 | GCC_C_LANGUAGE_STANDARD = gnu99; 326 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 327 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 328 | GCC_WARN_UNUSED_VARIABLE = YES; 329 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 330 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 331 | RUN_CLANG_STATIC_ANALYZER = YES; 332 | SDKROOT = iphoneos; 333 | TARGETED_DEVICE_FAMILY = "1,2"; 334 | VALIDATE_PRODUCT = YES; 335 | }; 336 | name = Release; 337 | }; 338 | A91D9DF416B4000200484DAC /* Debug */ = { 339 | isa = XCBuildConfiguration; 340 | buildSettings = { 341 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 342 | GCC_PREFIX_HEADER = "RangeSelectorSample/RangeSelectorSample-Prefix.pch"; 343 | INFOPLIST_FILE = "RangeSelectorSample/RangeSelectorSample-Info.plist"; 344 | PRODUCT_NAME = "$(TARGET_NAME)"; 345 | WRAPPER_EXTENSION = app; 346 | }; 347 | name = Debug; 348 | }; 349 | A91D9DF516B4000200484DAC /* Release */ = { 350 | isa = XCBuildConfiguration; 351 | buildSettings = { 352 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 353 | GCC_PREFIX_HEADER = "RangeSelectorSample/RangeSelectorSample-Prefix.pch"; 354 | INFOPLIST_FILE = "RangeSelectorSample/RangeSelectorSample-Info.plist"; 355 | PRODUCT_NAME = "$(TARGET_NAME)"; 356 | WRAPPER_EXTENSION = app; 357 | }; 358 | name = Release; 359 | }; 360 | /* End XCBuildConfiguration section */ 361 | 362 | /* Begin XCConfigurationList section */ 363 | A91D9DC616B4000100484DAC /* Build configuration list for PBXProject "RangeSelectorSample" */ = { 364 | isa = XCConfigurationList; 365 | buildConfigurations = ( 366 | A91D9DF116B4000200484DAC /* Debug */, 367 | A91D9DF216B4000200484DAC /* Release */, 368 | ); 369 | defaultConfigurationIsVisible = 0; 370 | defaultConfigurationName = Release; 371 | }; 372 | A91D9DF316B4000200484DAC /* Build configuration list for PBXNativeTarget "RangeSelectorSample" */ = { 373 | isa = XCConfigurationList; 374 | buildConfigurations = ( 375 | A91D9DF416B4000200484DAC /* Debug */, 376 | A91D9DF516B4000200484DAC /* Release */, 377 | ); 378 | defaultConfigurationIsVisible = 0; 379 | defaultConfigurationName = Release; 380 | }; 381 | /* End XCConfigurationList section */ 382 | }; 383 | rootObject = A91D9DC316B4000100484DAC /* Project object */; 384 | } 385 | -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/ACVAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ACVAppDelegate.h 3 | // RangeSelectorSample 4 | // 5 | // Created by Antonio Cabezuelo Vivo on 26/01/13. 6 | // Copyright (c) 2013 Antonio Cabezuelo Vivo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ACVViewController; 12 | 13 | @interface ACVAppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) ACVViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/ACVAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // ACVAppDelegate.m 3 | // RangeSelectorSample 4 | // 5 | // Created by Antonio Cabezuelo Vivo on 26/01/13. 6 | // Copyright (c) 2013 Antonio Cabezuelo Vivo. All rights reserved. 7 | // 8 | 9 | #import "ACVAppDelegate.h" 10 | 11 | #import "ACVViewController.h" 12 | 13 | @implementation ACVAppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 18 | // Override point for customization after application launch. 19 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 20 | self.viewController = [[ACVViewController alloc] initWithNibName:@"ACVViewController_iPhone" bundle:nil]; 21 | } else { 22 | self.viewController = [[ACVViewController alloc] initWithNibName:@"ACVViewController_iPad" bundle:nil]; 23 | } 24 | self.window.rootViewController = self.viewController; 25 | [self.window makeKeyAndVisible]; 26 | return YES; 27 | } 28 | 29 | - (void)applicationWillResignActive:(UIApplication *)application 30 | { 31 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 32 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 33 | } 34 | 35 | - (void)applicationDidEnterBackground:(UIApplication *)application 36 | { 37 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 38 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 39 | } 40 | 41 | - (void)applicationWillEnterForeground:(UIApplication *)application 42 | { 43 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 44 | } 45 | 46 | - (void)applicationDidBecomeActive:(UIApplication *)application 47 | { 48 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 49 | } 50 | 51 | - (void)applicationWillTerminate:(UIApplication *)application 52 | { 53 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/ACVViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ACVViewController.h 3 | // RangeSelectorSample 4 | // 5 | // Created by Antonio Cabezuelo Vivo on 26/01/13. 6 | // Copyright (c) 2013 Antonio Cabezuelo Vivo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ACVRangeSelector.h" 11 | 12 | @interface ACVViewController : UIViewController 13 | @property (weak, nonatomic) IBOutlet ACVRangeSelector *rangeSelector; 14 | @property (weak, nonatomic) IBOutlet UILabel *leftLabel; 15 | @property (weak, nonatomic) IBOutlet UILabel *rightLabel; 16 | @property (weak, nonatomic) IBOutlet UILabel *centerLabel; 17 | 18 | - (IBAction)rangeChanged:(ACVRangeSelector *)sender; 19 | @end 20 | -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/ACVViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ACVViewController.m 3 | // RangeSelectorSample 4 | // 5 | // Created by Antonio Cabezuelo Vivo on 26/01/13. 6 | // Copyright (c) 2013 Antonio Cabezuelo Vivo. All rights reserved. 7 | // 8 | 9 | #import "ACVViewController.h" 10 | 11 | @interface ACVViewController () 12 | 13 | @end 14 | 15 | @implementation ACVViewController 16 | 17 | - (void)viewDidLoad 18 | { 19 | [super viewDidLoad]; 20 | 21 | ACVRangeSelector *rs = [[ACVRangeSelector alloc] initWithFrame:CGRectMake(CGRectGetMinX(self.rangeSelector.frame), CGRectGetMaxY(self.rightLabel.frame)+50, CGRectGetWidth(self.rangeSelector.frame), 40)]; 22 | [rs setLeftThumbImage:[UIImage imageNamed:@"left-handle"] forState:UIControlStateNormal]; 23 | [rs setRightThumbImage:[UIImage imageNamed:@"right-handle"] forState:UIControlStateNormal]; 24 | [rs setMiddleThumbImage:[UIImage imageNamed:@"middle-handle"] forState:UIControlStateNormal]; 25 | [rs setConnectionImage:[UIImage imageNamed:@"connector"] forState:UIControlStateNormal]; 26 | rs.scaleMiddleThumb = NO; 27 | rs.leftPointerOffset = 17; 28 | rs.rightPointerOffset = 17; 29 | rs.connectionOffset = 0; 30 | [self.view addSubview:rs]; 31 | } 32 | 33 | 34 | - (IBAction)rangeChanged:(ACVRangeSelector *)sender { 35 | self.leftLabel.text = [NSString stringWithFormat:@"Left: %.2f", sender.leftValue]; 36 | self.rightLabel.text = [NSString stringWithFormat:@"Right: %.2f", sender.rightValue]; 37 | self.centerLabel.text = [NSString stringWithFormat:@"Middle: %.2f", sender.middleValue]; 38 | } 39 | @end 40 | -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/SampleApp/RangeSelectorSample/RangeSelectorSample/Default-568h@2x.png -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/SampleApp/RangeSelectorSample/RangeSelectorSample/Default.png -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/SampleApp/RangeSelectorSample/RangeSelectorSample/Default@2x.png -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/Images/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/SampleApp/RangeSelectorSample/RangeSelectorSample/Images/Icon.png -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/Images/Icon72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/SampleApp/RangeSelectorSample/RangeSelectorSample/Images/Icon72.png -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/Images/connector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/SampleApp/RangeSelectorSample/RangeSelectorSample/Images/connector.png -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/Images/left-handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/SampleApp/RangeSelectorSample/RangeSelectorSample/Images/left-handle.png -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/Images/middle-handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/SampleApp/RangeSelectorSample/RangeSelectorSample/Images/middle-handle.png -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/Images/right-handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/SampleApp/RangeSelectorSample/RangeSelectorSample/Images/right-handle.png -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/RangeSelectorSample-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIcons 12 | 13 | CFBundlePrimaryIcon 14 | 15 | CFBundleIconFiles 16 | 17 | Icon.png 18 | Icon72.png 19 | 20 | 21 | 22 | CFBundleIdentifier 23 | com.tapsandswipes.${PRODUCT_NAME:rfc1034identifier} 24 | CFBundleInfoDictionaryVersion 25 | 6.0 26 | CFBundleName 27 | ${PRODUCT_NAME} 28 | CFBundlePackageType 29 | APPL 30 | CFBundleShortVersionString 31 | 1.0.1 32 | CFBundleSignature 33 | ???? 34 | CFBundleVersion 35 | 1.0.1 36 | LSRequiresIPhoneOS 37 | 38 | UIRequiredDeviceCapabilities 39 | 40 | armv7 41 | 42 | UISupportedInterfaceOrientations 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | UISupportedInterfaceOrientations~ipad 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationPortraitUpsideDown 52 | UIInterfaceOrientationLandscapeLeft 53 | UIInterfaceOrientationLandscapeRight 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/RangeSelectorSample-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'RangeSelectorSample' target in the 'RangeSelectorSample' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/en.lproj/ACVViewController_iPad.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1536 5 | 12C60 6 | 2844 7 | 1187.34 8 | 625.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 1930 12 | 13 | 14 | IBProxyObject 15 | IBUILabel 16 | IBUIView 17 | 18 | 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | PluginDependencyRecalculationVersion 23 | 24 | 25 | 26 | 27 | IBFilesOwner 28 | IBIPadFramework 29 | 30 | 31 | IBFirstResponder 32 | IBIPadFramework 33 | 34 | 35 | 36 | 274 37 | 38 | 39 | 40 | 290 41 | {{20, 20}, {728, 35}} 42 | 43 | 44 | _NS:9 45 | NO 46 | YES 47 | 7 48 | NO 49 | IBIPadFramework 50 | Range Selector Sample 51 | 52 | 1 53 | MCAwIDAAA 54 | darkTextColor 55 | 56 | 57 | 0 58 | 1 59 | 60 | 2 61 | 20 62 | 63 | 64 | Helvetica-Bold 65 | 20 66 | 16 67 | 68 | NO 69 | 70 | 71 | 72 | 290 73 | {{20, 76}, {728, 40}} 74 | 75 | 76 | _NS:9 77 | 78 | 3 79 | MCAwAA 80 | 81 | IBIPadFramework 82 | 83 | 84 | 85 | 290 86 | {{20, 133}, {728, 21}} 87 | 88 | 89 | _NS:9 90 | NO 91 | YES 92 | 7 93 | NO 94 | IBIPadFramework 95 | Left: 96 | 97 | 98 | 0 99 | 100 | 1 101 | 17 102 | 103 | 104 | Helvetica 105 | 17 106 | 16 107 | 108 | NO 109 | 110 | 111 | 112 | 290 113 | {{20, 188}, {728, 21}} 114 | 115 | _NS:9 116 | NO 117 | YES 118 | 7 119 | NO 120 | IBIPadFramework 121 | Middle: 122 | 123 | 124 | 0 125 | 126 | 127 | NO 128 | 129 | 130 | 131 | 290 132 | {{20, 256}, {728, 24}} 133 | 134 | 135 | _NS:9 136 | NO 137 | YES 138 | 7 139 | NO 140 | IBIPadFramework 141 | Right: 142 | 143 | 144 | 0 145 | 146 | 147 | NO 148 | 149 | 150 | {{0, 20}, {768, 1004}} 151 | 152 | 153 | 154 | 3 155 | MQA 156 | 157 | 2 158 | 159 | 160 | 161 | 2 162 | 163 | IBIPadFramework 164 | 165 | 166 | 167 | 168 | 169 | 170 | view 171 | 172 | 173 | 174 | 3 175 | 176 | 177 | 178 | rangeSelector 179 | 180 | 181 | 182 | 27 183 | 184 | 185 | 186 | leftLabel 187 | 188 | 189 | 190 | 28 191 | 192 | 193 | 194 | centerLabel 195 | 196 | 197 | 198 | 29 199 | 200 | 201 | 202 | rightLabel 203 | 204 | 205 | 206 | 30 207 | 208 | 209 | 210 | rangeChanged: 211 | 212 | 213 | 13 214 | 215 | 26 216 | 217 | 218 | 219 | 220 | 221 | 0 222 | 223 | 224 | 225 | 226 | 227 | -1 228 | 229 | 230 | File's Owner 231 | 232 | 233 | -2 234 | 235 | 236 | 237 | 238 | 2 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 4 251 | 252 | 253 | 254 | 255 | 5 256 | 257 | 258 | 259 | 260 | 261 | 6 262 | 263 | 264 | 265 | 266 | 7 267 | 268 | 269 | 270 | 271 | 8 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | ACVViewController 280 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 281 | UIResponder 282 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 283 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 284 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 285 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 286 | ACVRangeSelector 287 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 288 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 289 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 290 | 291 | 292 | 293 | 294 | 295 | 30 296 | 297 | 298 | 0 299 | IBIPadFramework 300 | YES 301 | 3 302 | 1930 303 | 304 | 305 | -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/en.lproj/ACVViewController_iPhone.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1536 5 | 12C60 6 | 2844 7 | 1187.34 8 | 625.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 1930 12 | 13 | 14 | IBProxyObject 15 | IBUILabel 16 | IBUIView 17 | 18 | 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | PluginDependencyRecalculationVersion 23 | 24 | 25 | 26 | 27 | IBFilesOwner 28 | IBCocoaTouchFramework 29 | 30 | 31 | IBFirstResponder 32 | IBCocoaTouchFramework 33 | 34 | 35 | 36 | 274 37 | 38 | 39 | 40 | 290 41 | {{20, 58}, {280, 51}} 42 | 43 | 44 | 45 | _NS:9 46 | 47 | 3 48 | MCAwAA 49 | 50 | IBCocoaTouchFramework 51 | 52 | 53 | 54 | 290 55 | {{20, 20}, {280, 30}} 56 | 57 | 58 | 59 | _NS:9 60 | NO 61 | YES 62 | 7 63 | NO 64 | IBCocoaTouchFramework 65 | Range Selector Sample 66 | 67 | 1 68 | MCAwIDAAA 69 | darkTextColor 70 | 71 | 72 | 0 73 | 1 74 | 75 | 2 76 | 20 77 | 78 | 79 | Helvetica-Bold 80 | 20 81 | 16 82 | 83 | NO 84 | 85 | 86 | 87 | 290 88 | {{20, 140}, {280, 21}} 89 | 90 | 91 | 92 | _NS:9 93 | NO 94 | YES 95 | 7 96 | NO 97 | IBCocoaTouchFramework 98 | Left: 99 | 100 | 101 | 0 102 | 103 | 1 104 | 17 105 | 106 | 107 | Helvetica 108 | 17 109 | 16 110 | 111 | NO 112 | 113 | 114 | 115 | 290 116 | {{20, 183}, {280, 21}} 117 | 118 | 119 | _NS:9 120 | NO 121 | YES 122 | 7 123 | NO 124 | IBCocoaTouchFramework 125 | Middle: 126 | 127 | 128 | 0 129 | 130 | 131 | NO 132 | 133 | 134 | 135 | 290 136 | {{20, 227}, {280, 21}} 137 | 138 | 139 | 140 | _NS:9 141 | NO 142 | YES 143 | 7 144 | NO 145 | IBCocoaTouchFramework 146 | Right: 147 | 148 | 149 | 0 150 | 151 | 152 | NO 153 | 154 | 155 | {{0, 20}, {320, 548}} 156 | 157 | 158 | 159 | 160 | 3 161 | MC43NQA 162 | 163 | 2 164 | 165 | 166 | NO 167 | 168 | 169 | IBUIScreenMetrics 170 | 171 | YES 172 | 173 | 174 | 175 | 176 | 177 | {320, 568} 178 | {568, 320} 179 | 180 | 181 | IBCocoaTouchFramework 182 | Retina 4 Full Screen 183 | 2 184 | 185 | IBCocoaTouchFramework 186 | 187 | 188 | 189 | 190 | 191 | 192 | view 193 | 194 | 195 | 196 | 7 197 | 198 | 199 | 200 | rangeSelector 201 | 202 | 203 | 204 | 24 205 | 206 | 207 | 208 | leftLabel 209 | 210 | 211 | 212 | 25 213 | 214 | 215 | 216 | rightLabel 217 | 218 | 219 | 220 | 26 221 | 222 | 223 | 224 | centerLabel 225 | 226 | 227 | 228 | 27 229 | 230 | 231 | 232 | rangeChanged: 233 | 234 | 235 | 13 236 | 237 | 28 238 | 239 | 240 | 241 | 242 | 243 | 0 244 | 245 | 246 | 247 | 248 | 249 | -1 250 | 251 | 252 | File's Owner 253 | 254 | 255 | -2 256 | 257 | 258 | 259 | 260 | 6 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 8 273 | 274 | 275 | 276 | 277 | 20 278 | 279 | 280 | 281 | 282 | 21 283 | 284 | 285 | 286 | 287 | 22 288 | 289 | 290 | 291 | 292 | 23 293 | 294 | 295 | 296 | 297 | 298 | 299 | ACVViewController 300 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 301 | UIResponder 302 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 303 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 304 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 305 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 306 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 307 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 308 | ACVRangeSelector 309 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 310 | 311 | 312 | 313 | 314 | 315 | 28 316 | 317 | 318 | 319 | 320 | ACVRangeSelector 321 | UIControl 322 | 323 | IBProjectSource 324 | ./Classes/ACVRangeSelector.h 325 | 326 | 327 | 328 | ACVViewController 329 | UIViewController 330 | 331 | rangeChanged: 332 | ACVRangeSelector 333 | 334 | 335 | rangeChanged: 336 | 337 | rangeChanged: 338 | ACVRangeSelector 339 | 340 | 341 | 342 | UILabel 343 | UILabel 344 | ACVRangeSelector 345 | UILabel 346 | 347 | 348 | 349 | centerLabel 350 | UILabel 351 | 352 | 353 | leftLabel 354 | UILabel 355 | 356 | 357 | rangeSelector 358 | ACVRangeSelector 359 | 360 | 361 | rightLabel 362 | UILabel 363 | 364 | 365 | 366 | IBProjectSource 367 | ./Classes/ACVViewController.h 368 | 369 | 370 | 371 | 372 | 0 373 | IBCocoaTouchFramework 374 | YES 375 | 3 376 | 1930 377 | 378 | 379 | -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | "CFBundleDisplayName" = "Range Select"; -------------------------------------------------------------------------------- /SampleApp/RangeSelectorSample/RangeSelectorSample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RangeSelectorSample 4 | // 5 | // Created by Antonio Cabezuelo Vivo on 26/01/13. 6 | // Copyright (c) 2013 Antonio Cabezuelo Vivo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "ACVAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([ACVAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tapsandswipes/ACVRangeSelector/64d551515214ae0c6c31429b8564147305f25a8b/sample.png --------------------------------------------------------------------------------