iOS如何让滑块停在离散点

发布于 2024-11-29 15:13:35 字数 79 浏览 0 评论 0原文

我想让滑块停在代表时间轴上整数的离散点处。最好的方法是什么?我不想要介于两者之间的任何值。如果滑块也可以“捕捉”到每个离散点的位置,那就太好了。

I would like to make a slider stop at discrete points that represent integers on a timeline. What's the best way to do this? I don't want any values in between. It would be great if the slider could "snap" to position at each discrete point as well.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

你的心境我的脸 2024-12-06 15:13:36

我为此所做的是首先将当前滑块值的“输出”变量设置为整数(默认情况下为浮点数)。然后将输出数字设置为滑块的当前值:

int output = (int)mySlider.value;
mySlider.value = output;

这会将其设置为以 1 个整数的增量移动。要使其在特定的数字范围内移动,例如在 5 秒内移动,请使用以下公式修改输出值。将其添加到上面的前两行之间:

int output = (int)mySlider.value;
int newValue = 5 * floor((output/5)+0.5);
mySlider.value = newValue;

现在,当您移动滑块时,滑块会“跳”到 5 的倍数。

What I did for this is first set an "output" variable of the current slider value to an integer (its a float by default). Then set the output number as the current value of the slider:

int output = (int)mySlider.value;
mySlider.value = output;

This will set it to move in increments of 1 integers. To make it move in a specific range of numbers, say for example, in 5s, modify your output value with the following formula. Add this between the first two lines above:

int output = (int)mySlider.value;
int newValue = 5 * floor((output/5)+0.5);
mySlider.value = newValue;

Now your slider "jumps" to multiples of 5 as you move it.

时光清浅 2024-12-06 15:13:36

我按照 Nathan 的建议做了,但我还想更新实时显示当前值的关联 UILabel,所以这就是我所做的:

- (IBAction) countdownSliderChanged:(id)sender
{
    // Action Hooked to 'Value Changed' (continuous)

    // Update label (to rounded value)

    CGFloat value = [_countdownSlider value];

    CGFloat roundValue = roundf(value);

    [_countdownLabel setText:[NSString stringWithFormat:@" %2.0f 秒", roundValue]];
}


- (IBAction) countdownSliderFinishedEditing:(id)sender
{
    // Action Hooked to 'Touch Up Inside' (when user releases knob)

    // Adjust knob (to rounded value)

    CGFloat value = [_countdownSlider value];

    CGFloat roundValue = roundf(value);

    if (value != roundValue) {
        // Almost 100% of the time - Adjust:

        [_countdownSlider setValue:roundValue];
    }
}

当然,缺点是它需要两个操作(方法)每个滑块。

I did as Nathan suggested, but I also want to update an associated UILabel displaying the current value in real time, so here is what I did:

- (IBAction) countdownSliderChanged:(id)sender
{
    // Action Hooked to 'Value Changed' (continuous)

    // Update label (to rounded value)

    CGFloat value = [_countdownSlider value];

    CGFloat roundValue = roundf(value);

    [_countdownLabel setText:[NSString stringWithFormat:@" %2.0f 秒", roundValue]];
}


- (IBAction) countdownSliderFinishedEditing:(id)sender
{
    // Action Hooked to 'Touch Up Inside' (when user releases knob)

    // Adjust knob (to rounded value)

    CGFloat value = [_countdownSlider value];

    CGFloat roundValue = roundf(value);

    if (value != roundValue) {
        // Almost 100% of the time - Adjust:

        [_countdownSlider setValue:roundValue];
    }
}

The drawback, of course, is that it takes two actions (methods) per slider.

带刺的爱情 2024-12-06 15:13:36

带有 ValueChangedTouchUpInside 的 Swift 版本。

编辑:实际上,在这种情况下你应该连接 3 个事件:

yourSlider.addTarget(self, action: #selector(presetNumberSliderTouchUp), for: [.touchUpInside, .touchUpOutside, .touchCancel])

我刚刚粘贴了我的代码,但你可以轻松地看到它是如何完成的。

private func setSizesSliderValue(pn: Int, slider: UISlider, setSliderValue: Bool)
{
    if setSliderValue
    {
        slider.setValue(Float(pn), animated: true)
    }

    masterPresetInfoLabel.text = String(
        format: TexturingViewController.createAndSendPresetNumberNofiticationTemplate,
        self.currentPresetNumber.name.uppercased(),
        String(self.currentPresetNumber.currentUserIndexHumanFriendly)
    )
}

@objc func presetNumberSliderTouchUp(_ sender: Any)
{
    guard let slider = sender as? NormalSlider else{
        return
    }

    setupSliderChangedValuesGeneric(slider: slider, setSliderValue: true)
}

private func setupSliderChangedValuesGeneric(slider: NormalSlider, setSliderValue: Bool)
{
    let rounded = roundf((Float(slider.value) / Float(presetNumberStep))) * Float(presetNumberStep)

    // Set new preset number value
    self.currentPresetNumber.current = Int(rounded)
    setSizesSliderValue(pn: Int(rounded), slider: slider, setSliderValue: setSliderValue)
}

@IBAction func presetNumberChanged(_ sender: Any)
{
    guard let slider = sender as? NormalSlider else{
        return
    }

    setupSliderChangedValuesGeneric(slider: slider, setSliderValue: false)
}

Swift version with ValueChanged and TouchUpInside.

EDIT: Actually you should hook up 3 events in this case:

yourSlider.addTarget(self, action: #selector(presetNumberSliderTouchUp), for: [.touchUpInside, .touchUpOutside, .touchCancel])

I've just pasted my code, but you can easily see how it's done.

private func setSizesSliderValue(pn: Int, slider: UISlider, setSliderValue: Bool)
{
    if setSliderValue
    {
        slider.setValue(Float(pn), animated: true)
    }

    masterPresetInfoLabel.text = String(
        format: TexturingViewController.createAndSendPresetNumberNofiticationTemplate,
        self.currentPresetNumber.name.uppercased(),
        String(self.currentPresetNumber.currentUserIndexHumanFriendly)
    )
}

@objc func presetNumberSliderTouchUp(_ sender: Any)
{
    guard let slider = sender as? NormalSlider else{
        return
    }

    setupSliderChangedValuesGeneric(slider: slider, setSliderValue: true)
}

private func setupSliderChangedValuesGeneric(slider: NormalSlider, setSliderValue: Bool)
{
    let rounded = roundf((Float(slider.value) / Float(presetNumberStep))) * Float(presetNumberStep)

    // Set new preset number value
    self.currentPresetNumber.current = Int(rounded)
    setSizesSliderValue(pn: Int(rounded), slider: slider, setSliderValue: setSliderValue)
}

@IBAction func presetNumberChanged(_ sender: Any)
{
    guard let slider = sender as? NormalSlider else{
        return
    }

    setupSliderChangedValuesGeneric(slider: slider, setSliderValue: false)
}
筑梦 2024-12-06 15:13:35

我在这里采取的步骤与 jrturton 的答案中所述的步骤几乎相同,但我发现滑块会明显落后于我的动作。我是这样做的:

将滑块放入 Interface Builder 的视图中。
设置滑块的最小/最大值。 (我使用了 0 和 5)

在 .h 文件中:

@property (strong, nonatomic) IBOutlet UISlider *mySlider;
- (IBAction)sliderChanged:(id)sender;

在 .m 文件中:

- (IBAction)sliderChanged:(id)sender 
{
    int sliderValue;
    sliderValue = lroundf(mySlider.value);
    [mySlider setValue:sliderValue animated:YES];
}

在 Interface Builder 中,我将滑块的“Touch Up Inside”事件连接到“文件所有者”,而不是“值已更改”。现在,当我抬起手指时,它可以让我平滑地移动滑块并捕捉到每个整数。

谢谢@jrturton!

更新 - Swift:

@IBOutlet var mySlider: UISlider!

@IBAction func sliderMoved(sender: UISlider) {
    sender.setValue(Float(lroundf(mySlider.value)), animated: true)
}

此外,如果在故事板中连接事物有任何困惑,我已将一个快速示例上传到 github:https://github.com/nathandries/StickySlider

The steps that I took here were pretty much the same as stated in jrturton's answer but I found that the slider would sort of lag behind my movements quite noticeably. Here is how I did this:

Put the slider into the view in Interface Builder.
Set the min/max values of the slider. (I used 0 and 5)

In the .h file:

@property (strong, nonatomic) IBOutlet UISlider *mySlider;
- (IBAction)sliderChanged:(id)sender;

In the .m file:

- (IBAction)sliderChanged:(id)sender 
{
    int sliderValue;
    sliderValue = lroundf(mySlider.value);
    [mySlider setValue:sliderValue animated:YES];
}

After this in Interface Builder I hooked up the 'Touch Up Inside' event for the slider to File's Owner, rather than 'Value Changed'. Now it allows me to smoothly move the slider and snaps to each whole number when my finger is lifted.

Thanks @jrturton!

UPDATE - Swift:

@IBOutlet var mySlider: UISlider!

@IBAction func sliderMoved(sender: UISlider) {
    sender.setValue(Float(lroundf(mySlider.value)), animated: true)
}

Also if there is any confusion on hooking things up in the storyboard I have uploaded a quick example to github: https://github.com/nathandries/StickySlider

野味少女 2024-12-06 15:13:35

要使滑块“粘在”特定点,您的视图控制器应该在从滑块链接到的 valueChanged 方法中,根据滑块的值确定适当的舍入,然后使用 setValue:animated: 将滑块移动到适当的位置。因此,如果您的滑块从 0 变为 2,并且用户将其更改为 0.75,则您认为该值应该为 1 并将滑块值设置为该值。

To make the slider "stick" at specific points, your viewcontroller should, in the valueChanged method linked to from the slider, determine the appropriate rounded from the slider's value and then use setValue: animated: to move the slider to the appropriate place. So, if your slider goes from 0 to 2, and the user changes it to 0.75, you assume this should be 1 and set the slider value to that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文