iPhone : How to detect the end of slider drag?

IosIphoneIos5Ios4Uislider

Ios Problem Overview


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

Ios Solutions


Solution 1 - Ios

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.

Swift 5 version:

mySlider.isContinuous = false

Solution 2 - Ios

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

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

Solution 3 - Ios

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

Solution 4 - Ios

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.

Solution 5 - Ios

Swift 5 and Swift 4
  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")
    }
    

Solution 6 - Ios

You can use:

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

to detect when the touchDown and touchUp events occur in UISlider

Solution 7 - Ios

I think you need the control event UIControlEventTouchUpInside.

Solution 8 - Ios

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

Solution 9 - Ios

Connect Touch Up Inside and Value Changed

enter image description here

Solution 10 - Ios

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. 🤷") // No need to take action.
      } else {
        self.sliderHasFinishedTracking = true
        print("Action upon slider drag/tap finishing ⌛️")
      }
    }
      
    self.sliderLastStoredValue = currentValue
  }
}

Solution 11 - Ios

In Swift 4 you can use this function

1 Frist step:- Adding the target in slider

self.distanceSlider.addTarget(self, action: #selector(self.sliderDidEndSliding(notification:)), for: ([.touchUpInside,.touchUpOutside]))

2 Second step:- Create a function

@objc func sliderDidEndSliding(notification: NSNotification)
{
   print("Hello-->\(distanceSlider.value)")
}

Solution 12 - Ios

Maybe you should add target for UIControlEventTouchUpInside、UIControlEventTouchUpOutside、UIControlEventTouchCancel events.

I met the same problem before , because i don't add target for UIControlEventTouchCancel event.

Solution 13 - Ios

I had similar issue recently. Here is what I did in Swift:

    theSlider.continuous = false;

The code that holds this continuous value reads:

public var continuous: Bool // if set, value change events are generated
    // any time the value changes due to dragging. default = YES

The default seems to be YES (true). Setting it it to false does the thing you want.

Solution 14 - Ios

RxSwift:

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

Solution 15 - Ios

Create an action and outlet for the slider (or you can typecast sender from action to UISlider), and in the UI Uncheck the Continuous Updates check box. This way we will get the slider value only when slider stops dragging.

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

enter image description here

Solution 16 - Ios

Try like this

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDroidHeavenView Question on Stackoverflow
Solution 1 - IosRok JarcView Answer on Stackoverflow
Solution 2 - IosDevin PitcherView Answer on Stackoverflow
Solution 3 - IosthomasView Answer on Stackoverflow
Solution 4 - Iosrob mayoffView Answer on Stackoverflow
Solution 5 - IosGuy DaherView Answer on Stackoverflow
Solution 6 - IosMudit BajpaiView Answer on Stackoverflow
Solution 7 - IosscorpiozjView Answer on Stackoverflow
Solution 8 - IosAndyView Answer on Stackoverflow
Solution 9 - IosAtefView Answer on Stackoverflow
Solution 10 - IosJamie BirchView Answer on Stackoverflow
Solution 11 - Iospansora abhayView Answer on Stackoverflow
Solution 12 - IoszhuomingView Answer on Stackoverflow
Solution 13 - IosEvdzhan MustafaView Answer on Stackoverflow
Solution 14 - IosAdam SmakaView Answer on Stackoverflow
Solution 15 - IosSameer JagtapView Answer on Stackoverflow
Solution 16 - IosRaj SubbiahView Answer on Stackoverflow