web-dev-qa-db-fra.com

Appuyez sur UISlider pour définir la valeur

J'ai créé un curseur (servant de contrôle de la vidéo, comme YouTube en bas) et défini les valeurs maximale (durée) et minimale. Et ensuite utilisé SeekToTime pour changer le currentTime. Maintenant, l'utilisateur peut faire glisser le curseur du curseur pour changer la valeur 

Ce que je veux réaliser est de laisser l'utilisateur appuyer n'importe où sur le curseur et régler l'heure actuelle de la vidéo.

J'ai eu une approche de cette réponse , et j'ai essayé de l'appliquer à mon cas, mais je n'ai pas réussi à la faire fonctionner.

class ViewController: UIViewController, PlayerDelegate {

var slider: UISlider!

override func viewDidLoad() {
  super.viewDidLoad()

  // Setup the slider
}

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

Je pensais que cela devrait fonctionner, mais pas de chance. Ensuite, j'ai essayé de déboguer en essayant d'imprimer "A" dans les journaux, mais cela ne semble donc pas aller dans la fonction sliderTapped()

Qu'est-ce que je fais mal? Ou y a-t-il un meilleur moyen de réaliser ce que j'essaie de réaliser?

15
senty

Il semble que vous ayez besoin d'initialiser la reconnaissance des gestes du tap dans votre viewDidLoad () conformément à l'exemple de code ci-dessus. Il y a un commentaire là-bas, mais je ne vois pas le logiciel de reconnaissance créé nulle part.

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)
    }
}
25
myuiviews

Il semble que le simple fait de sous-classer UISlider et de revenir toujours à true pour beginTracking produise l'effet souhaité.

iOS 10 et Swift 3

class CustomSlider: UISlider {
    override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
        return true
    }
}

Utilisez ensuite CustomSlider au lieu de UISlider dans votre code.

26
pteofil

Ceci est mon code, basé sur la réponse "myuiviews".
J'ai corrigé 2 petits "bugs" du code original.

1 - Taper sur 0 était trop difficile, alors j'ai rendu les choses plus faciles
2 - Faire glisser légèrement le pouce du curseur a également déclenché le "tapGestureRecognizer", ce qui le fait revenir à la position initiale. J'ai donc ajouté un filtre de distance minimale pour éviter cela.

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)
    }
}
1
Diogo Souza

La solution la plus simple serait probablement, en utilisant l'action "Retouche à l'intérieur", connectées via le constructeur d'interface.

@IBAction func finishedTouch(_ sender: UISlider) {

    finishedMovingSlider(sender)
}

Celui-ci sera appelé dès que votre doigt aura quitté l'écran du téléphone.

0
znx

la réponse de pteofil devrait être la réponse acceptée ici. 

Voici la solution pour Xamarin pour tous les intéressés:

public override bool BeginTracking(UITouch uitouch, UIEvent uievent)
{
    return true;
}

Comme mentionné par pteofil, vous devez sous-classer UISlider pour que cela fonctionne.

0
PunainenAurinko