iOS上带有刻度线的水平滑块

4

我能否在iOS上实现带有刻度标记的水平滑块?与MacOS不同,iOS没有此选项。


3
你需要自己编程实现这个功能;iOS上的UISliders(滑块)不具备此功能。 - Carl Goldsmith
那么,@CarlGoldsmith,你是如何编写程序的呢? - JohnK
1
@JohnK 这个问题是关于它的可能性,而不是方法;我的答案已经被接受一年多了。 - Carl Goldsmith
请查看我的Pod https://github.com/joamafer/JMMarkSlider - jomafer
请查看我在 CocoaPods 上的 pod https://github.com/joamafer/JMMarkSlider - jomafer
3个回答

3
我实际上在我们公司的网站上写了一篇关于如何做到这一点的教程:http://fragmentlabs.com/blog/making-talking2trees-part-3-77。快速回答是我编写的一个自定义方法,并在上面的文章中进行了解释:
-(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;
}

您基本上可以将此方法应用于位于UISlider后面的视图,并在适当的间隔处创建刻度标记。您可以通过修改ticksDivider变量来更改可见的刻度数。上面的示例每个滑块值创建一个刻度,除非slider的maximumValue属性大于10(我的滑块值为5、40和120),在这种情况下,我将该值除以10。
您必须调整offsetOffset值和xPos += offset+...之后的浮点值,以考虑您的拇指图像和滑块端部插图的宽度(使拇指按钮看起来位于每个中心位置)。

这个回应的好处在于它实际上提出了一个替代方案。不幸的是,拇指勾选对齐最多也只是不完美的。事实上,为了使对齐接近,人们必须摆弄一些来历可疑的参数,这是特别临时和不科学的(尤其是与你的代码的差异:2.7/1.7)。毕竟,我们谈论的是几何!需要研究一下是否可以基于真实参数,比如从[slider thumbRectForBounds:trackRect:value:] - JohnK

2

虽然ctlockey的解决方案确实可行,但我希望有一个更简单的方案,同时也允许拇指在用户释放时自动贴近最近的刻度线。

我的解决方案如下。它是UISlider的子类,只覆盖了两个方法。它非常简单,但可以作为更复杂版本的基础。

-(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];
}

1
以上实现在iOS 6中运行良好,但在iOS 7+中,默认的滑块图像不再可访问self.currentThumImage.size.width的值。解决方案是,如果您想访问图像的大小,则必须为滑块设置自定义图像。参见:https://dev59.com/5Hvaa4cB1Zd3GeqPGKkq - paulmrest

2

来自@CarlGoldsmith - 你需要自己编写程序;iOS上的UISlider没有这个功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接