【问题标题】:iPhone : How to detect the end of slider drag?iPhone:如何检测滑块拖动的结束?
【发布时间】:2012-03-12 12:22:08
【问题描述】:

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

【问题讨论】:

  • 使用:[slider addTarget:self action:@selector(sliderStoppedDragging:) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchUpOutside];
  • 是的!谢谢!

标签: ios iphone ios5 ios4 uislider


【解决方案1】:

如果你在拖动之间不需要任何数据,那么你应该简单地设置:

[mySlider setContinuous: NO];

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

Swift 5 版本:

mySlider.isContinuous = false

【讨论】:

  • 这是这个问题的最佳答案。我希望我们可以改变这个答案。
  • i.imgur.com/0Edd2xe.png?1 XCode 版本 6.x 具有通过 IDE 本身设置 setContinuous 的功能。
  • 是的,最好的答案是这个。
  • 很好的答案。这是 Swift 4 代码:self.mySlider.isContinuous = false
  • 这不是作者要问的。他想不停地滑,也想知道什么时候停止。
【解决方案2】:

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

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

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

【讨论】:

  • 完美运行!你从哪里得到它的来源?
  • 感谢@RoiMulia,我不记得我第一次看到它是在哪里,多年来我一直在滑块中使用它。我有时会用它来忽略 UITouchPhaseEnded 上的变化,因为当用户抬起手指时,该值往往会跳跃。
  • 记得在你的UISlider中设置isContinuous = true
  • 这是一个很好的解决方案,但是它有一个触摸取消的问题。尽管 touchEvent 枚举中有一个“已取消”事件,但在取消触摸时不会触发它。因此,我建议还为 Slider 中的 touchCancel 事件添加一个侦听器。这应该涵盖所有可能性。
  • 我看到有时灵态会继续:开始、静止、移动,但从未结束或取消。这对我的用例来说是有问题的,因为我希望每次交互都会结束或被取消。上面提到了修复:使用单独的触摸取消目标/操作。
【解决方案3】:

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

界面构建器:

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

【讨论】:

    【解决方案4】:

    由于UISliderUIControl 的子类,您可以为其UIControlEventTouchUpInside 设置目标和操作。

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

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

    触摸结束时会向您发送dragEndedForSlider: 消息。

    如果您想在您的 nib 中执行此操作,您可以按住 control 键单击滑块以获取其连接菜单,然后从“Touch Up Inside”套接字拖动到目标对象。

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

    【讨论】:

    • @rob mayoff 抱歉,您确实需要使用 UIControlEventTouchUpOutside。否则,当您完成拖动时,如果您的手指不在滑块上,则不会调用选择器。
    • 自从我写下这个答案后,UISlider 的行为发生了变化。
    • 可以确认您确实还需要在 iOS 9 中为 UIControlEventTouchUpOutside 注册一个处理程序。
    • 我无法在 iOS 9 中调用 UIControlEventTouchCancel 处理程序。但我只能调用 UIControlEventTouchUpInsideUIControlEventTouchUpOutside
    • 上面采用两个参数的答案在 Catalyst 中不起作用。在那里看到我的评论。不过,这个答案确实如此。
    【解决方案5】:

    斯威夫特 5 和斯威夫特 4

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

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

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

    【讨论】:

    • 你好。开始拖动时如何暂停视频?
    • 这并不检测是否发生了拖动,只需轻按而不拖动即可触发。
    【解决方案6】:

    你可以使用:

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

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

    【讨论】:

      【解决方案7】:

      我认为你需要控制事件UIControlEventTouchUpInside

      【讨论】:

        【解决方案8】:

        斯威夫特 3 答案

        我遇到了同样的问题,最终解决了这个问题,所以也许它会对某人有所帮助。将 your_Slider 连接到情节提要中的“Value Changed”,当滑块移动时“Slider Touched”动作以及松开“Slider Released”时。

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

        【讨论】:

        • 很好的解决方案,但要小心,因为在开始拖动 结束拖动时会调用 Slider Released
        • 在发布时有时不称为“滑块已发布”
        【解决方案9】:

        连接Touch Up InsideValue Changed

        【讨论】:

          【解决方案10】:

          斯威夫特 3.1

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

          为此,我在上面使用滑块的 isTracking 属性扩展了 Andy 的答案。我需要记录两个状态: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
            }
          }
          

          【讨论】:

            【解决方案11】:

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

            【讨论】:

              【解决方案12】:

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

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

              【讨论】:

                【解决方案13】:

                我最近有类似的问题。这是我在 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 即可满足您的要求。

                【讨论】:

                  【解决方案14】:

                  RxSwift:

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

                  【讨论】:

                    【解决方案15】:

                    这样试试

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

                    【讨论】:

                    • 每次滑块的拇指移动时发送动作,而不仅仅是在拖动结束时。
                    【解决方案16】:

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

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

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2019-08-12
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多