Tap on UISlider to Set the Value

前端 未结 6 403
無奈伤痛
無奈伤痛 2021-02-01 19:20

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

相关标签:
6条回答
  • 2021-02-01 19:50

    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)
        }
    }
    
    0 讨论(0)
  • 2021-02-01 19:55

    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.

    0 讨论(0)
  • 2021-02-01 19:56

    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)
        }
    }
    
    0 讨论(0)
  • 2021-02-01 20:03

    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.

    0 讨论(0)
  • 2021-02-01 20:05

    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.

    0 讨论(0)
  • 2021-02-01 20:09

    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()
    
    0 讨论(0)
提交回复
热议问题