diff --git a/RangeSlider.xcodeproj/project.pbxproj b/RangeSlider.xcodeproj/project.pbxproj index 5d1122b..f9a415c 100755 --- a/RangeSlider.xcodeproj/project.pbxproj +++ b/RangeSlider.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 2860E32E111B888700E27156 /* AppDelegate_iPad.m in Sources */ = {isa = PBXBuildFile; fileRef = 2860E32C111B888700E27156 /* AppDelegate_iPad.m */; }; 2860E32F111B888700E27156 /* MainWindow_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2860E32D111B888700E27156 /* MainWindow_iPad.xib */; }; 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; + 35D6C07D185FF03C00418803 /* rangethumb@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 35D6C07C185FF03C00418803 /* rangethumb@2x.png */; }; 899E8854130C39BC00F0E7D8 /* RangeSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 899E8853130C39BC00F0E7D8 /* RangeSlider.m */; }; FAA0016E16E19A1E00260842 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FAA0016D16E19A1E00260842 /* Default-568h@2x.png */; }; FAA0017216E1A38900260842 /* fillrange.png in Resources */ = {isa = PBXBuildFile; fileRef = FAA0016F16E1A38900260842 /* fillrange.png */; }; @@ -35,6 +36,7 @@ 288765FC0DF74451002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Shared/main.m; sourceTree = ""; }; 32CA4F630368D1EE00C91783 /* RangeSlider_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RangeSlider_Prefix.pch; sourceTree = ""; }; + 35D6C07C185FF03C00418803 /* rangethumb@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "rangethumb@2x.png"; sourceTree = ""; }; 899E8852130C39BC00F0E7D8 /* RangeSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RangeSlider.h; sourceTree = ""; }; 899E8853130C39BC00F0E7D8 /* RangeSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RangeSlider.m; sourceTree = ""; }; 8D1107310486CEB800E47090 /* RangeSlider-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "RangeSlider-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = ""; }; @@ -74,6 +76,7 @@ FAA0016F16E1A38900260842 /* fillrange.png */, FAA0017016E1A38900260842 /* fullrange.png */, FAA0017116E1A38900260842 /* rangethumb.png */, + 35D6C07C185FF03C00418803 /* rangethumb@2x.png */, 899E8852130C39BC00F0E7D8 /* RangeSlider.h */, 899E8853130C39BC00F0E7D8 /* RangeSlider.m */, 2860E327111B887F00E27156 /* MainWindow_iPhone.xib */, @@ -157,6 +160,8 @@ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; + attributes = { + }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "RangeSlider" */; compatibilityVersion = "Xcode 3.1"; developmentRegion = English; @@ -185,6 +190,7 @@ 2860E32F111B888700E27156 /* MainWindow_iPad.xib in Resources */, FAA0016E16E19A1E00260842 /* Default-568h@2x.png in Resources */, FAA0017216E1A38900260842 /* fillrange.png in Resources */, + 35D6C07D185FF03C00418803 /* rangethumb@2x.png in Resources */, FAA0017316E1A38900260842 /* fullrange.png in Resources */, FAA0017416E1A38900260842 /* rangethumb.png in Resources */, ); diff --git a/iPhone/AppDelegate_iPhone.m b/iPhone/AppDelegate_iPhone.m index 2674118..ba8970f 100644 --- a/iPhone/AppDelegate_iPhone.m +++ b/iPhone/AppDelegate_iPhone.m @@ -19,21 +19,15 @@ @implementation AppDelegate_iPhone - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - slider = [[RangeSlider alloc] initWithFrame:CGRectMake(10, 100, 300, 30)]; // the slider enforces a height of 30, although I'm not sure that this is necessary + slider = [[RangeSlider alloc] initWithFrame:CGRectMake(10, 100, 300, 130)]; - slider.minimumRangeLength = .03; // this property enforces a minimum range size. By default it is set to 0.0 - - [slider setMinThumbImage:[UIImage imageNamed:@"rangethumb.png"]]; // the two thumb controls are given custom images - [slider setMaxThumbImage:[UIImage imageNamed:@"rangethumb.png"]]; - - - UIImage *image; // there are two track images, one for the range "track", and one for the filled in region of the track between the slider thumbs - - [slider setTrackImage:[[UIImage imageNamed:@"fullrange.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(9.0, 9.0, 9.0, 9.0)]]; - - image = [UIImage imageNamed:@"fillrange.png"]; - [slider setInRangeTrackImage:image]; - + slider.minimumRangeLength = 0.25; // this property enforces a minimum range size. By default it is set to 0.0 + + UIImage *minImage = [UIImage imageNamed:@"rangethumb.png"]; + UIImage *maxImage = [UIImage imageNamed:@"rangethumb.png"]; + UIImage *trackImage = [[UIImage imageNamed:@"fullrange.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(9.0, 9.0, 9.0, 9.0)]; + UIImage *inRangeTrackImage = [UIImage imageNamed:@"fillrange.png"]; + [slider setMinThumbImage:minImage maxThunbImage:maxImage trackImage:trackImage inRangeTrackImage:inRangeTrackImage]; [slider addTarget:self action:@selector(report:) forControlEvents:UIControlEventValueChanged]; // The slider sends actions when the value of the minimum or maximum changes diff --git a/iPhone/RangeSlider.h b/iPhone/RangeSlider.h index bfaee9f..3805d86 100644 --- a/iPhone/RangeSlider.h +++ b/iPhone/RangeSlider.h @@ -19,8 +19,7 @@ } @property (nonatomic) CGFloat min, max, minimumRangeLength; -- (void)setMinThumbImage:(UIImage *)image; -- (void)setMaxThumbImage:(UIImage *)image; -- (void)setTrackImage:(UIImage *)image; -- (void)setInRangeTrackImage:(UIImage *)image; + +- (void)setMinThumbImage:(UIImage *)minImage maxThunbImage:(UIImage *)maxImage trackImage:(UIImage *)trackImage inRangeTrackImage:(UIImage *)inRangeTrackImage; + @end diff --git a/iPhone/RangeSlider.m b/iPhone/RangeSlider.m index 583801c..1e96f88 100644 --- a/iPhone/RangeSlider.m +++ b/iPhone/RangeSlider.m @@ -1,10 +1,10 @@ - // - // RangeSlider.m - // RangeSlider - // - // Created by Charlie Mezak on 9/16/10. - // Copyright 2010 Natural Guides, LLC. All rights reserved. - // +// +// RangeSlider.m +// RangeSlider +// +// Created by Charlie Mezak on 9/16/10. +// Copyright 2010 Natural Guides, LLC. All rights reserved. +// #import "RangeSlider.h" #import @@ -14,80 +14,74 @@ @interface RangeSlider () - (void)calculateMinMax; -- (void)setupSliders; @end @implementation RangeSlider +{ + float _maxLength; + float _leftMargin; +} @synthesize min, max, minimumRangeLength; - (id)initWithFrame:(CGRect)frame { - if ((self = [super initWithFrame:CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, SLIDER_HEIGHT)])) { + if ((self = [super initWithFrame:frame])) { self.clipsToBounds = NO; - // default values + // default values min = 0.0; max = 1.0; minimumRangeLength = 0.0; - - backgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, SLIDER_HEIGHT)]; + + backgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, self.frame.size.height)]; backgroundImageView.contentMode = UIViewContentModeScaleToFill; [self addSubview:backgroundImageView]; - - trackImageView = [[UIImageView alloc] initWithFrame:CGRectMake(5, 0, frame.size.width-10, SLIDER_HEIGHT)]; - trackImageView.contentMode = UIViewContentModeScaleToFill; - - inRangeTrackImageView = [[UIImageView alloc] initWithFrame:CGRectMake(min*frame.size.width, 0, (max-min)*frame.size.width, SLIDER_HEIGHT)]; - inRangeTrackImageView.contentMode = UIViewContentModeScaleToFill; - [self addSubview:trackImageView]; - [self addSubview:inRangeTrackImageView]; - - [self setupSliders]; - - [self updateTrackImageViews]; } return self; } -- (void)setupSliders { - - minSlider = [[UIImageView alloc] initWithFrame:CGRectMake(min*self.frame.size.width, (SLIDER_HEIGHT-self.frame.size.height)/2.0, self.frame.size.height, self.frame.size.height)]; - minSlider.backgroundColor = [UIColor whiteColor]; - minSlider.contentMode = UIViewContentModeScaleToFill; - - maxSlider = [[UIImageView alloc] initWithFrame:CGRectMake(max*(self.frame.size.width-self.frame.size.height), (SLIDER_HEIGHT-self.frame.size.height)/2.0, self.frame.size.height, self.frame.size.height)]; - maxSlider.backgroundColor = [UIColor whiteColor]; - maxSlider.contentMode = UIViewContentModeScaleToFill; - - [self addSubview:minSlider]; - [self addSubview:maxSlider]; - -} - -- (void)setMinThumbImage:(UIImage *)image { - minSlider.backgroundColor = [UIColor clearColor]; - minSlider.image = image; -} - -- (void)setMaxThumbImage:(UIImage *)image { - maxSlider.backgroundColor = [UIColor clearColor]; - maxSlider.image = image; -} - -- (void)setInRangeTrackImage:(UIImage *)image { - trackImageView.frame = CGRectMake(inRangeTrackImageView.frame.origin.x,trackImageView.frame.origin.y, inRangeTrackImageView.frame.size.width, trackImageView.frame.size.height); - inRangeTrackImageView.image = [image stretchableImageWithLeftCapWidth:image.size.width/2.0-2 topCapHeight:image.size.height-2]; +- (void)setMinThumbImage:(UIImage *)minImage maxThunbImage:(UIImage *)maxImage trackImage:(UIImage *)trackImage inRangeTrackImage:(UIImage *)inRangeTrackImage +{ + minSlider = [[UIImageView alloc] initWithImage:minImage]; + CGRect minSliderFrame = minSlider.frame; + minSliderFrame.origin.x = 0; + minSliderFrame.origin.y = (self.bounds.size.height - minSliderFrame.size.height) / 2; + minSlider.frame = minSliderFrame; + [self addSubview:minSlider]; -} - -- (void)setTrackImage:(UIImage *)image { - trackImageView.frame = CGRectMake(5, MAX((self.frame.size.height-image.size.height)/2.0,0), self.frame.size.width-10, MIN(self.frame.size.height,image.size.height)); - trackImageView.image = image; - inRangeTrackImageView.frame = CGRectMake(inRangeTrackImageView.frame.origin.x,trackImageView.frame.origin.y,inRangeTrackImageView.frame.size.width,trackImageView.frame.size.height); + maxSlider = [[UIImageView alloc] initWithImage:maxImage]; + CGRect maxSliderFrame = maxSlider.frame; + maxSliderFrame.origin.x = self.bounds.size.width - maxSliderFrame.size.width/2; + maxSliderFrame.origin.y = (self.bounds.size.height - maxSliderFrame.size.height) / 2; + maxSlider.frame = maxSliderFrame; + [self addSubview:maxSlider]; + + trackImageView = [[UIImageView alloc] initWithImage:trackImage]; + CGRect trackFrame = trackImageView.frame; + trackFrame.origin.x = minSlider.bounds.size.width / 2; + trackFrame.origin.y = (self.bounds.size.height - trackFrame.size.height) / 2; + trackFrame.size.width = self.bounds.size.width - minSlider.bounds.size.width/2 - maxSlider.bounds.size.width/2; + trackImageView.frame = trackFrame; + [self addSubview:trackImageView]; + + inRangeTrackImageView = [[UIImageView alloc] initWithImage:inRangeTrackImage]; + CGRect inRangeTrackFrame = inRangeTrackImageView.frame; + inRangeTrackFrame.origin.y = (self.bounds.size.height - inRangeTrackFrame.size.height) / 2; + inRangeTrackImageView.frame = inRangeTrackFrame; + [self addSubview:inRangeTrackImageView]; + + [self bringSubviewToFront:minSlider]; + [self bringSubviewToFront:maxSlider]; + + _maxLength = trackImageView.frame.size.width; + _leftMargin = trackImageView.frame.origin.x; + + [self updateThumbViews]; + [self updateTrackImageViews]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { @@ -112,53 +106,26 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { if (trackingSlider == minSlider) { float newX = MAX( - 0, + _leftMargin, MIN( - minSlider.frame.origin.x+deltaX, - self.frame.size.width-self.frame.size.height*2.0-minimumRangeLength*(self.frame.size.width-self.frame.size.height*2.0)) - ); + minSlider.center.x + deltaX, + _leftMargin + (1-minimumRangeLength) * _maxLength + )); - minSlider.frame = CGRectMake( - newX, - minSlider.frame.origin.y, - minSlider.frame.size.width, - minSlider.frame.size.height - ); + minSlider.center = CGPointMake(newX, minSlider.center.y); - maxSlider.frame = CGRectMake( - MAX( - maxSlider.frame.origin.x, - minSlider.frame.origin.x+self.frame.size.height+minimumRangeLength*(self.frame.size.width-self.frame.size.height*2.0) - ), - maxSlider.frame.origin.y, - self.frame.size.height, - self.frame.size.height); + maxSlider.center = CGPointMake(MAX(maxSlider.center.x, minSlider.center.x + minimumRangeLength * _maxLength), maxSlider.center.y); } else if (trackingSlider == maxSlider) { - float newX = MAX( - self.frame.size.height+minimumRangeLength*(self.frame.size.width-self.frame.size.height*2.0), - MIN( - maxSlider.frame.origin.x+deltaX, - self.frame.size.width-self.frame.size.height) - ); - - maxSlider.frame = CGRectMake( - newX, - maxSlider.frame.origin.y, - maxSlider.frame.size.width, - maxSlider.frame.size.height - ); - - minSlider.frame = CGRectMake( - MIN( - minSlider.frame.origin.x, - maxSlider.frame.origin.x-self.frame.size.height-minimumRangeLength*(self.frame.size.width-2.0*self.frame.size.height) - ), - minSlider.frame.origin.y, - self.frame.size.height, - self.frame.size.height); + float newX = MAX(_leftMargin + minimumRangeLength*_maxLength, MIN(self.frame.size.width-maxSlider.frame.size.width/2, maxSlider.center.x+deltaX)); + + maxSlider.center = CGPointMake(newX, maxSlider.center.y); + + minSlider.center = CGPointMake(MIN(minSlider.center.x, maxSlider.center.x-minimumRangeLength*_maxLength), minSlider.center.y); } + + NSLog(@"%f", minSlider.center.x); [self calculateMinMax]; [self updateTrackImageViews]; @@ -166,9 +133,9 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - (void)updateTrackImageViews { - inRangeTrackImageView.frame = CGRectMake(minSlider.frame.origin.x+0.5*self.frame.size.height, + inRangeTrackImageView.frame = CGRectMake(minSlider.center.x, inRangeTrackImageView.frame.origin.y, - maxSlider.frame.origin.x-minSlider.frame.origin.x, + maxSlider.center.x-minSlider.center.x, inRangeTrackImageView.frame.size.height); } @@ -186,8 +153,8 @@ - (void)setMax:(CGFloat)newMax { } - (void)calculateMinMax { - float newMax = MIN(1,(maxSlider.frame.origin.x - self.frame.size.height)/(self.frame.size.width-(2*self.frame.size.height))); - float newMin = MAX(0,minSlider.frame.origin.x/(self.frame.size.width-2.0*self.frame.size.height)); + float newMax = MIN(1, (maxSlider.center.x - _leftMargin) / _maxLength); + float newMin = MAX(0, (minSlider.center.x - _leftMargin) / _maxLength); if (newMin != min || newMax != max) { @@ -207,18 +174,11 @@ - (void)setMinimumRangeLength:(CGFloat)length { - (void)updateThumbViews { - maxSlider.frame = CGRectMake(max*(self.frame.size.width-2*self.frame.size.height)+self.frame.size.height, - (SLIDER_HEIGHT-self.frame.size.height)/2.0, - self.frame.size.height, - self.frame.size.height); - - minSlider.frame = CGRectMake(MIN( - min*(self.frame.size.width-2*self.frame.size.height), - maxSlider.frame.origin.x-self.frame.size.height-(minimumRangeLength*(self.frame.size.width-self.frame.size.height*2.0)) - ), - (SLIDER_HEIGHT-self.frame.size.height)/2.0, - self.frame.size.height, - self.frame.size.height); + maxSlider.center = CGPointMake(_leftMargin + max*_maxLength, maxSlider.center.y); + minSlider.center = CGPointMake(MIN( + _leftMargin + min*_maxLength, + maxSlider.center.x - minimumRangeLength*_maxLength + ), minSlider.center.y); } diff --git a/iPhone/rangethumb.png b/iPhone/rangethumb.png index 18ecc2f..9f60577 100644 Binary files a/iPhone/rangethumb.png and b/iPhone/rangethumb.png differ diff --git a/iPhone/rangethumb@2x.png b/iPhone/rangethumb@2x.png new file mode 100644 index 0000000..210d911 Binary files /dev/null and b/iPhone/rangethumb@2x.png differ