iPhone: Як виявити кінець перетягування повзунка?


96

Як виявити подію, коли користувач закінчив перетягування повзунка?


1
Використання: [повзунок addTarget: самодіяльність: @selector (sliderStoppedDragging :) forControlEvents: UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
Генрі Су

Відповіді:


179

Якщо вам не потрібні дані між перетягуванням, вам слід просто встановити:

[mySlider setContinuous: NO];

Таким чином ви отримаєте valueChangedподію лише тоді, коли користувач перестане рухати повзунок.

Версія Swift 5 :

mySlider.isContinuous = false

2
Це найкраща відповідь на це питання. Я хотів би змінити відповідь на це.
M. Porooshani

1
i.imgur.com/0Edd2xe.png?1 XCode версії 6.x має цю функцію встановлення setContinuous за допомогою самої IDE.
Абхієет,

1
Так, найкраща відповідь така.
sabiland

3
Чудова відповідь. Ось код Swift 4:self.mySlider.isContinuous = false
Марко Вебер

2
Це не те, про що запитує автор. Він хоче постійно ковзати, а також хоче знати, коли зупинятися.
lbsweek

120

Ви можете додати дію, яка приймає два параметри, відправника та подію, для 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;
    }
}

Свіфт 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
        }
    }
}

Примітка у Interface Builder, додаючи дію, ви також можете додати до дії параметри відправника та події.


1
Працює ідеально! Де ви взяли для цього джерело?
Roi Mulia

2
дякую @RoiMulia, я не пам’ятаю, де я це вперше побачив, роками використовую в повзунках. Іноді я використовую його, щоб проігнорувати зміну на UITouchPhaseEnded, оскільки значення має тенденцію стрибати, коли користувач піднімає палець.
Devin Pitcher

2
Не забудьте встановити isContinuous = trueу вашому UISlider.
krlbsk

2
Це чудове рішення, однак у нього є проблема зі скасуванням дотику. Незважаючи на те, що в переліку touchEvent є подія "скасовано", вона не запускається, коли дотик скасовано. Тому я рекомендую також додати слухач для події touchCancel із повзунка. Це повинно охоплювати всі можливості.
bnussey

2
Я бачив, що інколи фаза може йти: почалася, нерухома, переїхала, але потім ніколи не закінчилась і не скасована. Це проблематично для мого випадку використання, оскільки я очікував, що кожна взаємодія закінчиться або буде скасована. Виправлення зазначено вище: використовуйте окрему ціль / дію для скасування дотику.
Йорданія H

71

Я використовую сповіщення "Touch Up Inside" та "Touch up outside".

Конструктор інтерфейсів:

Підключіть обидва сповіщення у Interface Builder до способу отримання. Метод може виглядати так:

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

19

Оскільки UISliderце підклас UIControl, ви можете встановити ціль і дію для нього UIControlEventTouchUpInside.

Якщо ви хочете зробити це в коді, це виглядає так:

[self.slider addTarget:self action:@selector(dragEndedForSlider:)
    forControlEvents:UIControlEventTouchUpInside];

Це надішле вам dragEndedForSlider:повідомлення, коли дотик закінчиться.

Якщо ви хочете зробити це за допомогою перо, ви можете натиснути на повзунок, клацнувши клавішу управління, щоб отримати меню його з'єднань, а потім перетягнути з гнізда “Touch Up Inside” до цільового об’єкта.

Слід також додати ціль і дії для UIControlEventTouchUpOutsideі за UIControlEventTouchCancel.


1
@rob mayoff Вибачте, але вам потрібно використовувати UIControlEventTouchUpOutside. В іншому випадку селектор не буде викликаний, якщо ваш палець не знаходиться на повзунку, коли ви закінчите перетягування.
user3164248

2
З UISliderмоменту написання цієї відповіді поведінка користувача змінилася.
грабувати майофф

Можна підтвердити , що ви дійсно повинні також зареєструвати обробник для UIControlEventTouchUpOutside в прошивкою 9.
Плівки

Я ніколи не міг викликати UIControlEventTouchCancelобробник в iOS 9. Але я можу викликати UIControlEventTouchUpInsideі UIControlEventTouchUpOutsideлише.
petrsyn

17

Свіфт 5 і Свіфт 4

  1. Додати мета для touchUpInsideі touchUpOutsideподій. Ви можете зробити це або програмно, або з розкадровки. Це як ви робите це програмно

    slider.addTarget(self, action: #selector(sliderDidEndSliding), for: [.touchUpInside, .touchUpOutside])
    
  2. Напишіть свою функцію для обробки кінця перетягування повзунка

    func sliderDidEndSliding() {
        print("end sliding")
    }
    

Привіт. Як я можу призупинити відео, коли починаю перетягувати?
kemdo

Це не визначає, чи завжди колись траплялося перетягування, і може бути викликане простим натисканням без перетягування.
Chewie The Chorkie

9

Ви можете використовувати:

- (void)addTarget:(id)target action:(SEL)action 
                   forControlEvents:(UIControlEvents)controlEvents  

щоб виявити, коли в UISlider відбуваються події touchDown та touchUp



5

Швидка відповідь 3

У мене була така сама проблема, і врешті-решт це змусило працювати, тож, можливо, це допоможе комусь Підключіть your_Slider до 'Значення змінено' в розкадровці, і коли повзунок переміщується "Повзунок торкнувся" діяв, а коли відпустив "Повзунок звільнений".

@IBAction func your_Slider(_ sender: UISlider) {
    if (yourSlider.isTracking) {
        print("Slider Touched")
    } else {
        print("Slider Released")
    }
}

2
Хороше рішення, але обережне, тому що Slider Released викликається, коли починається перетягування і закінчується перетягування
Гай Дахер,

а іноді не називається "Slider Released" при випуску
Вадим


4

Свіфт 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
  }
}

4

У 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)")
}

2

Можливо, вам слід додати ціль для подій UIControlEventTouchUpInside 、 UIControlEventTouchUpOutside 、 UIControlEventTouchCancel.

Я зустрічав ту саму проблему раніше, оскільки не додаю ціль для події UIControlEventTouchCancel .


1

Нещодавно у мене була подібна проблема. Ось що я зробив у Свіфті:

    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, це робить те, що ви хочете.


0

Спробуйте так

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

Це надсилає дію кожного разу, коли великий палець рухається, а не лише коли закінчується перетягування.
грабувати майофф

0

RxSwift:

self.slider.rx.controlEvent([.touchUpInside, .touchUpOutside])
    .bind(to: self.viewModel.endSlidingSlider)
    .disposed(by: self.disposeBag)

0

Створіть дію та розетку для повзунка (або ви можете ввести відправника від дії до UISlider) і в інтерфейсі зніміть прапорець Неперервні оновлення. Таким чином ми отримаємо значення повзунка лише тоді, коли повзунок перестане перетягуватися.

@IBAction func actionSlider(_ sender: Any) {
   let value = sliderSpeed.value.rounded()
}

введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.