实施步骤/捕捉 UISlider
Posted
技术标签:
【中文标题】实施步骤/捕捉 UISlider【英文标题】:Implementing steps/snapping UISlider 【发布时间】:2011-06-16 10:22:31 【问题描述】:我正在尝试使用 UISlider 实现某种形式的捕捉或步骤。我已经编写了以下代码,但它并没有像我希望的那样顺利。它可以工作,但是当我向上滑动它时,它会向右对齐 5 点,使手指不在“滑动圆”的中心
这是我的代码,其中self.lastQuestionSliderValue
是我设置为滑块初始值的类的属性。
if (self.questionSlider.value > self.lastQuestionSliderValue)
self.questionSlider.value += 5.0;
else
self.questionSlider.value -= 5.0;
self.lastQuestionSliderValue = (int)self.questionSlider.value;
【问题讨论】:
【参考方案1】:这实际上比我最初想象的要容易得多。最初我试图获得 thumbrect 属性并做复杂的数学运算。这是我最终得到的结果:
h 文件:
@property (nonatomic, retain) IBOutlet UISlider* questionSlider;
@property (nonatomic) float lastQuestionStep;
@property (nonatomic) float stepValue;
m 文件:
- (void)viewDidLoad
[super viewDidLoad];
// Set the step to whatever you want. Make sure the step value makes sense
// when compared to the min/max values for the slider. You could take this
// example a step further and instead use a variable for the number of
// steps you wanted.
self.stepValue = 25.0f;
// Set the initial value to prevent any weird inconsistencies.
self.lastQuestionStep = (self.questionSlider.value) / self.stepValue;
// This is the "valueChanged" method for the UISlider. Hook this up in
// Interface Builder.
-(IBAction)valueChanged:(id)sender
// This determines which "step" the slider should be on. Here we're taking
// the current position of the slider and dividing by the `self.stepValue`
// to determine approximately which step we are on. Then we round to get to
// find which step we are closest to.
float newStep = roundf((questionSlider.value) / self.stepValue);
// Convert "steps" back to the context of the sliders values.
self.questionSlider.value = newStep * self.stepValue;
确保你为你的 UISlider 视图连接了方法和出口,你应该很高兴。
【讨论】:
太棒了!非常感谢你。您能否详细说明您是如何想到如何实现这种效果/它是如何工作的想法的? @Andreas:我在我的代码中添加了更多的 cmets。我希望他们有所帮助。 为什么 stepValue 是 int 类型,而你用 25.0f 设置它? @PaulBrewczynski 我认为这只是我最初实现的保留。您应该安全地将stepValue
设置为 int 或将其重构为存储在 float 中。
@FreeAsInBeer 其实你可以通过条件转换从发件人那里得到 UISlider,不需要出口。【参考方案2】:
对我来说最简单的解决方案就是
- (IBAction)sliderValueChanged:(id)sender
UISlider *slider = sender;
slider.value = roundf(slider.value);
【讨论】:
【参考方案3】:另一种 Swift 方法是做类似的事情
let step: Float = 10
@IBAction func sliderValueChanged(sender: UISlider)
let roundedValue = round(sender.value / step) * step
sender.value = roundedValue
// Do something else with the value
【讨论】:
你的意思是round(sender.value * step) / step
吗?
我使用的公式是这样的:假设 UISlider 从 0 到 100 并且您想要 10 步。如果当前滑块值为 14,则您的滑块应该“对齐”到 10:@ 987654323@ 如果您的滑块的值为 46,您希望它捕捉到 50:round(46/10) * 10 = 5 * 10 = 50
在您的情况下,它会产生相同的结果:round(46*10) / 10 = 460 / 10 = 46
希望这清楚。 :)
这是有道理的。我使用的是具有默认最小值和最大值 (0..1) 的滑块,而这个公式总是产生 0。在这种情况下,除法之前的乘法将产生 0.0、0.1、0.2、... 0.9、1.0。但设置不同的最大值可能是更常见的情况。
哦,明白了!是的,如果可以的话,设置更高的最小值和最大值,否则你将不得不做更多的计算,就像你想的那样。
我建议将round()
改为floor()
以避免滑动抖动【参考方案4】:
也许有人会需要! 在我的情况下,我需要任何整数步,所以我使用了以下代码:
-(void)valueChanged:(id)sender
UISlider *slider = sender;
slider.value = (int)slider.value;
【讨论】:
我看到的问题是它不会锁定到一个 int 直到你一直滑到那个 int 值。例如,如果您有一个从 1 到 2 的滑块,如果滑块从 1 到 1.99 的任何位置滑动,它将保持在 1。然后当您滑动到 2 时,它会滑到 2。因为 int 会将所有内容向下舍入。请参阅我的答案以获得更好的舍入方法。【参考方案5】:快捷版
示例: 您希望滑块以 100 为步长从 1 到 10000 移动。 UISlider 设置如下:
slider.maximumValue = 100
slider.minimumValue = 0
slider.continuous = true
在用于滑块的操作 func() 中使用:
var sliderValue:Int = Int(sender.value) * 100
【讨论】:
【参考方案6】:一个非常简单的:
- (void)sliderUpdated:(UISlider*)sli
CGFloat steps = 5;
sli.value = roundf(sli.value/sli.maximumValue*steps)*sli.maximumValue/steps;
如果您想要一个快速的解决方案并且您已经通过 UIControlEventValueChanged 添加了目标,那就太好了。
【讨论】:
以上是关于实施步骤/捕捉 UISlider的主要内容,如果未能解决你的问题,请参考以下文章