Как определить событие, когда пользователь закончил перетаскивание указателя ползунка?
iPhone: Как определить конец перетаскивания ползунка?
Ответы (16)
Если вам не нужны данные между перетаскиванием, вы должны просто установить:
[mySlider setContinuous: NO];
Таким образом, вы получите valueChanged
событие только тогда, когда пользователь перестанет перемещать ползунок.
Версия Swift 5:
mySlider.isContinuous = false
Events [x] Continuous Updates
параметр для UISliderView. Снятие этого флажка устанавливает continuous
в значение false / NO.
- person leanne; 14.07.2016
self.mySlider.isContinuous = false
- person Marco Weber; 16.12.2017
Вы можете добавить действие, которое принимает два параметра, отправителя и событие, для 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
}
}
}
Обратите внимание, что в Интерфейсном Разработчике при добавлении действия у вас также есть возможность добавить к действию параметры отправителя и события.
allTouches
есть несколько событий, принадлежащих разным фазам?
- person David; 10.03.2017
isContinuous = true
в свой UISlider
.
- person krlbsk; 20.09.2017
allTouches
будет nil
при увеличении / уменьшении значения с помощью VoiceOver.
- person Jordan H; 28.01.2020
Я использую уведомления «Подкрашивание изнутри» и «Подкрашивание снаружи».
Разработчик интерфейса:
Подключите оба уведомления в Интерфейсном Разработчике к вашему методу получения. Метод может выглядеть так:
- (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
изменилось с тех пор, как я написал этот ответ.
- person rob mayoff; 11.04.2015
UIControlEventTouchCancel
в iOS 9. Но я могу вызывать только UIControlEventTouchUpInside
и UIControlEventTouchUpOutside
.
- person petrsyn; 29.09.2016
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")
}
}
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()
}