点击UISlider设置值

时间:2021-08-03 08:26:49

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 to change the currentTime. Now, the user can slide the thumb of the slider to change the value

我创建了一个Slider(作为视频的控件,就像YouTube在底部一样)并设置最大值(持续时间)和最小值。然后使用SeekToTime更改currentTime。现在,用户可以滑动滑块的拇指来更改值

What I want to achieve is letting the user tap on anywhere on the slider and set the current time of the video.

我想要实现的是让用户点击滑块上的任意位置并设置视频的当前时间。

I got an approach from this answer, and I tried to apply it to my case, but couldn't make it work

我从这个答案中得到了一个方法,我试着将它应用到我的案例中,但是无法使它成功

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

I thought this should work, but no luck. Then I tried debugging with trying to printing "A" to logs, but it doesn't so apparently it doesn't go into the sliderTapped() function.

我认为这应该有用,但没有运气。然后我尝试在尝试将“A”打印到日志时进行调试,但它显然没有进入sliderTapped()函数。

What am I doing wrong? Or is there a better way to achieve what I am trying to achieve?

我究竟做错了什么?或者有更好的方法来实现我想要实现的目标吗?

5 个解决方案

#1


21  

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.

看起来您需要根据上面的代码示例在viewDidLoad()中实际初始化点击手势识别器。那里有评论,但我没有看到识别器在任何地方被创建。

Swift 2:

斯威夫特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:

斯威夫特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


17  

It seems like just subclassing UISlider and returning always true to the beginTracking produce the desired effect.

它似乎只是继承UISlider并返回始终为true的beginTrackin*生所需的效果。

iOS 10 and Swift 3

iOS 10和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.

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

#3


1  

This is my code, based on "myuiviews" answer.
I fixed 2 little "bugs" of the original code.

这是我的代码,基于“myuiviews”的回答。我修复了原始代码的两个小“错误”。

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.

1 - 点击0太难了,所以我让它变得更容易2 - 滑动滑块的拇指稍微滑动了一下“tapGestureRecognizer”,这使它返回到初始位置,所以我添加了一个最小距离滤镜以避免那。

Swift 4

斯威夫特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)
    }
}

#4


0  

pteofil's answer should be the accepted answer here.

pteofil的回答应该是这里接受的答案。

Below is the solution for Xamarin for everyone's interested:

以下是每个人感兴趣的Xamarin解决方案:

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

As pteofil mentioned, you need to subclass the UISlider for this to work.

正如pteofil所提到的,你需要为UISlider创建子类以使其工作。

#5


0  

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.

一旦手指离开手机屏幕,就会调用此功能。

#1


21  

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.

看起来您需要根据上面的代码示例在viewDidLoad()中实际初始化点击手势识别器。那里有评论,但我没有看到识别器在任何地方被创建。

Swift 2:

斯威夫特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:

斯威夫特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


17  

It seems like just subclassing UISlider and returning always true to the beginTracking produce the desired effect.

它似乎只是继承UISlider并返回始终为true的beginTrackin*生所需的效果。

iOS 10 and Swift 3

iOS 10和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.

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

#3


1  

This is my code, based on "myuiviews" answer.
I fixed 2 little "bugs" of the original code.

这是我的代码,基于“myuiviews”的回答。我修复了原始代码的两个小“错误”。

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.

1 - 点击0太难了,所以我让它变得更容易2 - 滑动滑块的拇指稍微滑动了一下“tapGestureRecognizer”,这使它返回到初始位置,所以我添加了一个最小距离滤镜以避免那。

Swift 4

斯威夫特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)
    }
}

#4


0  

pteofil's answer should be the accepted answer here.

pteofil的回答应该是这里接受的答案。

Below is the solution for Xamarin for everyone's interested:

以下是每个人感兴趣的Xamarin解决方案:

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

As pteofil mentioned, you need to subclass the UISlider for this to work.

正如pteofil所提到的,你需要为UISlider创建子类以使其工作。

#5


0  

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.

一旦手指离开手机屏幕,就会调用此功能。