IPhone: 如何检测滑块拖动的结束?

如何检测事件时,用户已结束拖动的滑块指针?

77872 次浏览

你可使用:

- (void)addTarget:(id)target action:(SEL)action
forControlEvents:(UIControlEvents)controlEvents

检测 UISlider 中触摸到和触摸到事件何时发生

试试这样

customSlider.minimumValue = 0.0;
customSlider.maximumValue = 10.0;
[customSlider addTarget:self action:@selector(changeSlider:) forControlEvents:UIControlEventValueChanged];




-(void)changeSlider:(id)sender{
UISlider *slider=(UISlider *)sender;
float sliderValue=(float)(slider.value );
NSLog(@"sliderValue = %f",sliderValue);
}

因为 UISliderUIControl的一个子类,所以您可以为它的 UIControlEventTouchUpInside设置一个目标和操作。

如果你想用代码来做,它看起来像这样:

[self.slider addTarget:self action:@selector(dragEndedForSlider:)
forControlEvents:UIControlEventTouchUpInside];

当触摸结束时,它将向您发送 dragEndedForSlider:消息。

如果你想在你的笔尖做到这一点,你可以控制-点击你的滑块得到它的连接菜单,然后从“内部触摸”插座拖动到目标对象。

您还应该为 UIControlEventTouchUpOutsideUIControlEventTouchCancel添加一个目标和操作。

我认为你需要控制事件 UIControlEventTouchUpInside

如果在拖动之间不需要任何数据,那么只需设置:

[mySlider setContinuous: NO];

这样,只有当用户停止移动滑块时,才会接收到 valueChanged事件。

Swift 5 版本:

mySlider.isContinuous = false

I use the "Touch Up Inside" and "Touch up outside" notifications.

Interface Builder

将 Interface Builder 中的两个通知连接到接收方法,该方法可以如下所示:

- (IBAction)lengthSliderDidEndSliding:(id)sender {
NSLog(@"Slider did end sliding... Do your stuff here");
}

代码:

If you want to wire it programatically you would have something like this in your viewWillAppear (or wherever it fits you) call:

[_mySlider addTarget:self
action:@selector(sliderDidEndSliding:)
forControlEvents:(UIControlEventTouchUpInside | UIControlEventTouchUpOutside)];

The receiving method would look like this:

- (void)sliderDidEndSliding:(NSNotification *)notification {
NSLog(@"Slider did end sliding... Do your stuff here");
}

我最近也遇到过类似的问题,以下是我在 Swift 中的做法:

    theSlider.continuous = false;

保存此连续值的代码如下:

public var continuous: Bool // if set, value change events are generated
// any time the value changes due to dragging. default = YES

默认值似乎是 YES (true)。将其设置为 false 可以实现您想要的效果。

您可以为 UIControlEventValueChanged 添加一个操作,该操作接受 参数、 sender 和事件:

[slider addTarget:self action:@selector(onSliderValChanged:forEvent:) forControlEvents:UIControlEventValueChanged]

然后检查触摸对象在处理程序中的相位:

- (void)onSliderValChanged:(UISlider*)slider forEvent:(UIEvent*)event {
UITouch *touchEvent = [[event allTouches] anyObject];
switch (touchEvent.phase) {
case UITouchPhaseBegan:
// handle drag began
break;
case UITouchPhaseMoved:
// handle drag moved
break;
case UITouchPhaseEnded:
// handle drag ended
break;
default:
break;
}
}

Swift 4 & 5

slider.addTarget(self, action: #selector(onSliderValChanged(slider:event:)), for: .valueChanged)
@objc func onSliderValChanged(slider: UISlider, event: UIEvent) {
if let touchEvent = event.allTouches?.first {
switch touchEvent.phase {
case .began:
// handle drag began
case .moved:
// handle drag moved
case .ended:
// handle drag ended
default:
break
}
}
}

请注意,在添加操作时,Interface Builder 还可以选择将 sender 和 event 参数都添加到操作中。

连接 Touch Up InsideValue Changed

enter image description here

快速3答案

我也遇到过同样的问题,最终还是成功了,所以也许能帮到别人。将你的滑块连接到故事板中的“价值改变”,当滑块移动时“滑块触摸”动作,当放开时“滑块释放”。

@IBAction func your_Slider(_ sender: UISlider) {
if (yourSlider.isTracking) {
print("Slider Touched")
} else {
print("Slider Released")
}
}

Swift 5和 Swift 4

  1. Add target for touchUpInside and touchUpOutside events. You can do it either programatically or from storyboard. This is how you do it programatically

    slider.addTarget(self, action: #selector(sliderDidEndSliding), for: [.touchUpInside, .touchUpOutside])
    
  2. Write your function to handle the end of slider drag

    func sliderDidEndSliding() {
    print("end sliding")
    }
    

Swift 3.1

有时,您希望滑块的拖动事件连续触发,但是可以选择执行不同的代码,这取决于滑块是否仍在被拖动或者刚刚被拖动完毕。

为了做到这一点,我已经扩展了上面 Andy 的答案,它利用了滑块的 isTracking属性。我需要记录两种状态: sliderHasFinishedTrackingsliderLastStoredValue

我的代码是正确的:

  • doesn't fire an action upon starting drag

  • 如果用户只是轻轻一点滑块(意味着 isTracking仍然是 false) ,就会触发操作


class SliderExample: UIViewController {
var slider: UISlider = UISlider()
var sliderHasFinishedTracking: Bool = true
var sliderLastStoredValue: Float!


override func loadView() {
super.loadView()


slider.minimumValue = 100.0
slider.maximumValue = 200.0
slider.isContinuous = true
slider.value = 100.0
self.sliderLastStoredValue = slider.value
slider.addTarget(self, action: #selector(respondToSlideEvents), for: .valueChanged)
// add your slider to the view however you like
}


func respondToSlideEvents(sender: UISlider) {
let currentValue: Float = Float(sender.value)
print("Event fired. Current value for slider: \(currentValue)%.")


if(slider.isTracking) {
self.sliderHasFinishedTracking = false
print("Action while the slider is being dragged ⏳")
} else {
if(self.sliderHasFinishedTracking && currentValue == self.sliderLastStoredValue){
print("Slider has finished tracking and its value hasn't changed, " +
"yet event was fired anyway. 🤷") // No need to take action.
} else {
self.sliderHasFinishedTracking = true
print("Action upon slider drag/tap finishing ⌛️")
}
}


self.sliderLastStoredValue = currentValue
}
}

也许你应该为 UIControlEventTouchUpInside、 UIControlEventTouchUpOut、 UIControlEventTouchCancel 事件添加目标。

我以前遇到过同样的问题,因为我没有为 UIControlEventTouchCancel事件添加目标。

在 Swift 4中你可以使用这个函数

第一步: 在滑块中添加目标

self.distanceSlider.addTarget(self, action: #selector(self.sliderDidEndSliding(notification:)), for: ([.touchUpInside,.touchUpOutside]))

第二步:-创建一个函数

@objc func sliderDidEndSliding(notification: NSNotification)
{
print("Hello-->\(distanceSlider.value)")
}

RxSwift:

self.slider.rx.controlEvent([.touchUpInside, .touchUpOutside])
.bind(to: self.viewModel.endSlidingSlider)
.disposed(by: self.disposeBag)

为滑块创建一个操作和出口(或者您可以将发件人从操作类型转换为 UISlider) ,并在 UI 中取消选中“连续更新”复选框。这样,只有当滑块停止拖动时,我们才能得到滑块值。

@IBAction func actionSlider(_ sender: Any) {
let value = sliderSpeed.value.rounded()
}

enter image description here