iPhone : How to detect the end of slider drag?
IosIphoneIos5Ios4UisliderIos 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
-
Add target for
touchUpInside
andtouchUpOutside
events. You can do it either programatically or from storyboard. This is how you do it programaticallyslider.addTarget(self, action: #selector(sliderDidEndSliding), for: [.touchUpInside, .touchUpOutside])
-
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
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
remainsfalse
)
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()
}
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);
}