iPhone:スライダーのドラッグの終わりを検出する方法は?


94

ユーザーがスライダーポインターのドラッグを終了したときにイベントを検出する方法


1
使用:[slider addTarget:self action:@selector(sliderStoppedDragging :) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
Henry Sou

回答:


171

ドラッグの間にデータが必要ない場合は、単に設定する必要があります。

[mySlider setContinuous: NO];

この方法ではvalueChanged、ユーザーがスライダーの移動を停止したときにのみイベントを受け取ります。

Swift 5バージョン:

mySlider.isContinuous = false

2
これがこの質問に対する最良の答えです。これに対する答えを変えられたらいいのに。
M. Porooshani

1
i.imgur.com/0Edd2xe.png?1 XCodeバージョン6.xには、IDE自体を介してsetContinuousを設定するこの機能があります。
Abhijeet

1
はい、最良の答えはこれです。
サビランド

1
Xcode 7.3 Interface BuilderにはEvents [x] Continuous UpdatesUISliderViewの設定があります。これをオフにするcontinuousと、false / NOに設定されます。
リーンリーン

3
素晴らしい答え。ここでスウィフト4コードは次のとおりです。self.mySlider.isContinuous = false
マルコ・ウェーバー

115

UIControlEventValueChangedの送信者とイベントの2つのパラメーターを取るアクションを追加できます。

[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でアクションを追加するときに、アクションに送信者パラメーターとイベントパラメーターの両方を追加するオプションもあります。


1
完璧に動作します!そのソースをどこで手に入れましたか?
Roi Mulia

2
@RoiMuliaのおかげで、最初にどこで見たのか覚えていません。スライダーで何年も使用しています。ユーザーが指を離すと値がジャンプする傾向があるため、UITouchPhaseEndedの変更を無視するために使用することがあります。
Devin Pitcher

2
を設定isContinuous = trueすることを忘れないでくださいUISlider
krlbsk 2017

2
これは優れたソリューションですが、タッチキャンセルに問題があります。touchEvent列挙型には「キャンセルされた」イベントがありますが、タッチがキャンセルされてもイベントは発生しません。したがって、スライダーからtouchCancelイベントのリスナーを追加することもお勧めします。これはすべての可能性をカバーするはずです。
bnussey

2
私は時々フェーズが進むことができるのを見ました:始まった、静止した、動かされた、しかしその後決して終わらなかった、またはキャンセルされた。すべての対話が終了またはキャンセルされることを期待していたので、これは私のユースケースにとって問題です。修正は上記のとおりです。個別のタッチキャンセルターゲット/アクションを使用してください。
ジョーダンH

71

「Touch Up Inside」と「Touch up Outside」の通知を使用します。

インターフェイスビルダー:

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:タッチが終了するとメッセージが送信されます。

ペン先で行う場合は、スライダーをコントロールクリックして接続メニューを表示し、「Touch Up Inside」ソケットからターゲットオブジェクトにドラッグします。

あなたはまたのためのターゲットとアクションを追加しなければならないUIControlEventTouchUpOutsideとのためにUIControlEventTouchCancel


1
@rob mayoff申し訳ありませんが、UIControlEventTouchUpOutsideを使用する必要があります。それ以外の場合、ドラッグが終了したときに指がスライダー上にない場合、セレクターは呼び出されません。
user3164248 2015

2
UISliderこの回答を書いてから、の動作が変わりました。
rob mayoff 2015

あなたがいることを確認することができないものiOS 9にUIControlEventTouchUpOutsideのためのハンドラを登録する必要があります
LMS

私は呼び出すことができなかったUIControlEventTouchCancelのiOS 9にハンドラしかし、私は呼び出すことができるよUIControlEventTouchUpInsideUIControlEventTouchUpOutsideだけ。
petrsyn 2016

17

Swift 5およびSwift 4

  1. イベントのターゲットを追加touchUpInsidetouchUpOutsideます。プログラムで、またはストーリーボードから実行できます。これはプログラムで行う方法です

    slider.addTarget(self, action: #selector(sliderDidEndSliding), for: [.touchUpInside, .touchUpOutside])
  2. スライダードラッグの終了を処理する関数を記述します

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

こんにちは。ドラッグを開始するときにビデオを一時停止するにはどうすればよいですか?
kemdo 2018

これは、必ずしもドラッグが発生したかどうかを検出せず、ドラッグせずにタップするだけでトリガーできます。
Chewie The Chorkie

9

以下を使用できます。

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

UISliderでtouchDownおよびtouchUpイベントが発生したことを検出する



5

スウィフト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")
    }
}

2
良い解決策ですが、ドラッグ開始してドラッグ終了するとSlider Releasedが呼び出されるため注意が必要です
Guy Daher

リリース時に「スライダーリリース済み」と呼ばれないこともあります
Vadim


4

Swift 3.1

スライダーのドラッグイベントを継続的に発生させたい場合がありますが、スライダーがまだドラッグされているか、ドラッグが終了した直後かによって、異なるコードを実行するオプションがあります。

これを行うために、スライダーのisTrackingプロパティを利用する上記のアンディの答えを拡張しました。との2つの状態を記録する必要がsliderHasFinishedTrackingありましたsliderLastStoredValue

私のコードは正しく:

  • ドラッグ開始時にアクションを起動しません

  • ユーザーが1回のタップでスライダーを動かしただけの場合にアクションを起動します(つまり、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 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

デフォルトは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

0

RxSwift:

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

0

スライダーのアクションとアウトレットを作成し(またはアクションからUISliderに送信者をタイプキャストできます)、UIで[継続的な更新]チェックボックスをオフにします。このようにして、スライダーがドラッグを停止したときにのみスライダー値を取得します。

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

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.