捕捉到固定步数的UISlider(如iOS 7设置应用程序中的文本大小)

捕捉到固定步数的UISlider(如iOS 7设置应用程序中的文本大小),ios,objective-c,iphone,xcode,uislider,Ios,Objective C,Iphone,Xcode,Uislider,我正在尝试创建一个UISlider,它允许您从数字数组中进行选择。每个滑块位置应等距,滑块应捕捉到每个位置,而不是在它们之间平滑滑动。(这是iOS 7中引入的设置常规文本大小中滑块的行为。) 我想从中选择的数字是:-3、0、2、4、7、10和12。 (我对Objective-C非常陌生,所以一个完整的代码示例比一个代码片段要有用得多。=)答案基本上是一样的 要修改它以适应您的情况,您需要创建一个舍入函数,该函数只返回您想要的值。例如,你可以做一些简单的事情(尽管很粗糙),比如: -(int)r

我正在尝试创建一个
UISlider
,它允许您从数字数组中进行选择。每个滑块位置应等距,滑块应捕捉到每个位置,而不是在它们之间平滑滑动。(这是iOS 7中引入的
设置
常规
文本大小
中滑块的行为。)

我想从中选择的数字是:
-3、0、2、4、7、10和12。


(我对Objective-C非常陌生,所以一个完整的代码示例比一个代码片段要有用得多。=)

答案基本上是一样的

要修改它以适应您的情况,您需要创建一个舍入函数,该函数只返回您想要的值。例如,你可以做一些简单的事情(尽管很粗糙),比如:

-(int)roundSliderValue:(float)x {
    if (x < -1.5) {
        return -3;
    } else if (x < 1.0) {
        return 0;
    } else if (x < 3.0) {
        return 2;
    } else if (x < 5.5) {
        return 4;
    } else if (x < 8.5) {
        return 7;
    } else if (x < 11.0) {
        return 10;
    } else {
        return 12;
    }
}
最后,实施更改:

-(void)valueChanged:(id)slider {
    [slider setValue:[self roundSliderValue:slider.value] animated:NO];
}

其他一些答案是有效的,但这将在滑块的每个位置之间提供相同的固定空间。在本例中,您将滑块位置视为包含您感兴趣的实际数值的数组的索引

@interface MyViewController : UIViewController {
    UISlider *slider;
    NSArray *numbers;
}
@end

@implementation MyViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    slider = [[UISlider alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:slider];

    // These number values represent each slider position
    numbers = @[@(-3), @(0), @(2), @(4), @(7), @(10), @(12)];
    // slider values go from 0 to the number of values in your numbers array
    NSInteger numberOfSteps = ((float)[numbers count] - 1);
    slider.maximumValue = numberOfSteps;
    slider.minimumValue = 0;

    // As the slider moves it will continously call the -valueChanged: 
    slider.continuous = YES; // NO makes it call only once you let go
    [slider addTarget:self
               action:@selector(valueChanged:)
     forControlEvents:UIControlEventValueChanged];
}
- (void)valueChanged:(UISlider *)sender {
    // round the slider position to the nearest index of the numbers array
    NSUInteger index = (NSUInteger)(slider.value + 0.5);
    [slider setValue:index animated:NO];
    NSNumber *number = numbers[index]; // <-- This numeric value you want
    NSLog(@"sliderIndex: %i", (int)index);
    NSLog(@"number: %@", number);
}

与PengOne的方法类似,但我进行了手动取整,以使其更清楚发生了什么

- (IBAction)sliderDidEndEditing:(UISlider *)slider {
    // default value slider will start at
    float newValue = 0.0;

    if (slider.value < -1.5) {
        newValue = -3;
    } else if (slider.value < 1) {
        newValue = 0;
    } else if (slider.value < 3) {
        newValue = 2;
    } else if (slider.value < 5.5) {
        newValue = 4;
    } else if (slider.value < 8.5) {
        newValue = 7;
    } else if (slider.value < 11) {
        newValue = 10;
    } else {
        newValue = 12;
    }
    slider.value = newValue;
}

- (IBAction)sliderValueChanged:(id)sender {
    UISlider *slider = sender;
    float newValue = 0.0;

    if (slider.value < -1.5) {
        newValue = -3;
    } else if (slider.value < 1) {
        newValue = 0;
    } else if (slider.value < 3) {
        newValue = 2;
    } else if (slider.value < 5.5) {
        newValue = 4;
    } else if (slider.value < 8.5) {
        newValue = 7;
    } else if (slider.value < 11) {
        newValue = 10;
    } else {
        newValue = 12;
    }
    // and if you have a label displaying the slider value, set it
    [yourLabel].text = [NSString stringWithFormat:@"%d", (int)newValue];
}
-(iAction)滑块定义编辑:(UISlider*)滑块{
//默认值滑块将从
float newValue=0.0;
如果(滑块值<-1.5){
newValue=-3;
}else if(slider.value<1){
newValue=0;
}else if(slider.value<3){
newValue=2;
}否则如果(滑块值<5.5){
newValue=4;
}否则如果(滑块值<8.5){
newValue=7;
}else if(slider.value<11){
newValue=10;
}否则{
newValue=12;
}
slider.value=newValue;
}
-(iAction)sliderValueChanged:(id)发件人{
UISlider*滑块=发送器;
float newValue=0.0;
如果(滑块值<-1.5){
newValue=-3;
}else if(slider.value<1){
newValue=0;
}else if(slider.value<3){
newValue=2;
}否则如果(滑块值<5.5){
newValue=4;
}否则如果(滑块值<8.5){
newValue=7;
}else if(slider.value<11){
newValue=10;
}否则{
newValue=12;
}
//如果有显示滑块值的标签,请将其设置为
[yourLabel].text=[NSString stringWithFormat:@“%d”,(int)newValue];
}

如果步骤之间有规则的空格,则可以将其用于
15
值:

@IBAction func timeSliderChanged(sender: UISlider) {

    let newValue = Int(sender.value/15) * 15
    sender.setValue(Float(newValue), animated: false)
}

这适用于我的特殊情况,使用@IBDesignable:

需要偶数、整数间隔:

@IBDesignable
class SnappableSlider: UISlider {

    @IBInspectable
    var interval: Int = 1

    override init(frame: CGRect) {
        super.init(frame: frame)
        setUpSlider()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setUpSlider()
    }

    private func setUpSlider() {
        addTarget(self, action: #selector(handleValueChange(sender:)), for: .valueChanged)
    }

    @objc func handleValueChange(sender: UISlider) {
        let newValue =  (sender.value / Float(interval)).rounded() * Float(interval)
        setValue(Float(newValue), animated: false)
    }
}

如果任何人也需要捕捉动画,则可以执行以下操作:

  • 取消选中序列图像板中滑块的连续更新 您可以从swift
    slider.isContinuous=false执行相同操作

  • 视图控制器中添加以下
    @iAction
  • @iAction func滑块移动(\uSlider:UISlider){
    让stepCount=10
    让roundedCurrent=(slider.value/Float(stepCount)).rounded()
    设newValue=Int(舍入当前)*步数
    slider.setValue(Float(newValue),动画:true)
    }
    

    我的灵感来自于

    可能的复制品不,它不是。因为我没有一个固定的步骤5或10。我需要能够从滑块上的7个固定值中进行选择。另外,如果我真的可以使用你链接到的那个,我不知道如何实现代码并为我的配件进行更改。这可能是正确的方法,但我需要详细说明。对链接问题的高度投票的答案可以根据您的需要进行调整。你为什么不试试,然后再问一下你有没有问题?好的,这是个好消息。但是你能不能给我详细解释一下,也许是在回答这个问题时,提供一个示例代码,告诉我如何使代码适应我的需要?我应该在哪里添加代理?我该如何更改该值,使其适合我的7个不同刻度?正如我在问题中提到的,我对Objective-C相当陌生——我不能只看一段代码就想“啊,我可以改变这个,然后……”,但是:)非常感谢。这正是我想要的,并且以一种教我如何去做的方式来写。再次感谢你!所以我把“数字”改成了一个包含100多个数据点的数组。。。。如何更改UISlider的代码,使其相对于数据点的数量滑动?我知道“索引”需要更改,但是……/。。。。我想我会在几个小时内找到答案,但我认为其他一些人希望看到一个动态数组的答案,其中滑块可以有1到数千个索引……)如果将其设置为continuous values=NO
    slider.continuous=NO,则只需简单地更改代码即可接受静态或动态数组值,您将获得一个附加的upvote它允许用户在拖动滑块时进行更平滑的操作。由于它仅在用户完成拖动滑块并将其移动到最接近的整数值时计算
    valueChanged
    函数。@MatiasVad我需要与所讨论的相同的UI,我指的是小步垂直线,我搜索了它,但没有找到解决方案。这很容易实现,对于简单的情况来说是一个很好的选择。我认为被接受的答案(虽然仍然是一个很好的选择,当然更可定制)对于大多数情况来说是过分的,这应该足以满足大多数人的需求。太棒了
    @IBAction func timeSliderChanged(sender: UISlider) {
    
        let newValue = Int(sender.value/15) * 15
        sender.setValue(Float(newValue), animated: false)
    }
    
    @IBDesignable
    class SnappableSlider: UISlider {
    
        @IBInspectable
        var interval: Int = 1
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            setUpSlider()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            setUpSlider()
        }
    
        private func setUpSlider() {
            addTarget(self, action: #selector(handleValueChange(sender:)), for: .valueChanged)
        }
    
        @objc func handleValueChange(sender: UISlider) {
            let newValue =  (sender.value / Float(interval)).rounded() * Float(interval)
            setValue(Float(newValue), animated: false)
        }
    }