Can i realise a horizontal slider with tick marks on iOS? There is not such option like in MacOS.
-
3You'd have to program that yourself; UISliders on iOS don't have that functionality. – Carl Goldsmith Feb 08 '12 at 16:37
-
So @CarlGoldsmith, how *do* you program that? – JohnK May 05 '13 at 01:07
-
1@JohnK The question was about its possibility, not the method; my answer was accepted over a year ago. – Carl Goldsmith May 05 '13 at 11:42
-
Have a look at my pod https://github.com/joamafer/JMMarkSlider – jomafer Jul 24 '14 at 19:42
-
Have a look at my pod on CocoaPods https://github.com/joamafer/JMMarkSlider – jomafer Jul 24 '14 at 19:45
3 Answers
I actually wrote a tutorial on how to do this on my company's website:
http://fragmentlabs.com/blog/making-talking2trees-part-3-77
The quick answer for this is a custom method I wrote, and which is explained in the article above:
-(UIView*)tickMarksViewForSlider:(UISlider*)slider View:(UIView *)view
{
// set up vars
int ticksDivider = (slider.maximumValue > 10) ? 10 : 1;
int ticks = (int) slider.maximumValue / ticksDivider;
int sliderWidth = 364;
float offsetOffset = (ticks < 10) ? 1.7 : 1.1;
offsetOffset = (ticks > 10) ? 0 : offsetOffset;
float offset = sliderWidth / ticks - offsetOffset;
float xPos = 0;
// initialize view to return
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y+1,
slider.frame.size.width, slider.frame.size.height);
view.backgroundColor = [UIColor clearColor];
// make a UIImageView with tick for each tick in the slider
for (int i=0; i < ticks; i++)
{
if (i == 0) {
xPos += offset+5.25;
}
else
{
UIView *tick = [[UIView alloc] initWithFrame:CGRectMake(xPos, 3, 2, 16)];
tick.backgroundColor = [UIColor colorWithWhite:0.7 alpha:1];
tick.layer.shadowColor = [[UIColor whiteColor] CGColor];
tick.layer.shadowOffset = CGSizeMake(0.0f, 1.0f);
tick.layer.shadowOpacity = 1.0f;
tick.layer.shadowRadius = 0.0f;
[view insertSubview:tick belowSubview:slider];
xPos += offset - 0.4;
}
}
// return the view
return view;
}
You'd basically apply this method to a view that sits behind your UISlider, and it creates the tick marks at the appropriate intervals. You can change how many ticks are visible by modifying the ticksDivider variable. The above example creates one per slider value unless the slider's maximumValue property is greater than 10 (my sliders had values of 5, 40 and 120), in which case I divided the value by 10.
You have to play with the offsetOffset value and the float value after xPos += offset+...
to account for the width of your thumb image and slider cap insets (so the thumb button appears to be centered over each).

- 333
- 3
- 12
-
The great thing about this response is it actually proposes a replacement. Unfortunately the thumb-tick alignment is imperfect at best. The fact that one has to fiddle with parameters (of questionable provenance) to get the alignment even close is *ad hoc* and unscientific (esp. with the discrepancy with [your code](http://fragmentlabs.com/files/blogs/CustomSliderDemo_Part3.zip): 2.7/1.7). After all, this *should* be **geometry** we're talking about! Need to look into basing it off of real parameters, say, from `[slider thumbRectForBounds:trackRect:value:]`. – JohnK May 05 '13 at 00:11
While ctlockey's solution certainly works, I wanted something simpler but also that allowed the thumb to snap to whichever tick mark it is closest to when the user releases it.
My solution is below. It is a subclass of UISlider that only overrides two methods. It is bare bones but would be a foundation for a more complex version.
-(void)endTrackingWithTouch:(UITouch *)touch
withEvent:(UIEvent *)event
{
[super endTrackingWithTouch:touch withEvent:event];
if (self.value != floorf(self.value))
{
CGFloat roundedFloat = (float)roundf(self.value);
[self setValue:roundedFloat animated:YES];
}
}
-(void)drawRect:(CGRect)rect
{
CGFloat thumbOffset = self.currentThumbImage.size.width / 2.0f;
NSInteger numberOfTicksToDraw = roundf(self.maximumValue - self.minimumValue) + 1;
CGFloat distMinTickToMax = self.frame.size.width - (2 * thumbOffset);
CGFloat distBetweenTicks = distMinTickToMax / ((float)numberOfTicksToDraw - 1);
CGFloat xTickMarkPosition = thumbOffset; //will change as tick marks are drawn across slider
CGFloat yTickMarkStartingPosition = self.frame.size.height / 2; //will not change
CGFloat yTickMarkEndingPosition = self.frame.size.height; //will not change
UIBezierPath *tickPath = [UIBezierPath bezierPath];
for (int i = 0; i < numberOfTicksToDraw; i++)
{
[tickPath moveToPoint:CGPointMake(xTickMarkPosition, yTickMarkStartingPosition)];
[tickPath addLineToPoint:CGPointMake(xTickMarkPosition, yTickMarkEndingPosition)];
xTickMarkPosition += distBetweenTicks;
}
[tickPath stroke];
}

- 414
- 4
- 14
-
1The above implementation works fine in iOS 6, but in iOS 7+ the value of self.currentThumImage.size.width is no longer accessible with the default thumb image. The solution is that you have to set a custom image for the thumb if you want to access the image's size. See: http://stackoverflow.com/questions/21313796/how-to-read-size-of-uislider-thumb-image – paulmrest Aug 02 '15 at 19:45
From @CarlGoldsmith - You'd have to program that yourself; UISliders on iOS don't have that functionality.

- 3,220
- 6
- 47
- 74