Выполнение шагов / привязка UISlider

Я пытаюсь реализовать некоторую форму привязки или шагов с помощью 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;

person LuckyLuke    schedule 16.06.2011    source источник


Ответы (6)


На самом деле это намного проще, чем я думал вначале. Первоначально я пытался получить свойство "правильно делать" и выполнять сложные математические вычисления. Вот что у меня получилось:

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, и все должно быть в порядке.

person FreeAsInBeer    schedule 16.06.2011
comment
Это замечательно! Большое Вам спасибо. Не могли бы вы подробнее рассказать, как вы пришли к идее, как добиться этого эффекта / как это работает? - person LuckyLuke; 16.06.2011
comment
@Andreas: Я добавил еще несколько комментариев к своему коду. Надеюсь, они помогут. - person FreeAsInBeer; 16.06.2011
comment
Почему stepValue имеет тип int, когда вы настроили его с помощью 25.0f? - person Paul Brewczynski; 25.01.2015
comment
@PaulBrewczynski Я думаю, что это просто пережиток моей первоначальной реализации. Вы должны быть уверены, что установите stepValue в int или измените его так, чтобы он сохранялся в виде числа с плавающей запятой. - person FreeAsInBeer; 26.01.2015
comment
@FreeAsInBeer На самом деле вы можете получить UISlider от отправителя с условным преобразованием, не требуя выхода. - person Juan Boero; 17.03.2020

Самым простым решением для меня было просто

- (IBAction)sliderValueChanged:(id)sender {
    UISlider *slider = sender;
    slider.value = roundf(slider.value);
}
person Adam Johns    schedule 05.12.2014
comment
Спасибо, ваш хороший, потому что он скользит к ближайшему значению. - person kakubei; 13.03.2015

Может кому понадобится! В моей ситуации мне нужен был любой целочисленный шаг, поэтому я использовал следующий код:

-(void)valueChanged:(id)sender {
    UISlider *slider = sender;
    slider.value = (int)slider.value;
}
person rusBogun    schedule 18.12.2013
comment
Проблема, которую я вижу в этом, заключается в том, что он не будет блокироваться в int, пока вы не полностью перейдете к этому значению int. Например, если у вас есть ползунок от 1 до 2, если ползунок перемещается в любом месте от 1 до 1,99, он останется на 1. Затем, когда вы сдвинетесь на 2, он переместится в 2. Потому что int округляет все в меньшую сторону. См. Мой ответ для лучшего подхода к округлению. - person Adam Johns; 05.12.2014

ВЕРСИЯ SWIFT

Пример: вы хотите, чтобы ползунок двигался от 1 до 10000 с шагом 100. Настройка UISlider выглядит следующим образом:

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

В действии func () для ползунка используйте:

var sliderValue:Int = Int(sender.value) * 100
person Pescolly    schedule 18.01.2015

Другой подход 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

}
person Jure    schedule 16.11.2015
comment
Вы имеете в виду round(sender.value * step) / step? - person Aneel; 24.11.2015
comment
Формула, которую я использую, работает следующим образом: Допустим, UISlider идет от 0 до 100, а вам нужны шаги 10. Если текущее значение ползунка равно 14, ваш ползунок должен привязаться к 10: round(14/10) * 10 = 1 * 10 = 10 Если ваш ползунок имеет значение 46, вы хотите его нужно привязать к 50: round(46/10) * 10 = 5 * 10 = 50 В вашем случае результат будет тот же: round(46*10) / 10 = 460 / 10 = 46 Надеюсь, это проясняет. :) - person Jure; 24.11.2015
comment
В этом есть смысл. Я использовал ползунок с минимальным и максимальным значениями по умолчанию (0..1), и эта формула всегда давала 0. В этом случае умножение перед делением даст 0,0, 0,1, 0,2, ... 0,9, 1,0. Но, вероятно, более распространенный случай - установить другой максимум. - person Aneel; 24.11.2015
comment
О, понял! Да, если вы можете, установите более высокие минимальное и максимальное значение, иначе вам придется проделать еще несколько вычислений, как вы и поняли. - person Jure; 24.11.2015
comment
Я предлагаю изменить round() на floor(), чтобы избежать скользящего дрожания - person Johnny; 24.10.2017

Действительно простой:

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

Отлично, если вам нужно быстрое решение и вы добавили цель с помощью UIControlEventValueChanged.

person Leonard Pauli    schedule 07.04.2014