Нажмите на UISlider для установки значения
Я создал слайдер (работающий как контроль над видео, как у YouTube внизу) и установите максимальные (длительность) и минимальные значения. А затем использовал SeekToTime
, чтобы изменить currentTime. Теперь пользователь может скользить большим пальцем ползунка, чтобы изменить значение
То, что я хочу достичь, это позволить пользователю нажимать в любом месте ползунка и устанавливать текущее время видео.
У меня есть подход от этого ответа, и я попытался применить его к моему делу, но не смог заставить его работать
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)
}
}
Я думал, что это должно сработать, но не повезло. Затем я попробовал отладку с попыткой распечатать "A" в журналах, но, похоже, он не входит в функцию sliderTapped()
.
Что я делаю неправильно? Или есть лучший способ достичь того, чего я пытаюсь достичь?
Ответы
Ответ 1
Похоже, вам нужно фактически инициализировать распознаватель жестов в вашем представленииDidLoad() для примера кода выше. Там есть комментарий, но я не вижу, как распознаватель создается где угодно.
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)
}
}
Ответ 2
Похоже, что просто подклассифицировать UISlider и всегда возвращать true для beginTracking, вы получите желаемый эффект.
iOS 10 и Swift 3
class CustomSlider: UISlider {
override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
return true
}
}
Используйте CustomSlider вместо UISlider после этого в вашем коде.
Ответ 3
Это мой код, основанный на ответе "myuiviews".
Я исправил 2 маленьких "ошибки" исходного кода.
1 - Нажатие на 0 было слишком сложным, поэтому я упростил его
2 - Сдвиг большого пальца слайдера немного активировал "tapGestureRecognizer", который заставляет его вернуться в исходное положение, поэтому я добавил фильтр минимального расстояния, чтобы этого избежать.
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 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)
}
}
Ответ 4
Ответ pteofil должен быть принятым ответом здесь.
Ниже приведено решение для Xamarin для всех желающих:
public override bool BeginTracking(UITouch uitouch, UIEvent uievent)
{
return true;
}
Как указано в pteofil, вам нужно подклассифицировать UISlider, чтобы это работало.