Horizantal slider with tick marks on iOS

六月ゝ 毕业季﹏ 提交于 2019-12-01 18:27:12

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).

From @CarlGoldsmith - You'd have to program that yourself; UISliders on iOS don't have that functionality.

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];
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!