Обратите внимание, что в Интерфейсном Разработчике при добавлении действия у вас также есть возможность добавить к действию параметры отправителя и события.
Прекрасно работает! Откуда вы взяли для этого источник?
Рой Мулиа
2
спасибо @RoiMulia, не помню, где впервые увидел, уже много лет использую в слайдерах. Иногда я использую его, чтобы игнорировать изменение в UITouchPhaseEnded, поскольку значение имеет тенденцию к скачку, когда пользователь поднимает палец.
Девин Питчер,
2
Не забудьте установить isContinuous = trueв вашем UISlider.
krlbsk
2
Это отличное решение, однако у него есть проблема с отменой касания. Несмотря на то, что в перечислении touchEvent есть событие «cancelled», оно не запускается при отмене касания. Поэтому я рекомендую также добавить прослушиватель для события touchCancel из Slider. Это должно охватывать все возможности.
bnussey
2
Я видел, что иногда фаза может идти: началась, стояла, переместилась, но потом никогда не заканчивалась и не отменялась. Это проблематично для моего варианта использования, поскольку я ожидал, что каждое взаимодействие завершится или будет отменено. Исправление указано выше: используйте отдельную цель / действие отмены касания.
Jordan H
71
Я использую уведомления «Подкрашивание изнутри» и «Подкрашивание снаружи».
Разработчик интерфейса:
Подключите оба уведомления в Интерфейсном Разработчике к вашему методу получения. Метод может выглядеть так:
- (IBAction)lengthSliderDidEndSliding:(id)sender {
NSLog(@"Slider did end sliding... Do your stuff here");
}
В коде:
Если вы хотите подключить его программно, у вас будет что-то вроде этого в вашем viewWillAppear (или там, где вам подходит) вызов:
Это отправит вам dragEndedForSlider:сообщение, когда касание закончится.
Если вы хотите сделать это в своем наконечнике, вы можете щелкнуть слайдер, удерживая клавишу Control, чтобы открыть меню подключений, а затем перетащить его из гнезда «Touch Up Inside» на целевой объект.
Вы также должны добавить цель и действие для UIControlEventTouchUpOutsideи для UIControlEventTouchCancel.
@rob mayoff Извините, но вам нужно использовать UIControlEventTouchUpOutside. В противном случае селектор не будет вызываться, если ваш палец не находится на слайдере, когда вы закончите перетаскивание.
user3164248
2
Поведение UISliderизменилось с тех пор, как я написал этот ответ.
Роб Мэйофф
Могу подтвердить, что вам также необходимо зарегистрировать обработчик для UIControlEventTouchUpOutside в iOS 9.
lms
Мне никогда не удавалось вызвать UIControlEventTouchCancelобработчик в iOS 9. Но я могу вызвать UIControlEventTouchUpInsideи UIControlEventTouchUpOutsideтолько.
петрсын
17
Swift 5 и Swift 4
Добавить цель для touchUpInsideи touchUpOutsideсобытий. Вы можете сделать это программно или из раскадровки. Вот как вы это делаете программно
У меня была такая же проблема, и в конце концов это заработало, так что, возможно, это кому-то поможет. Подключите your_Slider к «Value Changed» в раскадровке, и при перемещении слайдера «Slider Touched» активирован, а когда отпущен «Slider Released».
Иногда вам может потребоваться, чтобы события перетаскивания ползунка запускались непрерывно, но у вас есть возможность выполнять другой код в зависимости от того, перетаскивается ли ползунок все еще или только что перетаскивание.
Для этого я расширил ответ Энди выше, в котором используется isTrackingсвойство ползунка . Мне нужно было записать два состояния: sliderHasFinishedTrackingи sliderLastStoredValue.
Мой код правильно:
не запускает действие при запуске перетаскивания
запускает действие, если пользователь подталкивает ползунок только одним нажатием (то есть, что isTrackingостается false)
classSliderExample: UIViewController{
var slider: UISlider = UISlider()
var sliderHasFinishedTracking: Bool = truevar sliderLastStoredValue: Float!overridefuncloadView() {
super.loadView()
slider.minimumValue = 100.0
slider.maximumValue = 200.0
slider.isContinuous = true
slider.value = 100.0self.sliderLastStoredValue = slider.value
slider.addTarget(self, action: #selector(respondToSlideEvents), for: .valueChanged)
// add your slider to the view however you like
}
funcrespondToSlideEvents(sender: UISlider) {
let currentValue: Float = Float(sender.value)
print("Event fired. Current value for slider: \(currentValue)%.")
if(slider.isTracking) {
self.sliderHasFinishedTracking = falseprint("Action while the slider is being dragged ⏳")
} else {
if(self.sliderHasFinishedTracking && currentValue == self.sliderLastStoredValue){
print("Slider has finished tracking and its value hasn't changed, " +
"yet event was fired anyway. 🤷") // No need to take action.
} else {
self.sliderHasFinishedTracking = trueprint("Action upon slider drag/tap finishing ⌛️")
}
}
self.sliderLastStoredValue = currentValue
}
}
Создайте действие и выход для ползунка (или вы можете привести тип отправителя из действия в UISlider) и в пользовательском интерфейсе снимите флажок «Непрерывные обновления». Таким образом, мы получим значение ползунка только тогда, когда ползунок перестанет перетаскивать.
@IBActionfuncactionSlider(_ sender: Any) {
let value = sliderSpeed.value.rounded()
}
Ответы:
Если вам не нужны данные между перетаскиванием, вы должны просто установить:
[mySlider setContinuous: NO];
Таким образом, вы получите
valueChanged
событие только тогда, когда пользователь перестанет перемещать ползунок.Версия Swift 5 :
mySlider.isContinuous = false
источник
self.mySlider.isContinuous = false
Вы можете добавить действие, которое принимает два параметра, отправителя и событие, для UIControlEventValueChanged:
[slider addTarget:self action:@selector(onSliderValChanged:forEvent:) forControlEvents:UIControlEventValueChanged]
Затем проверьте фазу сенсорного объекта в вашем обработчике:
- (void)onSliderValChanged:(UISlider*)slider forEvent:(UIEvent*)event { UITouch *touchEvent = [[event allTouches] anyObject]; switch (touchEvent.phase) { case UITouchPhaseBegan: // handle drag began break; case UITouchPhaseMoved: // handle drag moved break; case UITouchPhaseEnded: // handle drag ended break; default: break; } }
Swift 4 и 5
slider.addTarget(self, action: #selector(onSliderValChanged(slider:event:)), for: .valueChanged)
@objc func onSliderValChanged(slider: UISlider, event: UIEvent) { if let touchEvent = event.allTouches?.first { switch touchEvent.phase { case .began: // handle drag began case .moved: // handle drag moved case .ended: // handle drag ended default: break } } }
Обратите внимание, что в Интерфейсном Разработчике при добавлении действия у вас также есть возможность добавить к действию параметры отправителя и события.
источник
isContinuous = true
в вашемUISlider
.Я использую уведомления «Подкрашивание изнутри» и «Подкрашивание снаружи».
Разработчик интерфейса:
Подключите оба уведомления в Интерфейсном Разработчике к вашему методу получения. Метод может выглядеть так:
- (IBAction)lengthSliderDidEndSliding:(id)sender { NSLog(@"Slider did end sliding... Do your stuff here"); }
В коде:
Если вы хотите подключить его программно, у вас будет что-то вроде этого в вашем viewWillAppear (или там, где вам подходит) вызов:
[_mySlider addTarget:self action:@selector(sliderDidEndSliding:) forControlEvents:(UIControlEventTouchUpInside | UIControlEventTouchUpOutside)];
Метод получения будет выглядеть так:
- (void)sliderDidEndSliding:(NSNotification *)notification { NSLog(@"Slider did end sliding... Do your stuff here"); }
источник
Поскольку
UISlider
это подклассUIControl
, вы можете установить для него цель и действиеUIControlEventTouchUpInside
.Если вы хотите сделать это в коде, это будет выглядеть так:
[self.slider addTarget:self action:@selector(dragEndedForSlider:) forControlEvents:UIControlEventTouchUpInside];
Это отправит вам
dragEndedForSlider:
сообщение, когда касание закончится.Если вы хотите сделать это в своем наконечнике, вы можете щелкнуть слайдер, удерживая клавишу Control, чтобы открыть меню подключений, а затем перетащить его из гнезда «Touch Up Inside» на целевой объект.
Вы также должны добавить цель и действие для
UIControlEventTouchUpOutside
и дляUIControlEventTouchCancel
.источник
UISlider
изменилось с тех пор, как я написал этот ответ.UIControlEventTouchCancel
обработчик в iOS 9. Но я могу вызватьUIControlEventTouchUpInside
иUIControlEventTouchUpOutside
только.Swift 5 и Swift 4
Добавить цель для
touchUpInside
иtouchUpOutside
событий. Вы можете сделать это программно или из раскадровки. Вот как вы это делаете программноslider.addTarget(self, action: #selector(sliderDidEndSliding), for: [.touchUpInside, .touchUpOutside])
Напишите свою функцию для обработки конца перетаскивания ползунка
func sliderDidEndSliding() { print("end sliding") }
источник
Ты можешь использовать:
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
для обнаружения событий touchDown и touchUp в UISlider
источник
Я думаю, вам нужно контрольное событие
UIControlEventTouchUpInside
.источник
Swift 3 ответ
У меня была такая же проблема, и в конце концов это заработало, так что, возможно, это кому-то поможет. Подключите your_Slider к «Value Changed» в раскадровке, и при перемещении слайдера «Slider Touched» активирован, а когда отпущен «Slider Released».
@IBAction func your_Slider(_ sender: UISlider) { if (yourSlider.isTracking) { print("Slider Touched") } else { print("Slider Released") } }
источник
Подключите
Touch Up Inside
иValue Changed
источник
Swift 3.1
Иногда вам может потребоваться, чтобы события перетаскивания ползунка запускались непрерывно, но у вас есть возможность выполнять другой код в зависимости от того, перетаскивается ли ползунок все еще или только что перетаскивание.
Для этого я расширил ответ Энди выше, в котором используется
isTracking
свойство ползунка . Мне нужно было записать два состояния:sliderHasFinishedTracking
иsliderLastStoredValue
.Мой код правильно:
не запускает действие при запуске перетаскивания
запускает действие, если пользователь подталкивает ползунок только одним нажатием (то есть, что
isTracking
остаетсяfalse
)class SliderExample: UIViewController { var slider: UISlider = UISlider() var sliderHasFinishedTracking: Bool = true var sliderLastStoredValue: Float! override func loadView() { super.loadView() slider.minimumValue = 100.0 slider.maximumValue = 200.0 slider.isContinuous = true slider.value = 100.0 self.sliderLastStoredValue = slider.value slider.addTarget(self, action: #selector(respondToSlideEvents), for: .valueChanged) // add your slider to the view however you like } func respondToSlideEvents(sender: UISlider) { let currentValue: Float = Float(sender.value) print("Event fired. Current value for slider: \(currentValue)%.") if(slider.isTracking) { self.sliderHasFinishedTracking = false print("Action while the slider is being dragged ⏳") } else { if(self.sliderHasFinishedTracking && currentValue == self.sliderLastStoredValue){ print("Slider has finished tracking and its value hasn't changed, " + "yet event was fired anyway. 🤷") // No need to take action. } else { self.sliderHasFinishedTracking = true print("Action upon slider drag/tap finishing ⌛️") } } self.sliderLastStoredValue = currentValue } }
источник
В Swift 4 вы можете использовать эту функцию
1 Первый шаг: - Добавление цели в слайдер
self.distanceSlider.addTarget(self, action: #selector(self.sliderDidEndSliding(notification:)), for: ([.touchUpInside,.touchUpOutside]))
2 Второй шаг: - Создайте функцию
@objc func sliderDidEndSliding(notification: NSNotification) { print("Hello-->\(distanceSlider.value)") }
источник
Возможно, вам следует добавить цель для событий UIControlEventTouchUpInside 、 UIControlEventTouchUpOutside 、 UIControlEventTouchCancel.
Я сталкивался с той же проблемой раньше, потому что я не добавляю цель для события UIControlEventTouchCancel .
источник
Недавно у меня была аналогичная проблема. Вот что я сделал в Swift:
theSlider.continuous = false;
Код, содержащий это непрерывное значение, читает:
public var continuous: Bool // if set, value change events are generated // any time the value changes due to dragging. default = YES
По умолчанию, похоже, ДА (правда). Установка его в false делает то, что вы хотите.
источник
Попробуйте вот так
customSlider.minimumValue = 0.0; customSlider.maximumValue = 10.0; [customSlider addTarget:self action:@selector(changeSlider:) forControlEvents:UIControlEventValueChanged]; -(void)changeSlider:(id)sender{ UISlider *slider=(UISlider *)sender; float sliderValue=(float)(slider.value ); NSLog(@"sliderValue = %f",sliderValue); }
источник
RxSwift:
self.slider.rx.controlEvent([.touchUpInside, .touchUpOutside]) .bind(to: self.viewModel.endSlidingSlider) .disposed(by: self.disposeBag)
источник
Создайте действие и выход для ползунка (или вы можете привести тип отправителя из действия в UISlider) и в пользовательском интерфейсе снимите флажок «Непрерывные обновления». Таким образом, мы получим значение ползунка только тогда, когда ползунок перестанет перетаскивать.
@IBAction func actionSlider(_ sender: Any) { let value = sliderSpeed.value.rounded() }
источник