【问题标题】:Implementing steps/snapping UISlider实施步骤/捕捉 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;

【问题讨论】:

    标签: iphone uislider


    【解决方案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 添加了目标,那就太好了。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-17
          • 2016-10-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多