ios 点击UISlider以设置值

7ajki6be  于 2023-01-27  发布在  iOS
关注(0)|答案(8)|浏览(146)

我创建了一个Slider(作为视频的控件,就像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()函数。
我做错了什么?或者有没有更好的方法来实现我正在努力实现的目标?

kq0g1dla

kq0g1dla1#

看起来你需要在你的viewDidLoad()中根据上面的代码示例实际初始化点击手势识别器。这里有一个注解,但是我没有看到识别器正在创建。

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

雨燕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)
    }
}
vptzau2j

vptzau2j2#

看起来只是对UISlider进行子类化并总是返回true到beginTracking就可以产生所需的效果。

iOS 10和雨燕3

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

以后在代码中使用CustomSlider而不是UISlider。

piztneat

piztneat3#

我喜欢这种方法

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

以后再打电话

let slider = UISlider()
slider.addTapGesture()
neekobn8

neekobn84#

这是我的代码,基于"myuiviews"答案。
我修正了原始代码的两个小"bug"。
1-点击0太难了,所以我让它变得更容易
2-滑动滑块的拇指一点点也会触发"tapGestureRecognizer",这会使它返回到初始位置,所以我添加了一个最小距离过滤器来避免这种情况。

    • 雨燕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)
    }
}
k0pti3hp

k0pti3hp5#

我实现了pteofil,但是,因为我已经有一个附加到valueChanged的操作,所以我在跟踪方面遇到了问题。
我在看Adam的答案,我注意到他也做了一个很好的实现,除了我通常不喜欢添加手势识别器。所以我结合了两个答案(有点),现在我都可以使用滑动来改变值(因此触发valueChanged以及如果点击滑块:
1.我子类化了UISlider,并重写了beginTracking方法:

override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
        return true //Without this, we don't get any response in the method below 
    }

1.然后我重写了touchEnded方法(我想您也可以重写其他状态,但这似乎是逻辑上最合适的一个)

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else { return }
        let location = touch.location(in: self)
        let conversion = minimumValue + Float(location.x / bounds.width) * maximumValue
        setValue(conversion, animated: false)
        sendActions(for: .valueChanged) //Add this because without this it won't work.
    }

我在其他地方也有我的标准IBAction(这与上面的内容没有直接关系,但我添加它是为了提供完整的上下文):

@IBAction func didSkipToTime(_ sender: UISlider) {
        print("sender value: \(sender.value)") // Do whatever in this method
    }

希望它会有一些用处,适合你的需要。

ukdjmx9f

ukdjmx9f6#

pteofil的答案应该是这里可接受的答案。
下面是Xamarin的解决方案,每个人都感兴趣:

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

正如pteofil所提到的,您需要对UISlider进行子类化才能使其工作。

eit6fx6z

eit6fx6z7#

因此,将问题看作一个滑块,可以通过滑动“拇指”或点击整个滑块来改变其值,并将本页上已有的大量答案和评论汇总在一起,我们可以将解决方案简洁地表达为:

class MySlider: UISlider {
    override init(frame: CGRect) {
        super.init(frame:frame)
        config()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        config()
    }

    func config() {
        let tap = UITapGestureRecognizer(target: self, action: #selector(tapped))
        addGestureRecognizer(tap)
    }

    @objc func tapped(_ tapper: UITapGestureRecognizer) {
        let pointTappedX = tapper.location(in: self).x
        let positionOfSliderX = bounds.origin.x + 15
        let widthOfSlider = bounds.size.width - 30
        let newX = (pointTappedX - positionOfSliderX) / widthOfSlider

        let newValue = newX * CGFloat(maximumValue) + (1 - newX) * CGFloat(minimumValue)
        setValue(Float(newValue), animated: true)
        sendActions(for: .valueChanged)
    }
}
b09cbbtk

b09cbbtk8#

可能最简单的解决方案是,使用“touchupinside”操作,通过界面构建器连接。

@IBAction func finishedTouch(_ sender: UISlider) {

    finishedMovingSlider(sender)
}

只要你的手指离开手机屏幕,就会调用这个命令。

相关问题