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


94

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


1
使用:[slider addTarget:self操作:@selector(sliderStoppedDragging :) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
亨利·苏

Answers:


171

如果拖动之间不需要任何数据,则只需设置即可:

[mySlider setContinuous: NO];

这样您将收到 valueChanged仅当用户停止移动滑块时,事件。

Swift 5版本:

mySlider.isContinuous = false

2
这是对这个问题的最佳答案。我希望我们可以改变答案。
M. Porooshani 2015年

1
i.imgur.com/0Edd2xe.png?1 XCode版本6.x具有通过IDE本身设置setContinuous的功能。
Abhijeet 2015年

1
是的,最好的答案是这个。
sabiland '16

1
Xcode 7.3 Interface Builder具有Events [x] Continuous UpdatesUISliderView的设置。取消选中此设置continuous为false / NO。
leanne

3
好答案。这是Swift 4代码:self.mySlider.isContinuous = false
Marco Weber

115

您可以为UIControlEventValueChanged 添加一个带有两个参数的操作,即发送者和事件:

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

然后在处理程序中检查touch对象的阶段:

- (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;
    }
}

斯威夫特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中添加动作时,您还可以选择将发送者和事件参数都添加到动作中。


1
完美的作品!您是从哪里获得资源的?
罗伊·穆利亚

2
谢谢@RoiMulia,我不记得我第一次看到它了,我已经在滑块中使用了很多年了。有时我会用它来忽略UITouchPhaseEnded上的更改,因为当用户抬起手指时该值往往会跳跃。
Devin Pitcher

2
请记住设置isContinuous = true您的UISlider
krlbsk17年

2
这是一个很好的解决方案,但是它具有取消触摸的问题。尽管touchEvent枚举中存在“已取消”事件,但在取消触摸时不会触发该事件。因此,我建议您还为Slider中的touchCancel事件添加一个侦听器。这应该涵盖所有可能性。
bnussey

2
我看到有时阶段可以进行:开始,静止,移动,但从未结束也没有取消。这对于我的用例来说是有问题的,因为我希望每次交互都将结束或被取消。上面已指出了解决方法:使用单独的触摸取消目标/操作。
约旦H

71

我使用“内部润饰”和“外部润饰”通知。

界面生成器:

将Interface Builder中的两个通知都连接到您的接收方法。该方法可能如下所示:

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

在代码中:

如果要以编程方式进行连接,则在viewWillAppear中(或任何适合您的位置)都会有这样的调用:

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

接收方法如下所示:

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

19

由于UISlider是的子类UIControl,因此可以为其设置目标和操作UIControlEventTouchUpInside

如果要在代码中执行此操作,则如下所示:

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

那会给你一个 dragEndedForSlider:触摸结束后,消息。

如果要在笔尖中执行此操作,则可以按住Control键并单击并单击滑块以获取其连接菜单,然后将其从“ Touch Up Inside”插槽中拖到目标对象。

您还应该为UIControlEventTouchUpOutside和添加目标和操作UIControlEventTouchCancel


1
@rob mayoff对不起,但您确实需要使用UIControlEventTouchUpUpside。否则,完成拖动后,如果手指不在滑块上,则不会调用选择器。
user3164248'4

2
UISlider自从我撰写此答案以来,的行为已经改变。
rob mayoff 2015年

可以确认的是,你也需要在iOS的9注册一个处理器UIControlEventTouchUpOutside
LMS

我从未能够UIControlEventTouchCancel在iOS 9中调用处理程序。但是我只能UIControlEventTouchUpInside并且UIControlEventTouchUpOutside只能调用。
petrsyn

17

Swift 5和Swift 4

  1. touchUpInsidetouchUpOutside事件添加目标。您可以以编程方式或从情节提要中进行操作。这是您以编程方式进行的方式

    slider.addTarget(self, action: #selector(sliderDidEndSliding), for: [.touchUpInside, .touchUpOutside])
  2. 编写函数以处理滑块拖动的结束

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

你好。开始拖动时如何暂停视频?
kemdo

这不会检测到是否曾经发生过拖动,而只需轻按而不拖动即可触发。
Chewie The Chorkie

9

您可以使用:

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

检测UISlider中何时发生touchDown和touchUp事件



5

斯威夫特3答案

我遇到了同样的问题,最终使它起作用,所以也许它将对某人有所帮助。将your_Slider连接到情节提要中的“值已更改”,并且当滑块移动“ Slider Touched”时动作,而放开“ Slider Released”时。

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

2
好的解决方案,但要小心,因为在开始拖动结束拖动时会调用Slider Released
Guy Daher

有时在发行时不被称为“滑块发行”
Vadim


4

斯威夫特3.1

有时,您可能希望滑块的拖动事件连续触发,但是可以选择执行不同的代码,具体取决于滑块是被拖动还是刚刚被拖动。

为此,我在上面的Andy答案中进行了扩展,该答案利用了Slider的isTracking属性。我需要记录两个状态:sliderHasFinishedTrackingsliderLastStoredValue

我的代码正确:

  • 开始拖动时不会触发动作

  • 如果用户仅轻按一下滑块(表示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
  }
}

4

在Swift 4中,您可以使用此功能

1个第一个步骤:-在滑块中添加目标

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

2第二步:-创建一个函数

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

2

也许您应该为UIControlEventTouchUpInside,UIControlEventTouchUpOutside,UIControlEventTouchCancel事件添加目标。

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


1

我最近有类似的问题。这是我在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

默认值似乎是“是”(true)。将其设置为false即可完成所需的操作。


0

这样尝试

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

每当滑块的拇指移动时,就会发送动作,而不仅仅是拖动结束时。
rob mayoff 2012年


0

为滑块创建一个动作和出口(或者您可以从动作到UISlider键入发送者),然后在UI中取消选中“持续更新”复选框。这样,仅当滑块停止拖动时,我们才能获取滑块值。

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

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.