I created a Slider (operating as control of the video, like YouTube has at the bottom) and set the maximum (duration) and minimum values. And then used SeekToTime
t
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)
}
}
The probably simplest solution would be, using the "touch up inside" action, connected trough the interface builder.
@IBAction func finishedTouch(_ sender: UISlider) {
finishedMovingSlider(sender)
}
This will get called as soon as your finger leaves the phone screen.
This is my code, based on "myuiviews" answer.
I fixed 2 little "bugs" of the original code.
1 - Tapping on 0 was too difficult, so I made it easier
2 - Sliding the slider's thumb just a little bit was also firing the "tapGestureRecognizer", which makes it return to the initial position, so I added a minimum distance filter to avoid that.
Swift 4
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)
}
@objc func sliderTapped(gestureRecognizer: UIGestureRecognizer) {
// print("A")
var pointTapped: CGPoint = gestureRecognizer.location(in: self.view)
pointTapped.x -= 30 //Subtract left constraint (distance of the slider's origin from "self.view"
let positionOfSlider: CGPoint = slider.frame.origin
let widthOfSlider: CGFloat = slider.frame.size.width
//If tap is too near from the slider thumb, cancel
let thumbPosition = CGFloat((slider.value / slider.maximumValue)) * widthOfSlider
let dif = abs(pointTapped.x - thumbPosition)
let minDistance: CGFloat = 51.0 //You can calibrate this value, but I think this is the maximum distance that tap is recognized
if dif < minDistance {
print("tap too near")
return
}
var newValue: CGFloat
if pointTapped.x < 10 {
newValue = 0 //Easier to set slider to 0
} else {
newValue = ((pointTapped.x - positionOfSlider.x) * CGFloat(slider.maximumValue) / widthOfSlider)
}
slider.setValue(Float(newValue), animated: true)
}
}
pteofil's answer should be the accepted answer here.
Below is the solution for Xamarin for everyone's interested:
public override bool BeginTracking(UITouch uitouch, UIEvent uievent)
{
return true;
}
As pteofil mentioned, you need to subclass the UISlider for this to work.
It seems like just subclassing UISlider and returning always true to the beginTracking produce the desired effect.
iOS 10 and Swift 3
class CustomSlider: UISlider {
override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
return true
}
}
Use the CustomSlider instead of UISlider afterwards in your code.
I like this approach
extension UISlider {
public func addTapGesture() {
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
addGestureRecognizer(tap)
}
@objc private func handleTap(_ sender: UITapGestureRecognizer) {
let location = sender.location(in: self)
let percent = minimumValue + Float(location.x / bounds.width) * maximumValue
setValue(percent, animated: true)
sendActions(for: .valueChanged)
}
}
And later just call
let slider = UISlider()
slider.addTapGesture()