Skip to content

Commit

Permalink
Make slider behave more like the one in iPod.app. Add comments.
Browse files Browse the repository at this point in the history
If you are dragging at a distance from the scrubber and you continue dragging upwwards towards the slider, the thumb moves towards you until it meets you at the slider.
  • Loading branch information
ole committed Jan 5, 2011
1 parent e6ca151 commit 28dafa9
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 5 deletions.
1 change: 1 addition & 0 deletions OBSlider/OBSlider.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
NSArray *scrubbingSpeedChangePositions;

CGPoint beganTrackingLocation;
float beganTrackingValue;
}

@property (assign, readonly) float scrubbingSpeed;
Expand Down
24 changes: 19 additions & 5 deletions OBSlider/OBSlider.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ @interface OBSlider ()

@property (assign, readwrite) float scrubbingSpeed;
@property (assign) CGPoint beganTrackingLocation;
@property (assign) float beganTrackingValue;

- (NSUInteger) indexOfLowerScrubbingSpeed:(NSArray*)scrubbingSpeedPositions forOffset:(CGFloat)verticalOffset;
- (NSArray *) defaultScrubbingSpeeds;
Expand All @@ -27,6 +28,7 @@ @implementation OBSlider
@synthesize scrubbingSpeeds;
@synthesize scrubbingSpeedChangePositions;
@synthesize beganTrackingLocation;
@synthesize beganTrackingValue;


- (void) dealloc
Expand Down Expand Up @@ -97,7 +99,9 @@ - (BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
BOOL beginTracking = [super beginTrackingWithTouch:touch withEvent:event];
if (beginTracking)
{
// Store the location of the touch and the slider's value when tracking begins
self.beganTrackingLocation = [touch locationInView:self];
self.beganTrackingValue = self.value;
}
return beginTracking;
}
Expand All @@ -107,20 +111,28 @@ - (BOOL) continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
if (self.tracking)
{
CGPoint previousLocation = [touch previousLocationInView:self];
// Calculate the horizontal offset of the touch since tracking began
CGPoint currentLocation = [touch locationInView:self];
CGFloat trackingOffset = currentLocation.x - previousLocation.x;
CGFloat trackingOffset = currentLocation.x - beganTrackingLocation.x;

// Find the scrubbing speed that curresponds to the touch's vertical offset
CGFloat verticalOffset = fabsf(currentLocation.y - self.beganTrackingLocation.y);
NSUInteger scrubbingSpeedChangePosIndex = [self indexOfLowerScrubbingSpeed:self.scrubbingSpeedChangePositions forOffset:verticalOffset];
if (scrubbingSpeedChangePosIndex == NSNotFound) {
scrubbingSpeedChangePosIndex = [self.scrubbingSpeeds count];
}
self.scrubbingSpeed = [[self.scrubbingSpeeds objectAtIndex:scrubbingSpeedChangePosIndex - 1] floatValue];

float newScrubbingSpeed = [[self.scrubbingSpeeds objectAtIndex:scrubbingSpeedChangePosIndex - 1] floatValue];

// If the scrubbing speed changed since the last movement of the touch,
// we should animate the slider to the new value because the distance to the new value is potentially big.
// Otherwise, do not animate so that the slider's thumb closely follows the user's finger.
BOOL animateSlider = newScrubbingSpeed == self.scrubbingSpeed ? NO : YES;

// Calculate the new value for the slider and set it
self.scrubbingSpeed = newScrubbingSpeed;
CGRect trackRect = [self trackRectForBounds:self.bounds];
self.value = self.value + self.scrubbingSpeed * (self.maximumValue - self.minimumValue) * (trackingOffset / trackRect.size.width);
float newValue = self.beganTrackingValue + self.scrubbingSpeed * (self.maximumValue - self.minimumValue) * (trackingOffset / trackRect.size.width);
[self setValue:newValue animated:animateSlider];

if (self.continuous) {
[self sendActionsForControlEvents:UIControlEventValueChanged];
Expand All @@ -144,6 +156,8 @@ - (void) endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
#pragma mark -
#pragma mark Helper methods

// Return the lowest index in the array of numbers passed in scrubbingSpeedPositions
// whose value is smaller than verticalOffset.
- (NSUInteger) indexOfLowerScrubbingSpeed:(NSArray*)scrubbingSpeedPositions forOffset:(CGFloat)verticalOffset
{
for (int i = 0; i < [scrubbingSpeedPositions count]; i++) {
Expand Down

0 comments on commit 28dafa9

Please sign in to comment.