How to Enable "Tap and Slide" in a Uislider

Tap on UISlider to Set the Value

Looks like you need to actually initialize the tap gesture recognizer in your viewDidLoad() per the code example above. There's a comment there, but I don't see the recognizer being created anywhere.

Swift 2:

class ViewController: UIViewController {

var slider: UISlider!

override func viewDidLoad() {
super.viewDidLoad()

// Setup the slider

// Add a gesture recognizer to the slider
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "sliderTapped:")
self.slider.addGestureRecognizer(tapGestureRecognizer)
}

func sliderTapped(gestureRecognizer: UIGestureRecognizer) {
// print("A")

let pointTapped: CGPoint = gestureRecognizer.locationInView(self.view)

let positionOfSlider: CGPoint = slider.frame.origin
let widthOfSlider: CGFloat = slider.frame.size.width
let newValue = ((pointTapped.x - positionOfSlider.x) * CGFloat(slider.maximumValue) / widthOfSlider)

slider.setValue(Float(newValue), animated: true)
}
}

Swift 3:

class ViewController: UIViewController {

var slider: UISlider!

override func viewDidLoad() {
super.viewDidLoad()

// Setup the slider

// Add a gesture recognizer to the slider
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(sliderTapped(gestureRecognizer:)))
self.slider.addGestureRecognizer(tapGestureRecognizer)
}

func sliderTapped(gestureRecognizer: UIGestureRecognizer) {
// print("A")

let pointTapped: CGPoint = gestureRecognizer.location(in: self.view)

let positionOfSlider: CGPoint = slider.frame.origin
let widthOfSlider: CGFloat = slider.frame.size.width
let newValue = ((pointTapped.x - positionOfSlider.x) * CGFloat(slider.maximumValue) / widthOfSlider)

slider.setValue(Float(newValue), animated: true)
}
}

Go to tapped position of UISlider

UISlider's method is func setValue(_ value: Float, animated animated: Bool).

You'll need to cast your CGFloat to a Float.

So durationSlider.setValue(Float(newValue), animated: true)

iOS -How to have a separate UIView take control of a UISlider's thumbRect

I found the key to the problem here in this answer. @PaulaHasstenteufel said

// also remember to call valueChanged if there's any
// custom behaviour going on there and pass the slider
// variable as the parameter, as indicated below
self.sliderValueChanged(slider)

What I had to do was

  1. Use a UIPanGestureRecognizer
  2. comment out the UISlider's target action
  3. use the code from the target action's selector method in step-4 instead of using it in @objc func onSliderValChanged(sender: UISlider, event: UIEvent { }
  4. take the code from step-3 and add it to a new function
  5. add the function from step-5 to the bottom of the UIPanGetstureRecognizer's method

1- use the UIPanGestureRecognizer and make userInteraction is enabled for the UIView

let panGesture = UIPanGestureRecognizer(target: self, action: #selector(draggedView(_:)))
clearView.isUserInteractionEnabled = true
clearView.addGestureRecognizer(panGesture)

2- the Slider, I commented out it's addTarget for the .valueChanged event

let slider: UISlider = {
let slider = UISlider()
slider.translatesAutoresizingMaskIntoConstraints = false
slider.minimumValue = 1
slider.maximumValue = 5
slider.value = 1
slider.isContinuous = true
slider.maximumTrackTintColor = UIColor(white: 0, alpha: 0.3)

// ** COMMENT THIS OUT **
//slider.addTarget(self, action: #selector(onSliderValChanged(sender:event:)), for: .valueChanged)

return slider
}()

3- Take the code from the selector method the targetAction from above was using and instead insert that code in step 4

@objc func onSliderValChanged(sender: UISlider, event: UIEvent) {

/*
use this code in step-4 instead

slider.value = round(sender.value)

UIView.animate(withDuration: 0.25, animations: {
self.slider.layoutIfNeeded()

let trackRect = sender.trackRect(forBounds: sender.frame)
let thumbRect = sender.thumbRect(forBounds: sender.bounds, trackRect: trackRect, value: sender.value)
self.milesLabel.center = CGPoint(x: thumbRect.midX, y: sender.frame.origin.y - 55)

// ** all the other views are aligned with the thumbRect's center as it slides **

self.clearView.frame.origin = self.milesLabel.frame.origin
})
*/
}

4- Create a new method and insert the code from step-3

func sliderValueChanged(_ sender: UISlider, value: Float) {

// round the value for smooth sliding
sender.value = round(value)

UIView.animate(withDuration: 0.25, animations: {
self.slider.layoutIfNeeded()

let trackRect = sender.trackRect(forBounds: sender.frame)
let thumbRect = sender.thumbRect(forBounds: sender.bounds, trackRect: trackRect, value: sender.value)
self.milesLabel.center = CGPoint(x: thumbRect.midX, y: sender.frame.origin.y - 55)

// ** all the other views are aligned with the thumbRect's center as it slides **

self.clearView.frame.origin = self.milesLabel.frame.origin
})
}

5- I used the same code that I used for the UIGestureRecognizer but commented out the setValue function and instead used the function from step 4

@objc fileprivate func draggedView(_ sender: UIPanGestureRecognizer) {

if slider.isHighlighted { return }

let point = sender.location(in: slider)
let percentage = Float(point.x / slider.bounds.size.width)
let delta = percentage * (slider.maximumValue - slider.minimumValue)
let value = slider.minimumValue + delta

// I had to comment this out because the siding was to abrupt
//slider.setValue(value, animated: true)

// ** CALLING THIS FUNCTION FROM STEP-3 IS THE KEY TO GET THE UIView TO CONTROL THE SLIDER **
sliderValueChanged(slider, value: value)
}

How to delay start touch event of a UISlider in iOS?

You can disable user interaction on slider and then add a gesture recogniser over it (Not exactly sure about user interaction though). Maybe do something like this

let longPress = UILongPressGestureRecognizer(target: self.slider, action: Selector("longPressAndSlide:"))
longPress.minimumPressDuration = 0
self.addGestureRecognizer(longPress)

In longPressAndSlide you can calculate the direction and delta of movement and set the value of slider accordingly.

This has been answer multiple times actually. just a better search would help you more.

Update
Check answers under - How to enable "tap and slide" in a UISlider?

Latest Update
As the comments suggest, we can add a button on top of the slider and add longPress gesture over it. The handling can be done in the handler Action for the gesture.

Swift 4 The UISlider with AVPlayer doesn't slide

 Fixed it by deleting AVPlayer and changing AVPlayerItem to AVAudioPlayer, then putting the song URL into data : `

    //DOWNLOADS THE SONG IN THE URL AND PUTS IT IN DATA
var task: URLSessionTask? = nil

if let songUrl = songUrl {
task = URLSession.shared.dataTask(with: songUrl, completionHandler: { data, response, error in
// SELF.PLAYER IS STRONG PROPERTY
if let data = data {
self.playerItem = try? AVAudioPlayer(data: data)
self.playPause()
DispatchQueue.main.async {
self.sliderProgress()
}
}
})
task?.resume()`

Then I changed UISlider IBAction Value Changed to Touch Down and Touch Up Inside when I connected it to the ViewController:

    // TOUCH DOWN
@IBAction func SliderTouchDown(_ sender: UISlider) {
playerItem?.pause()
}

//TOUCH UP INSIDE
@IBAction func SliderTouchUpInside(_ sender: UISlider) {
playerItem?.currentTime = TimeInterval(sliderProgressOutlet.value)
playerItem?.play()
}

UISlider sliding event when its continuous set to No

It turns out It's my problem. I thought continous property set to YES will allow the UISlider to slide in float(While my value must be int, not float type).

self.progressSlider.continuous = YES; just call the value changed as long as the slider's value changed. It won't change the value to double.

self.progressSlider.continuous = No; When you're sliding the slider, value changed event won't be called until you release it.



Related Topics



Leave a reply



Submit