iPhone : How to detect the end of slider drag?

2019-01-13 05:48发布

问题:

How to detect the event when the user has ended the drag of a slider pointer?

回答1:

If you don't need any data inbetween drag, than you should simply set:

[mySlider setContinuous: NO];

This way you will receive valueChanged event only when the user stops moving the slider.



回答2:

I use the "Touch Up Inside" and "Touch up outside" notifications.

Interface Builder:

Connect both notifications in the Interface Builder to your receiving method. The method could look like this:

- (IBAction)lengthSliderDidEndSliding:(id)sender {
    NSLog(@"Slider did end sliding... Do your stuff here");
}

In code:

If you want to wire it programatically you would have something like this in your viewWillAppear (or wherever it fits you) call:

[_mySlider addTarget:self
              action:@selector(sliderDidEndSliding:) 
    forControlEvents:(UIControlEventTouchUpInside | UIControlEventTouchUpOutside)];

The receiving method would look like this:

- (void)sliderDidEndSliding:(NSNotification *)notification {
     NSLog(@"Slider did end sliding... Do your stuff here");
}


回答3:

You can add an action that takes two parameters, sender and an event, for UIControlEventValueChanged:

[slider addTarget:self action:@selector(onSliderValChanged:forEvent:) forControlEvents:UIControlEventValueChanged]

Then check the phase of the touch object in your handler:

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

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

Note in Interface Builder when adding an action you also have the option to add both sender and event parameters to the action.



回答4:

Since UISlider is a subclass of UIControl, you can set a target and action for its UIControlEventTouchUpInside.

If you want to do it in code, it looks like this:

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

That will send you a dragEndedForSlider: message when the touch ends.

If you want to do it in your nib, you can control-click your slider to get its connections menu, and then drag from the “Touch Up Inside” socket to the target object.

You should also add a target and action for UIControlEventTouchUpOutside and for UIControlEventTouchCancel.



回答5:

You can use:

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

to detect when the touchDown and touchUp events occur in UISlider



回答6:

Swift 4 and Swift 3

  1. Add target for touchUpInside and touchUpOutside events. You can do it either programatically or from storyboard. This is how you do it programatically

    slider.addTarget(self, action: #selector(sliderDidEndSliding), for: [.touchUpInside, .touchUpOutside])
    
  2. Write your function to handle the end of slider drag

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


回答7:

I think you need the control event UIControlEventTouchUpInside.



回答8:

Swift 3 answer

I had same problem and eventually got this to work, so maybe it will help somebody. Connect your_Slider to 'Value Changed' in storyboard and when slider moved "Slider Touched" actioned and when let go "Slider Released".

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


回答9:

Connect Touch Up Inside and Value Changed



回答10:

Swift 3.1

Sometimes you will want the slider's drag events to fire continuously, but have the option of executing different code depending on whether the slider is still being dragged or has just finished being dragged.

To do this, I've expanded on Andy's answer above that makes use of the slider's isTracking property. I needed to record two states: sliderHasFinishedTracking and sliderLastStoredValue.

My code correctly:

  • doesn't fire an action upon starting drag

  • fires the action if the user only nudges the slider with a single tap (meaning that isTracking remains 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.