Implementing steps/snapping UISlider

2019-03-08 05:27发布

I am trying to implement some form of snapping or steps with the UISlider. I have written the following code but it does not work as smooth as I hoped for. It works, but when the I slide it upwards it snap 5points to the right leaving the finger not centered over the "slide-circle"

This is my code where self.lastQuestionSliderValue is a property of the class which I have set to the initial value of the slider.

    if (self.questionSlider.value > self.lastQuestionSliderValue) {
        self.questionSlider.value += 5.0;
    } else {
        self.questionSlider.value -= 5.0;
    }

    self.lastQuestionSliderValue = (int)self.questionSlider.value;

6条回答
成全新的幸福
2楼-- · 2019-03-08 05:44

The simplest solution to me was just

- (IBAction)sliderValueChanged:(id)sender {
    UISlider *slider = sender;
    slider.value = roundf(slider.value);
}
查看更多
乱世女痞
3楼-- · 2019-03-08 05:50

SWIFT VERSION

Example: You want a slider to go from 1-10000 in steps of 100. UISlider setup is as follows:

slider.maximumValue = 100
slider.minimumValue = 0
slider.continuous = true

In the action func() for the slider use:

var sliderValue:Int = Int(sender.value) * 100
查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-03-08 05:57

It's actually considerably easier than I first thought. Originally I was trying to get the thumbrect property and do complicated math. Here's what I ended up with:

h File:

@property (nonatomic, retain) IBOutlet UISlider* questionSlider;
@property (nonatomic) float lastQuestionStep;
@property (nonatomic) float stepValue;

m File:

- (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;
}

Make sure you hook up the method and the outlet for your UISlider view and you should be good to go.

查看更多
Melony?
5楼-- · 2019-03-08 05:57

Maybe someone will need! In my situation I needed any integer step, so I used the following code:

-(void)valueChanged:(id)sender {
    UISlider *slider = sender;
    slider.value = (int)slider.value;
}
查看更多
虎瘦雄心在
6楼-- · 2019-03-08 05:59

A really simple one:

- (void)sliderUpdated:(UISlider*)sli {
    CGFloat steps = 5;
    sli.value = roundf(sli.value/sli.maximumValue*steps)*sli.maximumValue/steps;    
}

Great if you want a fast solution and you've added the target by UIControlEventValueChanged.

查看更多
Evening l夕情丶
7楼-- · 2019-03-08 06:00

Another Swift approach is to do something like

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

}

You can read more about the approach and setup in my post.

查看更多
登录 后发表回答