实施步骤/捕捉 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的主要内容,如果未能解决你的问题,请参考以下文章

从填充到捕捉视觉状态时的首选行为

实施工程师利器--项目实施步骤截图工具

在经典模式下配置捕捉

如何在 iOS 设备上的滑动手势期间“捕捉”子视图?

CRM实施的八大基本步骤

详解数据仓库的实施步骤,实战扫盲系列!